chartContextMenu.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import { mapMutations, mapState } from 'vuex'
  2. import cloneDeep from 'lodash/cloneDeep'
  3. import { toJpeg, toPng } from 'html-to-image'
  4. import isEmpty from 'lodash/isEmpty'
  5. import { randomString } from 'data-room-ui/js/utils'
  6. import Contextmenu from 'vue-contextmenujs'
  7. import Vue from 'vue'
  8. Vue.use(Contextmenu)
  9. export default {
  10. computed: {
  11. ...mapState({
  12. activeCode: state => state.bigScreen.activeCode,
  13. activeCodes: state => state.bigScreen.activeCodes,
  14. hoverCode: state => state.bigScreen.hoverCode,
  15. activeItemConfig: state => state.bigScreen.activeItemConfig,
  16. chartList: state => state.bigScreen.pageInfo.chartList,
  17. presetLine: state => state.bigScreen.presetLine
  18. })
  19. },
  20. data () {
  21. return {}
  22. },
  23. mounted () {
  24. },
  25. methods: {
  26. ...mapMutations('bigScreen', ['changeHoverCode', 'changeActiveCode', 'changeChartConfig', 'addItem', 'delItem', 'resetPresetLine', 'changeLayout', 'changeZIndex', 'changeLocked', 'saveTimeLine', 'copyCharts', 'pasteCharts', 'clearActiveCodes']), // 改变hover的组件
  27. changeHover (code) {
  28. this.changeHoverCode(code)
  29. }, // 改变激活的组件
  30. changeActive (code) {
  31. this.changeActiveCode(code)
  32. }, // 打开右侧面板
  33. openRightPanel (config) {
  34. this.changeActiveCode(config.code)
  35. this.$emit('openRightPanel', config)
  36. }, // 查看数据
  37. dataView (config) {
  38. this.changeActiveCode(config.code)
  39. this.$emit('openDataViewDialog', config)
  40. }, // 复制组件
  41. copyItem (config) {
  42. const newConfig = cloneDeep(config)
  43. newConfig.code = randomString(8)
  44. newConfig.title = newConfig.title + '_副本'
  45. // 区分是从左侧添加还是复制的组件
  46. newConfig.isCopy = true
  47. newConfig.x = config.x + 20
  48. newConfig.y = config.y + 20
  49. if (config.group) {
  50. newConfig.group = 'copy_' + config.group
  51. }
  52. this.addItem(newConfig)
  53. }, // 删除单个组件
  54. deleteItem (config) {
  55. this.$confirm('确定删除该组件吗?', '提示', {
  56. confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', customClass: 'bs-el-message-box'
  57. }).then(() => {
  58. this.delItem(config.code)
  59. })
  60. }, // 批量删除组合元素
  61. deleteGroupItem (config) {
  62. this.$confirm('确定批量删除选中的组件吗?', '提示', {
  63. confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', customClass: 'bs-el-message-box'
  64. }).then(() => {
  65. // 找到和本组件group相同的组件 删除
  66. const codes = this.chartList.filter(_chart => _chart.group === config.group && config.group).map(_chart => _chart.code)
  67. if (!isEmpty(codes)) {
  68. this.delItem(codes)
  69. } else {
  70. this.delItem(config.code)
  71. }
  72. })
  73. }, // 获取组件的坐标字符串,取整 (100, 100)
  74. getPoint ({ x, y }) {
  75. return `(${Math.round(x)}, ${Math.round(y)})`
  76. }, // 组合/取消组合图表
  77. groupChart (chart) {
  78. if (!chart.group || chart.group === 'tempGroup') {
  79. // 添加组合
  80. // eslint-disable-next-line no-unused-expressions
  81. this.activeCodes?.forEach(code => {
  82. const config = this.chartList.find(item => item.code === code)
  83. this.changeChartConfig({
  84. ...config, group: `group_${chart.code}`
  85. })
  86. })
  87. this.saveTimeLine('组合图表')
  88. } else {
  89. // 取消组合
  90. this.clearActiveCodes()
  91. // 找到和本组件group相同的组件 取消group
  92. this.chartList.forEach(_chart => {
  93. if (_chart.group === chart.group) {
  94. this.changeChartConfig({
  95. ..._chart, group: ''
  96. })
  97. }
  98. })
  99. this.saveTimeLine('取消组合图表')
  100. }
  101. }, // 生成图片
  102. generateImage (chart) {
  103. let componentDom = document.querySelector(`#${chart.code} .render-item-wrap`)
  104. if (this.isPreview) {
  105. componentDom = document.querySelector(`#${chart.code}`)
  106. }
  107. toPng(componentDom)
  108. .then((dataUrl) => {
  109. const link = document.createElement('a')
  110. link.download = `${chart.title}.png`
  111. link.href = dataUrl
  112. link.click()
  113. link.addEventListener('click', () => {
  114. link.remove()
  115. })
  116. })
  117. }, // 右键菜单
  118. onContextmenu (event, chart) {
  119. const isHidden = !chart?.option?.displayOption?.dataAllocation?.enable
  120. event.preventDefault()
  121. if (this.isPreview) {
  122. this.$contextmenu({
  123. items: [{
  124. label: '查看数据',
  125. icon: 'el-icon-view',
  126. hidden: isHidden,
  127. onClick: () => {
  128. this.dataView(chart)
  129. }
  130. },
  131. {
  132. label: '生成图片',
  133. icon: 'el-icon-download',
  134. hidden: isHidden,
  135. onClick: () => {
  136. this.generateImage(chart)
  137. }
  138. }],
  139. event, // 鼠标事件信息
  140. customClass: 'bs-context-menu-class', // 自定义菜单 class
  141. zIndex: 999, // 菜单样式 z-index
  142. minWidth: 150 // 主菜单最小宽度
  143. })
  144. } else {
  145. this.$contextmenu({
  146. items: [{
  147. label: '配置',
  148. icon: 'el-icon-setting',
  149. onClick: () => {
  150. this.openRightPanel(chart)
  151. }
  152. }, {
  153. label: '删除',
  154. icon: 'el-icon-delete',
  155. onClick: () => {
  156. this.deleteItem(chart)
  157. }
  158. }, {
  159. label: '批量删除',
  160. icon: 'el-icon-delete',
  161. onClick: () => {
  162. this.deleteGroupItem(chart)
  163. }
  164. }, {
  165. label: '复制',
  166. icon: 'el-icon-copy-document',
  167. onClick: () => {
  168. this.copyItem(chart)
  169. }
  170. }, {
  171. label: '组合复制',
  172. icon: 'el-icon-copy-document',
  173. onClick: () => {
  174. this.copyCharts()
  175. this.pasteCharts()
  176. }
  177. }, {
  178. label: '置于顶层',
  179. icon: 'el-icon-arrow-up',
  180. onClick: () => {
  181. let chartList = cloneDeep(this.chartList)
  182. // 将当前图表置底
  183. chartList = chartList.filter(item => item.code !== chart.code)
  184. chartList.unshift(chart)
  185. this.changeLayout(chartList)
  186. this.changeZIndex(chartList)
  187. }
  188. }, {
  189. label: '置于底层',
  190. icon: 'el-icon-arrow-down',
  191. onClick: () => {
  192. let chartList = cloneDeep(this.chartList)
  193. // 将当前图表置顶
  194. chartList = chartList.filter(item => item.code !== chart.code)
  195. chartList.push(chart)
  196. this.changeLayout(chartList)
  197. this.changeZIndex(chartList)
  198. }
  199. }, {
  200. label: chart.locked ? '解锁' : '锁定',
  201. icon: chart.locked ? 'el-icon-unlock' : 'el-icon-lock',
  202. onClick: () => {
  203. this.changeLocked(chart)
  204. }
  205. }, {
  206. label: (chart.group && chart.group !== 'tempGroup') ? '取消组合' : '组合',
  207. icon: (chart.group && chart.group !== 'tempGroup') ? 'iconfont-bigscreen icon-quxiaoguanlian' : 'iconfont-bigscreen icon-zuhe',
  208. onClick: () => {
  209. this.groupChart(chart)
  210. }
  211. }, {
  212. label: '查看数据',
  213. icon: 'el-icon-view',
  214. hidden: isHidden,
  215. onClick: () => {
  216. this.dataView(chart)
  217. }
  218. }, {
  219. label: '生成图片',
  220. icon: 'el-icon-download',
  221. onClick: () => {
  222. this.generateImage(chart)
  223. }
  224. }],
  225. event, // 鼠标事件信息
  226. customClass: 'bs-context-menu-class', // 自定义菜单 class
  227. zIndex: 999, // 菜单样式 z-index
  228. minWidth: 150 // 主菜单最小宽度
  229. })
  230. }
  231. return false
  232. }
  233. }
  234. }