Jelajahi Sumber

Revert "Revert "fix:初步实现3d组件""

This reverts commit 11c20b3eaf77892337003f5b97b019e05c4d6c6c.
liu.shiyi 1 tahun lalu
induk
melakukan
a15b2cc166

+ 29 - 22
data-room-ui/packages/BasicComponents/Map/index.vue

@@ -3,7 +3,14 @@
     style="width: 100%; height: 100%"
     class="bs-design-wrap bs-bar"
   >
-  <el-button class="button" v-if="this.level=='province'&&config.customize.down" @click="jumpTo(config)" type='text' > 返回上一级</el-button>
+    <el-button
+      v-if="level=='province'&&config.customize.down"
+      class="button"
+      type="text"
+      @click="jumpTo(config)"
+    >
+      返回上一级
+    </el-button>
     <div
       :id="`chart${config.code}`"
       style="width: 100%; height: 100%"
@@ -90,14 +97,14 @@ export default {
       }
       return config
     },
-    async jumpTo(config){
-      this.level='country'
-      const mapUrl =`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/country/中华人民共和国.json`
+    async jumpTo (config) {
+      this.level = 'country'
+      const mapUrl = `${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/country/中华人民共和国.json`
       const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
-      this.option.geo.map = '中华人民共和国';
-      this.changeData({...config,customize:{...config.customize,level:'country',scope:'中国'}})
-      echarts.registerMap('中华人民共和国', map);
-      this.charts.setOption(this.option, true);
+      this.option.geo.map = '中华人民共和国'
+      this.changeData({ ...config, customize: { ...config.customize, level: 'country', scope: '中国' } })
+      echarts.registerMap('中华人民共和国', map)
+      this.charts.setOption(this.option, true)
     },
     async newChart (config) {
       this.charts = echarts.init(
@@ -107,14 +114,14 @@ export default {
         // 背景颜色
         backgroundColor: config.customize.backgroundColor,
         graphic: [
-          ],
+        ],
         geo: {
           map: config.customize.scope,
           zlevel: 10,
-          show:true,
+          show: true,
           layoutCenter: ['50%', '50%'],
           roam: true,
-          layoutSize: "100%",
+          layoutSize: '100%',
           zoom: 1,
           label: {
             // 通常状态下的样式
@@ -277,17 +284,17 @@ export default {
       const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
       echarts.registerMap(config.customize.scope, map)
       this.charts.setOption(this.option)
-      this.charts.on('click',  async(params)=> {
-          if(params.name=='') return
-          if(config.customize.down===false||this.level==='province') return
-          this.level='province'
-          const mapUrl =`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/province/${params.name}.json`
-          const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
-          this.changeData({...config,customize:{...config.customize,level:'province',scope:params.name}})
-          this.option.geo.map = params.name
-          echarts.registerMap(params.name, map);
-          this.charts.setOption(this.option, true);
-          });
+      this.charts.on('click', async (params) => {
+        if (params.name == '') return
+        if (config.customize.down === false || this.level === 'province') return
+        this.level = 'province'
+        const mapUrl = `${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/province/${params.name}.json`
+        const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
+        this.changeData({ ...config, customize: { ...config.customize, level: 'province', scope: params.name } })
+        this.option.geo.map = params.name
+        echarts.registerMap(params.name, map)
+        this.charts.setOption(this.option, true)
+      })
     }
   }
 }

+ 10 - 0
data-room-ui/packages/BigScreenDesign/LeftPanel.vue

@@ -149,6 +149,7 @@
 import cloneDeep from 'lodash/cloneDeep'
 import basicComponents from 'data-room-ui/js/config/basicComponentsConfig'
 import g2PlotComponents, { getCustomPlots } from '../G2Plots/plotList'
+import echartsComponents from '../Echarts/echartList'
 import borderComponents from 'data-room-ui/js/config/borderComponentsConfig'
 import decorationComponents from 'data-room-ui/js/config/decorationComponentsConfig'
 import LayerList from './LayerList/index.vue'
@@ -172,6 +173,7 @@ export default {
   },
   data () {
     return {
+      echartsComponents,
       g2PlotComponents,
       activeName: 'chart', // 设置左侧tab栏的默认值
       fold: false, // 控制左侧菜单栏伸缩
@@ -191,6 +193,13 @@ export default {
           icon: 'icon-jichushuju',
           components: this.g2PlotComponents
         },
+        {
+          id: 7,
+          name: 'echart',
+          title: '3D',
+          icon: 'icon-jichushuju',
+          components: this.echartsComponents
+        },
         {
           id: 3,
           name: 'dataV',
@@ -243,6 +252,7 @@ export default {
     this.initList()
     this.g2PlotComponents = [...this.g2PlotComponents, ...getCustomPlots()]
     this.menuList[1].components = this.g2PlotComponents
+    this.menuList[2].components = this.echartsComponents
   },
   mounted () {
     this.nodeDrag()

+ 257 - 0
data-room-ui/packages/Echarts/3D图/3D固定柱状图.js

@@ -0,0 +1,257 @@
+/*
+ * @description: 配置,参考https://g2plot.antv.antgroup.com/examples
+ * @Date: 2023-03-27 14:38:23
+ * @Author: xing.heng
+ */
+import echarts from 'echarts'
+// 配置版本号
+const version = '2023071001'
+// 分类
+const category = 'Column'
+// 标题
+const title = '3D固定柱状图'
+// 类别, new Line()
+const chartType = 'Column'
+// 用于标识,唯一,和文件夹名称一致
+const name = 'FenZuZhuZhuangTu'
+
+// 右侧配置项
+const setting = [
+  {
+    label: '维度',
+    type: 'select', // 设置组件类型
+    field: 'xField', // 字段
+    optionField: 'xField', // 对应options中的字段
+    // 是否多选
+    multiple: false,
+    value: '',
+    tabName: 'data'
+  },
+  {
+    label: '指标',
+    type: 'select', // 设置组件类型
+    field: 'yField', // 字段
+    optionField: 'yField', // 对应options中的字段
+    // 是否多选
+    multiple: false,
+    value: '',
+    tabName: 'data'
+  },
+  {
+    label: '分组字段',
+    type: 'select', // 设置组件类型
+    field: 'seriesField', // 字段
+    optionField: 'seriesField', // 对应options中的字段
+    // 是否多选
+    multiple: false,
+    value: '',
+    tabName: 'data'
+  }
+]
+
+// 配置处理脚本
+const optionHandler = ''
+
+// 数据处理脚本
+const dataHandler = ''
+
+// 图表配置 new Line('domName', option)
+
+const xData = ['本年话务总量', '本年人工话务量', '每万客户呼入量', '本年话务总量', '本年人工话务量', '每万客户呼入量']
+const yData = [300, 1230, 425, 300, 1230, 425]
+const maxData = [1500, 1500, 1500, 1500, 1500, 1500]
+const option = {
+  animation: false,
+  tooltip: {
+    show: true
+  },
+  grid: {
+    left: '15%',
+    right: '5%',
+    bottom: '15%',
+    z: 100,
+    containLabel: false,
+    show: false
+  },
+  graphic: {
+    type: 'group',
+    bottom: '8%',
+    left: '10%',
+    z: 100,
+    children: [
+      {
+        type: 'rect',
+        left: 0,
+        bottom: 0,
+        shape: {
+          width: 400,
+          height: 10
+        },
+        style: {
+          fill: '#3f4867'
+        }
+      },
+      {
+        type: 'polygon',
+        left: 0,
+        bottom: 10,
+        shape: {
+          // 左上、右上、右下、左下
+          points: [[40, -50], [360, -50], [400, 0], [0, 0]]
+        },
+        style: {
+          fill: '#303256'
+        }
+      }
+    ]
+  },
+  xAxis: [
+    {
+      type: 'category',
+      data: xData,
+      // 坐标轴刻度设置:x轴数据展示
+      axisTick: {
+        show: true,
+        alignWithLabel: true
+      },
+      nameTextStyle: {
+        color: '#82b0ec'
+      },
+      // 是否显示坐标轴的轴线
+      axisLine: {
+        show: false
+      },
+      // 坐标轴刻度标签
+      axisLabel: {
+        textStyle: {
+          fontSize: 10,
+          color: 'rgb(40, 129, 170)'
+        },
+        margin: 30
+      }
+    }
+  ],
+  yAxis: [
+    {
+      show: true, // y轴文本标签显示
+      type: 'value',
+      axisLabel: {
+        textStyle: {
+          color: 'rgb(40, 129, 170)'
+        }
+      },
+      // 分隔线
+      splitLine: {
+        show: false // yAxis.show配置为true时,该配置才有效
+      },
+      // y轴轴线是否显示
+      axisLine: {
+        show: true
+      }
+    }
+  ],
+  series: [
+    {
+      type: 'pictorialBar', // 象形柱图
+      symbol: 'diamond',
+      symbolOffset: [0, '-50%'], // 上部菱形
+      symbolSize: [30, 15],
+      // symbolOffset: [0, -6], // 上部椭圆
+      symbolPosition: 'end',
+      z: 12,
+      label: {
+        normal: {
+          show: true,
+          position: 'top',
+          fontSize: 15,
+          fontWeight: 'bold',
+          color: '#27a7ce'
+        }
+      },
+      color: '#2DB1EF',
+      data: yData
+    },
+    {
+      type: 'pictorialBar',
+      symbol: 'diamond',
+      symbolSize: [30, 15],
+      symbolOffset: ['0%', '50%'], // 下部菱形
+      // symbolOffset: [0, 7], // 下部椭圆
+      z: 12,
+      color: '#187dcb',
+      data: yData
+    },
+    {
+      type: 'bar',
+      barWidth: 30,
+      z: 10,
+      itemStyle: {
+        normal: {
+          // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+          //   {
+          //     offset: 0,
+          //     color: '#115ba6'
+          //   },
+          //   {
+          //     offset: 1,
+          //     color: '#1db0dd'
+          //   }
+          // ]),
+          opacity: 0.8,
+          shadowColor: 'rgba(0, 0, 0, 0.5)', // 阴影颜色
+          shadowBlur: 0 // 阴影模糊值
+        }
+      },
+      data: yData
+    },
+    {
+      type: 'bar',
+      barWidth: 30,
+      barGap: '-100%',
+      itemStyle: {
+        normal: {
+          color: '#041133',
+          opacity: 0.8,
+          shadowColor: 'rgba(0, 0, 0, 0.5)', // 阴影颜色
+          shadowBlur: 0 // 阴影模糊值
+        }
+      },
+      label: {
+        show: false
+      },
+      data: maxData
+    },
+    {
+      type: 'pictorialBar', // 象形柱图
+      symbol: 'diamond',
+      symbolOffset: [0, '-50%'], // 上部菱形
+      symbolSize: [30, 15],
+      // symbolOffset: [0, -6], // 上部椭圆
+      symbolPosition: 'end',
+      z: 12,
+      label: {
+        normal: {
+          show: false,
+          position: 'top',
+          fontSize: 15,
+          fontWeight: 'bold',
+          color: '#27a7ce'
+        }
+      },
+      color: '#142f5a',
+      data: maxData
+
+    }
+  ]
+}
+export default {
+  category,
+  version,
+  title,
+  chartType,
+  name,
+  option,
+  setting,
+  optionHandler,
+  dataHandler
+}

+ 55 - 0
data-room-ui/packages/Echarts/echartList.js

@@ -0,0 +1,55 @@
+/*
+ * @description: webpack读取当前文件夹下的所有 图表的js文件配置, 生成g2Plot配置列表
+ * @Date: 2023-03-28 10:40:22
+ * @Author: xing.heng
+ */
+import { dataConfig, settingConfig } from '../PlotRender/settingConfig'
+import cloneDeep from 'lodash/cloneDeep'
+import sortList from './echartListSort'
+// 遍历 当前文件夹下的所有文件,找到中文.js文件,然后导出
+const files = require.context('./', true, /[\u4e00-\u9fa5]+.js$/)
+const echartsList = getEchartsList(files)
+// 获取plot配置
+function getEchartsList (files) {
+  const configMapList = {}
+  files.keys().forEach((key) => {
+    // ./折线图/基础折线图.js
+    // 取到 "基础折线图"
+    const configName = key.split('/')[2].replace('.js', '')
+    configMapList[configName] = files(key).default
+  })
+  const echartsList = []
+  for (const configMapKey in configMapList) {
+    const index = sortList.findIndex((item) => item === configMapKey)
+    const config = configMapList[configMapKey]
+
+    echartsList[index] = {
+      version: config.version,
+      category: configMapKey,
+      name: config.name,
+      title: config.title,
+      border: { type: '', titleHeight: 60, fontSize: 30, color: ['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9'] },
+      icon: null,
+      img: require(`../Echarts/images/${config.title}.png`),
+      className:
+        'com.gccloud.dataroom.core.module.chart.components.CustomComponentChart',
+      w: config?.option?.width || 450,
+      h: config?.option?.height || 320,
+      x: 0,
+      y: 0,
+      type: 'echartsComponent',
+      chartType: config.chartType,
+      loading: false,
+      option: {
+        ...config.option,
+        ...cloneDeep(settingConfig)
+      },
+      setting: config.setting, // 右侧面板自定义配置
+      dataHandler: config.dataHandler, // 数据自定义处理js脚本
+      optionHandler: config.optionHandler, // 配置自定义处理js脚本
+      ...cloneDeep(dataConfig)
+    }
+  }
+  return echartsList
+}
+export default echartsList

+ 4 - 0
data-room-ui/packages/Echarts/echartListSort.js

@@ -0,0 +1,4 @@
+// 左侧plot组件的排序
+export default [
+  '3D固定柱状图'
+]

TEMPAT SAMPAH
data-room-ui/packages/Echarts/images/3D固定柱状图.png


+ 227 - 0
data-room-ui/packages/EchartsRender/index.vue

@@ -0,0 +1,227 @@
+<template>
+  <div
+    v-loading="config.loading"
+    element-loading-text="图表加载中"
+    :element-loading-background="loadingBackground"
+    style="width: 100%;height: 100%"
+    class="bs-design-wrap bs-custom-component"
+    :class="{'light-theme':customTheme === 'light','auto-theme':customTheme !=='light'}"
+  >
+    <div
+      :id="chatId"
+      style="width: 100%;height: 100%"
+    />
+    <!--    <span style="color:#ffffff">{{config.option.data}}</span>-->
+  </div>
+</template>
+<script>
+import 'insert-css'
+import cloneDeep from 'lodash/cloneDeep'
+import linkageMixins from 'data-room-ui/js/mixins/linkageMixins'
+import commonMixins from 'data-room-ui/js/mixins/commonMixins'
+import { mapState, mapMutations } from 'vuex'
+import plotList, { getCustomPlots } from '../G2Plots/plotList'
+import { settingToTheme } from 'data-room-ui/js/utils/themeFormatting'
+import _ from 'lodash'
+import * as echarts from 'echarts'
+
+export default {
+  name: 'PlotCustomComponent',
+  mixins: [commonMixins, linkageMixins],
+  props: {
+    config: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  data () {
+    return {
+      chart: null,
+      hasData: false,
+      plotList
+    }
+  },
+  computed: {
+    ...mapState('bigScreen', {
+      pageInfo: state => state.pageInfo,
+      customTheme: state => state.pageInfo.pageConfig.customTheme,
+      activeCode: state => state.activeCode
+    }),
+    chatId () {
+      let prefix = 'chart_'
+      if (this.$route.path === window?.BS_CONFIG?.routers?.previewUrl) {
+        prefix = 'preview_chart_'
+      }
+
+      if (this.$route.path === window?.BS_CONFIG?.routers?.designUrl) {
+        prefix = 'design_chart_'
+      }
+
+      if (this.$route.path === window?.BS_CONFIG?.routers?.pageListUrl) {
+        prefix = 'management_chart_'
+      }
+      return prefix + this.config.code
+    }
+  },
+  created () {
+    this.plotList = [...this.plotList, ...getCustomPlots()]
+  },
+  watch: {
+    // 监听主题变化手动触发组件配置更新
+    'config.option.theme': {
+      handler (val) {
+        if (val) {
+          this.changeStyle(this.config, true)
+        }
+      }
+    }
+  },
+  mounted () {
+  },
+  beforeDestroy () {
+    if (this.chart) {
+      this.chart.destroy()
+    }
+  },
+  methods: {
+    ...mapMutations('bigScreen', ['changeChartConfig', 'changeActiveItemConfig', 'changeChartLoading']),
+    chartInit () {
+      let config = this.config
+      // key和code相等,说明是一进来刷新,调用list接口
+      if (this.config.code === this.config.key || this.isPreview) {
+        // 改变样式
+        config = this.changeStyle(config)
+        // 改变数据
+        config.loading = true
+        this.changeChartLoading(config)
+        this.changeDataByCode(config).then((res) => {
+          // 初始化图表
+          config.loading = false
+          this.changeChartLoading(config)
+          this.newChart(res)
+        }).catch(() => {
+        })
+      } else {
+        config.loading = true
+        this.changeChartLoading(config)
+        // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
+        this.changeData(config).then((res) => {
+          config.loading = false
+          this.changeChartLoading(config)
+          // 初始化图表
+          this.newChart(res)
+        })
+      }
+    },
+    /**
+     * 构造chart
+     */
+    newChart (config) {
+      const chartDom = document.getElementById(this.chatId)
+      const myChart = echarts.init(chartDom)
+      config.option && myChart.setOption(config.option)
+    },
+    /**
+     * 注册事件
+     */
+    registerEvent () {
+      // 图表添加事件进行数据联动
+      let formData = {}
+      // eslint-disable-next-line no-unused-vars
+      this.chart.on('tooltip:change', (...args) => {
+        formData = {}
+        formData = cloneDeep(args[0].data.items[0].data)
+      })
+      // eslint-disable-next-line no-unused-vars
+      this.chart.on('plot:click', (...args) => {
+        this.linkage(formData)
+      })
+    },
+    // 将config.setting的配置转化为option里的配置,这里之所以将转化的方法提出来,是因为在改变维度指标和样式的时候都需要转化
+    transformSettingToOption (config, type) {
+      let option = null
+      config.setting.forEach(set => {
+        if (set.optionField) {
+          const optionField = set.optionField.split('.')
+          option = config.option
+          optionField.forEach((field, index) => {
+            if (index === optionField.length - 1) {
+              // 数据配置时,必须有值才更新
+              if ((set.tabName === type && type === 'data' && set.value) || (set.tabName === type && type === 'custom')) {
+                option[field] = set.value
+              }
+            } else {
+              option = option[field]
+            }
+          })
+        }
+      })
+      config.option = { ...config.option, ...option }
+      return config
+    },
+    dataFormatting (config, data) {
+      // 数据返回成功则赋值
+      if (data.success) {
+        data = data.data
+        config = this.transformSettingToOption(config, 'data')
+        // 获取到后端返回的数据,有则赋值
+        const option = config.option
+        const setting = config.setting
+        if (config.dataHandler) {
+          try {
+            // 此处函数处理data
+            eval(config.dataHandler)
+          } catch (e) {
+            console.error(e)
+          }
+        }
+        // config.option.data = data
+      } else {
+        // 数据返回失败则赋前端的模拟数据
+        // config.option.data = this.plotList?.find(plot => plot.name === config.name)?.option?.data || config?.option?.data
+      }
+      return config
+    },
+    // 组件的样式改变,返回改变后的config
+    changeStyle (config, isUpdateTheme) {
+      config = { ...this.config, ...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 (!isUpdateTheme) {
+        config.theme = settingToTheme(_.cloneDeep(config), this.customTheme)
+      }
+      this.changeChartConfig(config)
+      if (config.code === this.activeCode) {
+        this.changeActiveItemConfig(config)
+      }
+      if (this.chart) {
+        this.chart.update(config.option)
+      }
+      return config
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../assets/style/echartStyle';
+.light-theme{
+  background-color: #FFFFFF;
+  color: #000000;
+}
+.auto-theme{
+  background-color: transparent;
+}
+
+</style>

+ 23 - 0
data-room-ui/packages/EchartsRender/settingConfig.js

@@ -0,0 +1,23 @@
+import { commonConfig, displayOption } from 'data-room-ui/js/config'
+export const settingConfig = {
+  displayOption: { ...displayOption }
+}
+const customConfig = {
+  root: {
+    contribution: false
+  },
+  customize: {
+    theme: 'dark', // 'light'、'dark'
+    colorScheme: [],
+    legend: null,
+    legendColor: '', // 图例颜色
+    xaxisColor: '', // x轴标签颜色
+    xaxisFontSize: 14, // x轴标签字体大小
+    yaxisColor: '', // y轴标签颜色
+    yaxisFontSize: 14, // y轴标签字体大小
+    labelColor: ''// 标签颜色
+  }
+}
+export const dataConfig = {
+  ...commonConfig(customConfig)
+}

+ 3 - 3
data-room-ui/packages/G2Plots/plotList.js

@@ -32,7 +32,7 @@ function getPlotList (files) {
       category: configMapKey,
       name: config.name,
       title: config.title,
-      border:{type:'',titleHeight:60,fontSize:30,color:['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9']},
+      border: { type: '', titleHeight: 60, fontSize: 30, color: ['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9'] },
       icon: null,
       img: require(`../G2Plots/images/componentLogo/${config.title}.png`),
       className:
@@ -65,7 +65,7 @@ export function getCustomPlots () {
       category: config.category,
       name: config.name,
       title: config.title,
-      border:{type:'',titleHeight:60,fontSize:30,color:['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9']},
+      border: { type: '', titleHeight: 60, fontSize: 30, color: ['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9'] },
       icon: null,
       img: config.img,
       className:
@@ -89,5 +89,5 @@ export function getCustomPlots () {
   return list
 }
 
-const plots = [...plotList, ...customPlots, mapData,FlyMapData]
+const plots = [...plotList, ...customPlots, mapData, FlyMapData]
 export default plots

+ 3 - 1
data-room-ui/packages/Render/RenderCard.vue

@@ -36,6 +36,7 @@ import { resolveComponentType } from 'data-room-ui/js/utils'
 import pcComponent from 'data-room-ui/js/utils/componentImport'
 import { dataInit, destroyedEvent } from 'data-room-ui/js/utils/eventBus'
 import CustomComponent from '../PlotRender/index.vue'
+import EchartsComponent from '../EchartsRender/index.vue'
 import Svgs from '../Svgs/index.vue'
 import RemoteComponent from 'data-room-ui/RemoteComponents/index.vue'
 import cloneDeep from 'lodash/cloneDeep'
@@ -52,7 +53,8 @@ export default {
     ...components,
     CustomComponent,
     Svgs,
-    RemoteComponent
+    RemoteComponent,
+    EchartsComponent
   },
   props: {
     // 卡片的属性