From 1115de732c0acf3d09f67279e9ea2004e14c16d4 Mon Sep 17 00:00:00 2001
From: "liu.shiyi" <liu.shiyi@ustcinfo.com>
Date: Tue, 27 Jun 2023 17:59:37 +0800
Subject: [PATCH] =?UTF-8?q?feat:g2plot=E4=BB=A3=E7=A0=81=E9=87=8D=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../BigScreenDesign/PageDesignTop.vue         |   1 -
 .../BigScreenDesign/RightSetting/index.vue    |  21 ++-
 .../packages/BigScreenDesign/index.vue        |  18 +-
 data-room-ui/packages/PlotRender/index.vue    | 141 ++++++--------
 .../packages/js/mixins/commonMixins.js        | 177 +++++-------------
 5 files changed, 127 insertions(+), 231 deletions(-)

diff --git a/data-room-ui/packages/BigScreenDesign/PageDesignTop.vue b/data-room-ui/packages/BigScreenDesign/PageDesignTop.vue
index 6ede304a..9fb88363 100644
--- a/data-room-ui/packages/BigScreenDesign/PageDesignTop.vue
+++ b/data-room-ui/packages/BigScreenDesign/PageDesignTop.vue
@@ -199,7 +199,6 @@ export default {
       saveTimeLine: 'bigScreen/saveTimeLine'
     }),
     setAlign (command) {
-      debugger
       const pageInfo = _.cloneDeep(this.pageInfo)
       // 获取所有选中的组件
       let activeChartList = pageInfo.chartList.filter((chart) => {
diff --git a/data-room-ui/packages/BigScreenDesign/RightSetting/index.vue b/data-room-ui/packages/BigScreenDesign/RightSetting/index.vue
index d4917a71..13386c95 100644
--- a/data-room-ui/packages/BigScreenDesign/RightSetting/index.vue
+++ b/data-room-ui/packages/BigScreenDesign/RightSetting/index.vue
@@ -51,6 +51,7 @@ import rightSetting from 'packages/js/utils/rightSettingImport'
 import CustomComponent from './G2CustomSetting.vue'
 import Svgs from 'packages/Svgs/setting.vue'
 import { mapState, mapMutations } from 'vuex'
+import _ from 'lodash'
 // 整体动态导入右侧设置组件,不用手动注册
 const components = {}
 for (const key in rightSetting) {
@@ -86,23 +87,23 @@ export default {
     },
     configDataSource () {
       return {
-        dataSource: this.config.dataSource,
-        linkage: this.config?.linkage,
+        dataSource: _.cloneDeep(this.config.dataSource),
+        linkage: _.cloneDeep(this.config?.linkage),
         dataHandler: this.config?.dataHandler,
-        dataSourceSetting: this.config?.setting?.filter(item => item.tabName === 'data') || []
+        dataSourceSetting: _.cloneDeep(this.config?.setting?.filter(item => item.tabName === 'data')) || []
       }
     },
     configStyle () {
       return {
         showTitle: this.config.showTitle,
-        title: this.config?.title,
+        title: _.cloneDeep(this.config?.title),
         w: this.config?.w,
         h: this.config?.h,
         x: this.config?.x,
         y: this.config?.y,
         z: this.config?.z,
-        setting: this.config?.setting,
-        customize: this.config?.customize,
+        setting: _.cloneDeep(this.config?.setting),
+        customize: _.cloneDeep(this.config?.customize),
         url: this.config?.url,
         dateFormat: this.config?.dateFormat,
         endTime: this.config?.endTime
@@ -112,8 +113,8 @@ export default {
   watch: {
     // 只更新样式部分,不调用接口
     configStyle: {
-      handler (val) {
-        if (val) {
+      handler (val, oldValue) {
+        if (!_.isEqual(val, oldValue)) {
           this.$emit('updateSetting', this.config)
           this.saveTimeLine(`更新${val?.title}组件属性`)
         }
@@ -122,8 +123,8 @@ export default {
     },
     // 更新数据源部分,需要调用接口
     configDataSource: {
-      handler (val) {
-        if (val) {
+      handler (val, oldValue) {
+        if (!_.isEqual(val, oldValue)) {
           this.$emit('updateDataSetting', this.config)
           this.saveTimeLine(`更新${val?.title}组件属性`)
         }
diff --git a/data-room-ui/packages/BigScreenDesign/index.vue b/data-room-ui/packages/BigScreenDesign/index.vue
index df920494..54e9e129 100644
--- a/data-room-ui/packages/BigScreenDesign/index.vue
+++ b/data-room-ui/packages/BigScreenDesign/index.vue
@@ -383,20 +383,18 @@ export default {
     },
     // 自定义属性更新
     updateSetting (config) {
-      config.key = new Date().getTime()
+      if (config.type === 'map') {
+        config.key = new Date().getTime()
+      }
       this.changeChartConfig(_.cloneDeep(config))
+      this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[
+        config.code
+      ]?.changeStyle(_.cloneDeep(config))
     },
     // 动态属性更新
     updateDataSetting (config) {
-      if (
-        this.$refs.Render?.$refs['RenderCard' + config.code][0] &&
-        this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[config.code] &&
-        this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[config.code]?.updateChartData
-      ) {
-        this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[
-          config.code
-        ]?.updateChartData(_.cloneDeep(config))
-      }
+      config.key = new Date().getTime()
+      this.changeChartConfig(config)
     },
     onSelectArea (area) {
       const { startX, startY, endX, endY } = area
diff --git a/data-room-ui/packages/PlotRender/index.vue b/data-room-ui/packages/PlotRender/index.vue
index 20f89a70..d1bad219 100644
--- a/data-room-ui/packages/PlotRender/index.vue
+++ b/data-room-ui/packages/PlotRender/index.vue
@@ -59,7 +59,6 @@ export default {
     this.plotList = [...this.plotList, ...getCustomPlots()]
   },
   mounted () {
-    this.chartInit()
   },
   beforeDestroy () {
     if (this.chart) {
@@ -69,76 +68,37 @@ export default {
   methods: {
     ...mapMutations('bigScreen', ['changeChartConfig']),
     chartInit () {
-      // key和code相等,说明是一进来刷新,调用/chart/data/list
+      let config = this.config
+      // key和code相等,说明是一进来刷新,调用list接口
       if (this.config.code === this.config.key || this.isPreview) {
-        // 先给默认数据, 渲染出图表
-        const config = _.cloneDeep(this.config)
-        // config.option = plotList.find(plot => plot.name === config.name)?.option
-        this.newChart(config.option)
-
-        // 再根据数据更新组件
-        // this.updateChart()
-        this.updateData()
+        // 改变样式
+        config = this.changeStyle(config)
+        // 改变数据
+        this.changeDataByCode(config).then((res) => {
+          // 初始化图表
+          this.newChart(res)
+        }).catch(() => {})
       } else {
-        // 否则说明是更新或者复制
-        this.newChart(this.config.option)
+        // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
+        this.changeData(config).then((res) => {
+          // 初始化图表
+          this.newChart(res)
+        })
       }
     },
     /**
      * 构造chart
      */
-    newChart (option) {
-      this.chart = new g2Plot[this.config.chartType](this.chatId, {
+    newChart (config) {
+      this.chart = new g2Plot[config.chartType](this.chatId, {
         renderer: 'svg',
-        // 大屏缩放状态下,点击准确
+        // 仪表盘缩放状态下,点击准确
         supportCSSTransform: true,
-        ...option || this.config.option
+        ...config.option
       })
       this.chart.render()
       this.registerEvent()
     },
-    // 根据G2Plot组件配置的dataKey,将获取到的数据赋值给指定的dataKey
-    updateData () {
-      this.getCurrentOption().then(({ data, config }) => {
-        if (data.success) {
-          // 成功后更新数据
-          config = this.buildOption(config, data)
-          const dataKey = config.option.dataKey
-          // eslint-disable-next-line no-inner-declarations
-          function getValueFromOption (option, dataKey) {
-            try {
-              return eval('option.' + dataKey)
-            } catch (error) {
-              return undefined
-            }
-          }
-          const newData = getValueFromOption(config.option, dataKey)
-          if (this.chart) {
-            this.chart.changeData(newData)
-          }
-        }
-      })
-    },
-    /**
-     * 更新组件
-     */
-    // updateChart () {
-    //   if (this.isPreview) {
-    //     this.getCurrentOption().then(({ data, config }) => {
-    //       if (data.success) {
-    //         // 成功后更新数据
-    //         config = this.buildOption(config, data)
-    //         this.changeChartConfig(config)
-    //         this.chart.update(config.option)
-    //       } else {
-    //         config.option.data = this.plotList.find(plot => plot.name === config.name)?.option.data
-    //         this.chart.update(config.option)
-    //       }
-    //     })
-    //   } else {
-    //     this.updateChartData(this.config)
-    //   }
-    // },
     /**
      * 注册事件
      */
@@ -155,21 +115,17 @@ export default {
         this.linkage(formData)
       })
     },
-    /**
-     * 组件的配置
-     * @returns {Promise<unknown>}
-     */
-    buildOption (config, data) {
-      config = _.cloneDeep(config)
-      // 遍历config.setting,将config.setting中的值赋值给config.option中对应的optionField
+    // 将config.setting的配置转化为option里的配置,这里之所以将转化的方法提出来,是因为在改变维度指标和样式的时候都需要转化
+    transformSettingToOption (config, type) {
+      let option = null
       config.setting.forEach(set => {
         if (set.optionField) {
           const optionField = set.optionField.split('.')
-          let option = config.option
+          option = config.option
           optionField.forEach((field, index) => {
             if (index === optionField.length - 1) {
               // 数据配置时,必须有值才更新
-              if ((set.tabName === 'data' && set.value) || set.tabName === 'custom') {
+              if (set.tabName === type && set.value) {
                 option[field] = set.value
               }
             } else {
@@ -178,35 +134,50 @@ export default {
           })
         }
       })
-      // eslint-disable-next-line no-unused-vars
-      const option = config.option
-      // eslint-disable-next-line no-unused-vars
-      // const setting = config.setting
-      if (this.config.optionHandler) {
-        try {
-          // 此处函数处理config
-          eval(this.config.optionHandler)
-        } catch (e) {
-          console.error(e)
-        }
-      }
+      config.option = option
+      return config
+    },
+    dataFormatting (config, data) {
+      // 数据返回成功则赋值
       if (data.success) {
         data = data.data
-        if (this.config.dataHandler) {
+        config = this.transformSettingToOption(config, 'data')
+        // 获取到后端返回的数据,有则赋值
+        const option = config.option
+        const setting = config.setting
+        if (config.dataHandler) {
           try {
             // 此处函数处理data
-            eval(this.config.dataHandler)
+            eval(config.dataHandler)
           } catch (e) {
             console.error(e)
           }
         }
-        // eslint-disable-next-line no-undef
-        config.option = option
         config.option.data = data
       } else {
-        // 数据获取失败,使用前端配置中的默认数据
-        config.option.data = this.plotList?.find(plot => plot.name === this.config.name)?.option?.data
+        // 数据返回失败则赋前端的模拟数据
+        config.option.data = this.plotList?.find(plot => plot.name === config.name)?.option?.data
+      }
+      return config
+    },
+    // 组件的样式改变,返回改变后的config
+    changeStyle (config) {
+      config = this.transformSettingToOption(config, 'custom')
+      // 这里定义了option和setting是为了保证在执行eval时,optionHandler、dataHandler里面可能会用到,
+      const option = config.option
+      const setting = config.setting
+      if (this.config.optionHandler) {
+        try {
+          // 此处函数处理config
+          eval(this.config.optionHandler)
+        } catch (e) {
+          console.error(e)
+        }
+      }
+      if (this.chart) {
+        this.chart.update(config.option)
       }
+      this.changeChartConfig(config)
       return config
     }
   }
diff --git a/data-room-ui/packages/js/mixins/commonMixins.js b/data-room-ui/packages/js/mixins/commonMixins.js
index 9d9c47e6..c58a3126 100644
--- a/data-room-ui/packages/js/mixins/commonMixins.js
+++ b/data-room-ui/packages/js/mixins/commonMixins.js
@@ -37,72 +37,25 @@ export default {
      * 初始化组件
      */
     chartInit () {
-      // 初始化组件和数据,若自己的组件的初始化和数据处理不一样,可重写该方法
-      // 如果key和code相等,说明是一进来刷新,调用/chart/data/list,否则是更新,调用 chart/data/chart
-      // 或者是组件联动isLink,也需要调用/chart/data/list更新
-      if (this.config.code === this.config.key) {
-        // 根据缓存数据初始化的组件
-        if (this.config.dataSource.dataSetType === '2') {
-          this.config = this.buildOption(this.config, { success: false })
-          this.changeChartConfig(this.config)
-          this.newChart(this.config.option)
-        } else {
-          // 根据数据集初始化的组件
-          if (this.isPreview) {
-            this.getCurrentOption().then(({ config, data }) => {
-              config = this.buildOption(config, data)
-              this.changeChartConfig(config)
-              this.newChart(config.option)
-            })
-          } else {
-            this.updateChartData(this.config)
-          }
-        }
+      let config = this.config
+      // key和code相等,说明是一进来刷新,调用list接口
+      if (this.config.code === this.config.key || this.isPreview) {
+        // 改变样式
+        config = this.changeStyle(config) ? this.changeStyle(config) : config
+        // 改变数据
+        config = this.changeDataByCode(config)
       } else {
-        this.newChart(this.config.option)
-      }
-    },
-    // 组件仅更新数据
-    changeData () { },
-    // 组件仅更新样式
-    changeStyle () {
-      this.config = _.cloneDeep(this.config)
-      // 遍历config.setting,将config.setting中的值赋值给config.option中对应的optionField
-      this.config.setting.forEach(set => {
-        if (set.optionField) {
-          const optionField = set.optionField.split('.')
-          let option = this.config.option
-          optionField.forEach((field, index) => {
-            if (index === optionField.length - 1) {
-              // 数据配置时,必须有值才更新
-              if ((set.tabName === 'data' && set.value) || set.tabName === 'custom') {
-                option[field] = set.value
-              }
-            } else {
-              option = option[field]
-            }
-          })
-        }
-      })
-      if (this.config.optionHandler) {
-        try {
-          // 此处函数处理config
-          eval(this.config.optionHandler)
-        } catch (e) {
-          console.error(e)
-        }
+        // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
+        // eslint-disable-next-line no-unused-vars
+        config = this.changeData(config)
       }
     },
     /**
-     * 初始化组件时获取后端返回的数据, 返回数据和当前组件的配置
+     * 初始化组件时获取后端返回的数据, 返回数据和当前组件的配置_list
      * @param settingConfig 设置时的配置。不传则为当前组件的配置
      * @returns {Promise<unknown>}
      */
-    getCurrentOption (settingConfig) {
-      const pageCode = this.pageCode
-      const chartCode = this.config.code
-      const type = this.config.type
-      const config = _.cloneDeep(settingConfig || this.config)
+    changeDataByCode (config) {
       let currentPage = 1
       let size = 10
       if (config?.option?.pagination) {
@@ -110,49 +63,28 @@ export default {
         size = config.option.pagination.pageSize
       }
       return new Promise((resolve, reject) => {
-        this.getDataByCode(pageCode, chartCode, type, currentPage, size).then((data) => {
-          resolve({
-            config, data
-          })
+        getChatInfo({
+          // innerChartCode: this.pageCode ? config.code : undefined,
+          chartCode: config.code,
+          current: currentPage,
+          pageCode: this.pageCode,
+          size: size,
+          type: config.type
+        }).then((data) => {
+          config = this.dataFormatting(config, data)
+          this.changeChartConfig(config)
         }).catch((err) => {
-          reject(err)
+          console.log(err)
+        }).finally(() => {
+          resolve(config)
         })
       })
     },
-    /**
-     *  根据 chatCode 获取后端返回的数据
-     * @param pageCode
-     * @param chartCode
-     * @param type
-     * @param current
-     * @param size
-     * @returns {Promise<*>}
-     */
-    async getDataByCode (
-      pageCode,
-      chartCode,
-      type,
-      current = 1,
-      size = 10
-    ) {
-      let parentCode
-      const data = await getChatInfo({
-        innerChartCode: parentCode ? chartCode : undefined,
-        chartCode: parentCode || chartCode,
-        current: current,
-        pageCode: pageCode,
-        size: size,
-        type: type
-      })
-      return data
-    },
-
     /**
      * @description: 更新chart
      * @param {Object} config
      */
-    updateChartData (config) {
-      const filterList = this.filterList
+    changeData (config, filterList) {
       const params = {
         chart: {
           ...config,
@@ -161,41 +93,36 @@ export default {
         current: 1,
         pageCode: this.pageCode,
         type: config.type,
-        filterList
+        filterList: filterList || this.filterList
       }
-      // if (config.type === 'remoteComponent') {
-      //   config = this.buildOption(config, { success: false })
-      //   config.key = new Date().getTime()
-      //   this.changeChartConfig(config)
-      //   return
-      // }
-      getUpdateChartInfo(params).then((res) => {
-        // 数据集脚本前端执行
-        if (res.executionByFrontend) {
-          try {
-            const returnResult = eval(`(${res.data})`)()
-            res.data = returnResult
-          } catch (error) {
-            console.error('数据集脚本执行失败', error)
+      return new Promise((resolve, reject) => {
+        getUpdateChartInfo(params).then((data) => {
+          config = this.dataFormatting(config, data)
+          // this.changeChartConfig(config)
+          if (this.chart) {
+            // 单指标组件和多指标组件的changeData传参不同
+            if (['Liquid', 'Gauge', 'RingProgress'].includes(config.chartType)) {
+              this.chart.changeData(config.option.percent)
+            } else {
+              this.chart.changeData(config.option.data)
+            }
           }
-        }
-        config = this.buildOption(config, res)
-        config.key = new Date().getTime()
-        this.changeChartConfig(config)
-        // 获取数据后更新组件配置
-
-        // this.$message.success('更新成功')
-      }).catch((err) => {
-        console.error(err)
-        // this.$message.error('更新失败')
+        }).catch(err => {
+          console.log(err)
+        }).finally(() => {
+          resolve(config)
+        })
       })
     },
-    newChart () {
-      // 需要在自己的组件中重写此方法,用于构建自己的组件
+    dataFormatting (config, data) {
+      // 覆盖
+    },
+    newChart (option) {
+      // 覆盖
     },
-    buildOption (config, data) {
-      // 需要在自己的组件中重写此方法:config当前组件的配置,data后端返回的数据
-      return config
+    changeStyle (config) {
+      // this.changeChartConfig(config)
+      // return config
     },
     // 缓存组件数据监听
     watchCacheData () {
@@ -206,7 +133,7 @@ export default {
           this.config.dataSource.dataSetType === '2' &&
           this.config.dataSource.businessKey === dataSetId
         ) {
-          const config = this.buildOption(this.config, data)
+          const config = this.dataFormatting(this.config, data)
           config.key = new Date().getTime()
           this.changeChartConfig(config)
           this.newChart(config.option)