Prechádzať zdrojové kódy

Merge remote-tracking branch 'origin/dev' into dev

qianming 2 rokov pred
rodič
commit
b693c9dcbb
21 zmenil súbory, kde vykonal 831 pridanie a 153 odobranie
  1. 3 1
      report-ui/src/store/index.js
  2. 42 0
      report-ui/src/store/modules/designer.js
  3. 290 0
      report-ui/src/views/bigscreenDesigner/designer/components/componentLinkage.vue
  4. 19 7
      report-ui/src/views/bigscreenDesigner/designer/components/contentMenu.vue
  5. 23 0
      report-ui/src/views/bigscreenDesigner/designer/components/dynamicForm.vue
  6. 164 106
      report-ui/src/views/bigscreenDesigner/designer/index.vue
  7. 128 0
      report-ui/src/views/bigscreenDesigner/designer/linkageLogic.js
  8. 12 0
      report-ui/src/views/bigscreenDesigner/designer/tools/configure/barCharts/widget-barchart.js
  9. 3 3
      report-ui/src/views/bigscreenDesigner/designer/tools/configure/form/widget-select.js
  10. 12 0
      report-ui/src/views/bigscreenDesigner/designer/tools/configure/lineCharts/widget-linechart.js
  11. 12 0
      report-ui/src/views/bigscreenDesigner/designer/tools/configure/percentCharts/widget-pie-percentage.js
  12. 4 3
      report-ui/src/views/bigscreenDesigner/designer/tools/index.js
  13. 3 3
      report-ui/src/views/bigscreenDesigner/designer/tools/main.js
  14. 25 2
      report-ui/src/views/bigscreenDesigner/designer/widget/bar/widgetBarchart.vue
  15. 4 5
      report-ui/src/views/bigscreenDesigner/designer/widget/form/widgetInput.vue
  16. 17 9
      report-ui/src/views/bigscreenDesigner/designer/widget/form/widgetSelect.vue
  17. 24 3
      report-ui/src/views/bigscreenDesigner/designer/widget/line/widgetLinechart.vue
  18. 24 2
      report-ui/src/views/bigscreenDesigner/designer/widget/percent/widgetPiePercentageChart.vue
  19. 5 1
      report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue
  20. 6 8
      report-ui/src/views/bigscreenDesigner/designer/widget/widget.vue
  21. 11 0
      report-ui/src/views/bigscreenDesigner/viewer/index.vue

+ 3 - 1
report-ui/src/store/index.js

@@ -7,6 +7,7 @@ import app from './modules/app'
 import user from './modules/user'
 import cacheView from './modules/cachaView'
 import help from './modules/help'
+import designer from './modules/designer'
 
 Vue.use(Vuex)
 
@@ -18,7 +19,8 @@ const store = new Vuex.Store({
     app,
     user,
     cacheView,
-    help
+    help,
+    designer
   },
   state: { },
   plugins: [initPlugin],

+ 42 - 0
report-ui/src/store/modules/designer.js

@@ -0,0 +1,42 @@
+/*
+ * @Author: chengsl
+ * @Date: 2022-11-08 10:30:37
+ * @LastEditors: chengsl
+ * @LastEditTime: 2023-02-24 09:54:34
+ * @Description: 设计器公用变量
+ */
+
+const designer = {
+  state: {
+    allComponentLinkage: [], // 所有组件之间的联动配置
+  },
+
+  mutations: {
+    SET_ALL_COMPONENT_LINKAGE: (state, params) => {
+      var { index = -1, widgetId = '', linkageArr } = params
+      try {
+        console.log('params---', params)
+        linkageArr = linkageArr.map(item => {
+          const arr = item.widgetValue.split('-$-')
+          return {
+            originId: widgetId,
+            targetId: arr[0],
+            targetName: arr[1],
+            paramsConfig: item.paramsConfig
+          }
+        })
+      } catch (error) {
+        linkageArr = [] // 兼容异常错误导致页面加载不出来
+      }
+      state.allComponentLinkage[index] = {
+        index: +index,
+        widgetId,
+        linkageArr
+      }
+    }
+  },
+
+  actions: {}
+}
+
+export default designer

+ 290 - 0
report-ui/src/views/bigscreenDesigner/designer/components/componentLinkage.vue

@@ -0,0 +1,290 @@
+<template>
+  <div class="component-linkage">
+    <el-button
+      type="primary"
+      size="mini"
+      icon="el-icon-plus"
+      :disabled="formData.length === layerWidget.length -1"
+      plain
+      @click="handleAddClick"
+    >
+      新增
+    </el-button>
+    <el-table :data="formData" style="width: 100%">
+      <el-table-column label="被联动组件名" align="left">
+        <template slot-scope="scope">
+          <div class="button-name" v-text="scope.row.widgetValue.split('-$-')[1]" />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center">
+        <template slot-scope="scope">
+          <span
+            class="editor"
+            @click="handleEditorClick(scope.$index, scope.row)"
+          >
+            <i class="el-icon-edit" /> 编辑
+          </span>
+          <span
+            class="delete"
+            @click="handleDeleteClick(scope.$index, scope.row)"
+          >
+            <i class="el-icon-delete" /> 删除
+          </span>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-dialog
+      :title="isAddFlag ? '新增' : '修改'"
+      :visible.sync="dialogVisible"
+      width="30%"
+      :before-close="handleClose"
+    >
+      <el-form ref="myForm" v-model="linkageForm" label-width="100px">
+        <el-form-item label="被联动的组件">
+          <el-select
+            v-model="linkageForm.widgetValue"
+            size="mini"
+            clearable
+            placeholder="请选择"
+          >
+            <el-option
+              v-for="(item, index) in layerWidget"
+              :key="item.widgetId"
+              :disabled="widgetIndex === index || widgetIdList.includes(index)"
+              :label="item.label"
+              :value="`${item.widgetId}-$-${item.label}-$-${index}`"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-show="linkageForm.widgetValue" class="params-form-item" label="参数配置">
+          <div class="params-config">
+            <div
+              v-for="item in linkageForm.paramsConfig"
+              :key="item.originKey"
+              class="item-config"
+            >
+              <div class="label">{{ item.originKey }}</div>
+              <div class="value">
+                <el-select
+                  v-model="item.targetKey"
+                  size="mini"
+                  clearable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="paramKey in currentTargetParams"
+                    :key="paramKey"
+                    :label="paramKey"
+                    :value="paramKey"
+                  />
+                </el-select>
+              </div>
+            </div>
+          </div>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button size="mini" @click="handleClose">取 消</el-button>
+        <el-button size="mini" type="primary" @click="handleSaveClick">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getOneConfigByCode } from '../linkageLogic'
+export default {
+  name: 'ComponentLinkage',
+  components: {},
+  model: {
+    prop: 'formData',
+    event: 'input'
+  },
+  props: {
+    formData: {
+      type: Array,
+      default: () => []
+    },
+    layerWidget: { // 当前设计器中所有组件的名称
+      type: Array,
+      default: () => []
+    },
+    widgetParamsConfig: { // 当前设计器中所有组件的的数据集配置
+      type: Array,
+      default: () => []
+    },
+    widgetIndex: { // 当前操作的组件下标
+      require: true,
+      type: Number,
+      default: -1
+    }
+  },
+  data() {
+    return {
+      isAddFlag: true, // true 新增, false 编辑
+      indexEditor: -1, // 编辑第几个数据
+      linkageForm: {
+        widgetValue: '', // 选中的组件的名字
+        paramsConfig: []
+      },
+      dialogVisible: false // 显示弹窗
+    }
+  },
+  computed: {
+    targetIndex() { // 当前选择联动的目标组件的下标
+      if (!this.linkageForm.widgetValue) return -1
+      return +this.linkageForm.widgetValue.split('-$-')[2]
+    },
+    currentTargetParams() { // 当前选择联动的目标组件的数据集参数
+      try {
+        return Object.keys(this.widgetParamsConfig[this.targetIndex].dynamicData.contextData)
+      } catch (error) {
+        return []
+      }
+    },
+    widgetIdList() {
+      return this.formData.map(item => {
+        return +item.widgetValue.split('-$-')[0]
+      })
+    }
+  },
+  watch: {
+    widgetIndex: {
+      handler(val) {
+        if (val !== -1) {
+          this.initFormDynamicData()
+        }
+      },
+      immediate: true
+    }
+  },
+  created() {
+  },
+  mounted() {},
+  methods: {
+    // 重置对象
+    initFormDynamicData() {
+      let paramsKey = []
+      const dynamicParamsWidget = ['widgetButtonGroup', 'widget-table']
+      if (dynamicParamsWidget.includes(this.layerWidget[this.widgetIndex].code)) { // 参数不确定的 通过消息接收
+        paramsKey = this.layerWidget[this.widgetIndex].paramsKeys || []
+      } else {
+        const widgetConfigTemp = getOneConfigByCode(this.layerWidget[this.widgetIndex].code)
+        if (!widgetConfigTemp) return
+        // console.log('this.layerWidget[this.widgetIndex---', this.layerWidget, '  ---  ', this.widgetIndex)
+        paramsKey = widgetConfigTemp.paramsKey
+      }
+      this.linkageForm = {
+        widgetValue: '', // 选中的组件的名字
+        paramsConfig: paramsKey.map(item => {
+          return {
+            originKey: item,
+            targetKey: ''
+          }
+        })
+      }
+    },
+    // 弹出框关闭
+    handleClose() {
+      this.dialogVisible = false
+      this.buttonLabel = ''
+      this.initFormDynamicData()
+    },
+    // 新增按钮
+    handleAddClick() {
+      this.buttonLabel = ''
+      this.initFormDynamicData()
+      this.isAddFlag = true
+      this.dialogVisible = true
+    },
+    // 修改按钮
+    handleEditorClick(index, row) {
+      this.isAddFlag = false
+      this.linkageForm = JSON.parse(JSON.stringify(this.formData[index]))
+      this.dialogVisible = true
+      this.indexEditor = index
+    },
+    // 删除
+    handleDeleteClick(index) {
+      this.formData.splice(index, 1)
+      this.$emit('input', this.formData)
+      this.$emit('change', this.formData)
+    },
+    // 确定
+    handleSaveClick() {
+      const obj = JSON.parse(JSON.stringify(this.linkageForm))
+      if (this.isAddFlag) {
+        // 新增
+        this.formData.push(obj)
+        this.dialogVisible = false
+      } else {
+        // 编辑
+        this.formData[this.indexEditor] = obj
+        this.dialogVisible = false
+      }
+      this.$emit('input', this.formData)
+      this.$emit('change', this.formData)
+    }
+  }
+}
+</script>
+<style lang='scss' scoped>
+.component-linkage {
+
+  .button-name {
+    width: 80px;
+    height: 30px;
+    line-height: 30px;
+    color: #A9B2BC;
+    border: 1px solid #23466F;
+    border-radius: 4px;
+    box-shadow: 0 0 3px #23466f inset;
+    text-align: center;
+  }
+  .editor, .delete {
+    color: #409eff;
+    cursor: pointer;
+  }
+  .delete {
+    margin-left: 10px;
+  }
+
+  /deep/.el-table,
+  /deep/.el-table__expanded-cell,
+  /deep/.el-table th,
+  /deep/.el-table tr {
+    background-color: transparent !important;
+    color: #859094 !important;
+  }
+  /deep/.el-table td,
+  /deep/.el-table th.is-leaf {
+    border-bottom: none;
+    line-height: 26px;
+  }
+  /deep/.el-table tbody tr:hover > td {
+    background-color: #263445 !important;
+  }
+  /deep/.el-table::before {
+    height: 0;
+  }
+  /deep/.el-dialog {
+    background: #1b1e25;
+    .el-dialog__title {
+      color: #fff;
+    }
+  }
+  .params-form-item {
+    margin-top: 20px;
+  }
+  .item-config {
+    display: flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    margin-bottom: 20px;
+    .label {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 19 - 7
report-ui/src/views/bigscreenDesigner/designer/components/contentMenu.vue

@@ -3,6 +3,12 @@
     <div class="contentmenu__item" @click="deleteLayer">
       <i class="iconfont iconguanbi"></i> 删除图层
     </div>
+    <div class="contentmenu__item" @click="lockLayer">
+      <i class="iconfont iconfuzhi1"></i> 锁定图层
+    </div>
+    <div class="contentmenu__item" @click="noLockLayer">
+      <i class="iconfont iconfuzhi1"></i> 解除锁定
+    </div>
     <div class="contentmenu__item" @click="copyLayer">
       <i class="iconfont iconfuzhi1"></i> 复制图层
     </div>
@@ -24,7 +30,7 @@
 export default {
   props: {
     styleObj: Object,
-    visible: Boolean
+    visible: Boolean,
   },
   data() {
     return {};
@@ -36,7 +42,7 @@ export default {
       } else {
         document.body.removeEventListener("click", this.closeMenu);
       }
-    }
+    },
   },
   methods: {
     closeMenu() {
@@ -46,22 +52,28 @@ export default {
       this.$confirm("是否删除所选图层?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       })
         .then(() => {
           this.$emit("deletelayer");
           this.$message({
             type: "success",
-            message: "删除成功!"
+            message: "删除成功!",
           });
         })
         .catch(() => {
           this.$message({
             type: "info",
-            message: "已取消删除"
+            message: "已取消删除",
           });
         });
     },
+    lockLayer() {
+      this.$emit("lockLayer");
+    },
+    noLockLayer() {
+      this.$emit("noLockLayer");
+    },
     copyLayer() {
       this.$emit("copylayer");
     },
@@ -76,8 +88,8 @@ export default {
     },
     movedownLayer() {
       this.$emit("movedownLayer");
-    }
-  }
+    },
+  },
 };
 </script>
 <style lang="scss" scoped>

+ 23 - 0
report-ui/src/views/bigscreenDesigner/designer/components/dynamicForm.vue

@@ -294,6 +294,15 @@
                   v-model="formData[itemChildList.name]"
                   @change="changed($event, itemChildList.name)"
                 />
+                <componentLinkage
+                  v-if="itemChildList.type == 'componentLinkage'"
+                  :key="'cl-' + idx"
+                  v-model="formData[itemChildList.name]"
+                  :layer-widget="layerWidget"
+                  :widget-params-config="widgetParamsConfig"
+                  :widget-index="widgetIndex"
+                  @change="changed($event, itemChildList.name)"
+                />
               </template>
             </el-collapse-item>
           </el-collapse>
@@ -319,6 +328,7 @@ import dynamicAddTable from "./dynamicAddTable.vue";
 import customUpload from "./customUpload.vue";
 import dynamicAddRadar from "./dynamicAddRadar";
 import MonacoEditor from "@/components/MonacoEditor/index";
+import componentLinkage from './componentLinkage';
 export default {
   name: "DynamicForm",
   components: {
@@ -330,6 +340,7 @@ export default {
     customUpload,
     dynamicAddRadar,
     MonacoEditor,
+    componentLinkage
   },
   model: {
     prop: "value",
@@ -341,6 +352,18 @@ export default {
       type: [Object],
       default: () => {},
     },
+    layerWidget: {
+      type: Array,
+      default: () => []
+    },
+    widgetParamsConfig: {
+      type: Array,
+      default: () => []
+    },
+    widgetIndex: {
+      type: Number,
+      default: -1
+    }
   },
   data() {
     return {

+ 164 - 106
report-ui/src/views/bigscreenDesigner/designer/index.vue

@@ -1,10 +1,3 @@
-<!--
- * @Descripttion: 大屏设计器
- * @Author: lide1202@hotmail.com
- * @Date: 2021-3-13 11:04:24
- * @Last Modified by:   lide1202@hotmail.com
- * @Last Modified time: 2021-3-13 11:04:24
- !-->
 <template>
   <div class="layout">
     <div
@@ -80,53 +73,53 @@
       :style="{ width: middleWidth + 'px', height: middleHeight + 'px' }"
     >
       <div class="top-button">
-        <span class="btn">
+        <span class="btn" @click="saveData">
           <el-tooltip
             class="item"
             effect="dark"
             content="保存"
             placement="bottom"
           >
-            <i class="iconfont iconsave" @click="saveData"></i>
+            <i class="iconfont iconsave"></i>
           </el-tooltip>
         </span>
-        <span class="btn">
+        <span class="btn" @click="viewScreen">
           <el-tooltip
             class="item"
             effect="dark"
             content="预览"
             placement="bottom"
           >
-            <i class="iconfont iconyulan" @click="viewScreen"></i>
+            <i class="iconfont iconyulan"></i>
           </el-tooltip>
         </span>
 
-        <span class="btn">
+        <span class="btn" @click="handleUndo">
           <el-tooltip
             class="item"
             effect="dark"
             content="撤销"
             placement="bottom"
           >
-            <i class="iconfont iconundo" @click="handleUndo"></i>
+            <i class="iconfont iconundo"></i>
           </el-tooltip>
         </span>
 
-        <span class="btn">
+        <span class="btn" @click="handleRedo">
           <el-tooltip
             class="item"
             effect="dark"
             content="恢复"
             placement="bottom"
           >
-            <i class="iconfont iconhuifubeifen" @click="handleRedo"></i>
+            <i class="iconfont iconhuifubeifen"></i>
           </el-tooltip>
         </span>
 
         <span
           :class="{
-            'btn': true,
-            'btn-disable': currentSizeRangeIndex === 0
+            btn: true,
+            'btn-disable': currentSizeRangeIndex === 0,
           }"
           @click="setSize(0)"
         >
@@ -138,7 +131,7 @@
             placement="bottom"
           >
             <!-- <svg-icon style="font-size:16px;" icon-class="jianhao" class-name="icon" /> -->
-            <i class="el-icon-minus" style="font-size:16px;" />
+            <i class="el-icon-minus" style="font-size: 16px" />
           </el-tooltip>
         </span>
         <!--
@@ -146,9 +139,9 @@
           :style="currentSizeRangeIndex === defaultSize.index ? 'cursor: no-drop;' : ''" -->
         <span
           :class="{
-            'btn': true,
+            btn: true,
             'scale-num': true,
-            'btn-disable': currentSizeRangeIndex === defaultSize.index
+            'btn-disable': currentSizeRangeIndex === defaultSize.index,
           }"
           @click="setSize(2)"
         >
@@ -159,15 +152,13 @@
             content="默认比例"
             placement="bottom"
           >
-            <span>
-              {{ parseInt(scaleNum) }}%
-            </span>
+            <span> {{ parseInt(scaleNum) }}% </span>
           </el-tooltip>
         </span>
         <span
           :class="{
-            'btn': true,
-            'btn-disable': currentSizeRangeIndex === 8
+            btn: true,
+            'btn-disable': currentSizeRangeIndex === 8,
           }"
           @click="setSize(1)"
         >
@@ -179,7 +170,7 @@
             placement="bottom"
           >
             <!-- <svg-icon style="font-size:16px;" icon-class="jiahao" class-name="icon" /> -->
-            <i class="el-icon-plus" style="font-size:16px;" />
+            <i class="el-icon-plus" style="font-size: 16px" />
           </el-tooltip>
         </span>
 
@@ -237,18 +228,15 @@
         </span>
       </div>
       <!-- 中间操作内容  主体 -->
-        <!-- :style="{
+      <!-- :style="{
           width: bigscreenWidthInWorkbench + 'px',
           height: bigscreenHeightInWorkbench + 'px',
         }" -->
-      <div
-        class="workbench-container"
-        @mousedown="handleMouseDown"
-      >
+      <div class="workbench-container" @mousedown="handleMouseDown">
         <div
           :style="{
-            width: ((+bigscreenWidth + 18) * bigscreenScaleInWorkbench) + 'px',
-            height: ((+bigscreenHeight + 18) * bigscreenScaleInWorkbench) + 'px'
+            width: (+bigscreenWidth + 18) * bigscreenScaleInWorkbench + 'px',
+            height: (+bigscreenHeight + 18) * bigscreenScaleInWorkbench + 'px',
           }"
           class="vue-ruler-tool-wrap"
         >
@@ -264,9 +252,12 @@
             :visible.sync="dashboard.presetLineVisible"
             :style="{
               width: +bigscreenWidth + 18 + 'px',
-              height: +bigscreenHeight + 18 +'px',
-              transform: currentSizeRangeIndex === defaultSize.index ? workbenchTransform : `scale(${sizeRange[currentSizeRangeIndex]/100})`,
-              transformOrigin: '0 0'
+              height: +bigscreenHeight + 18 + 'px',
+              transform:
+                currentSizeRangeIndex === defaultSize.index
+                  ? workbenchTransform
+                  : `scale(${sizeRange[currentSizeRangeIndex] / 100})`,
+              transformOrigin: '0 0',
             }"
           >
             <div
@@ -321,6 +312,9 @@
           <dynamicForm
             ref="formData"
             :options="widgetOptions.setup"
+            :layer-widget="layerWidget"
+            :widget-index="widgetIndex"
+            :widget-params-config="widgetParamsConfig"
             @onChanged="(val) => widgetValueChanged('setup', val)"
           />
         </el-tab-pane>
@@ -353,6 +347,8 @@
       :visible.sync="visibleContentMenu"
       :style-obj="styleObj"
       @deletelayer="deletelayer"
+      @lockLayer="lockLayer"
+      @noLockLayer="noLockLayer"
       @copylayer="copylayer"
       @istopLayer="istopLayer"
       @setlowLayer="setlowLayer"
@@ -412,7 +408,7 @@ export default {
         title: "", // 大屏页面标题
         width: 1920, // 大屏设计宽度
         height: 1080, // 大屏设计高度
-        backgroundColor: "", // 大屏背景色
+        backgroundColor: "#1E1E1E", // 大屏背景色
         backgroundImage: "", // 大屏背景图片
         refreshSeconds: null, // 大屏刷新时间间隔
         presetLine: [], // 辅助线
@@ -460,7 +456,9 @@ export default {
       activeName: "first",
       scaleNum: 0, // 当前缩放百分比的值
       sizeRange: [20, 40, 60, 80, 100, 150, 200, 300, 400], // 缩放百分比
-      currentSizeRangeIndex: -1 // 当前是哪个缩放比分比
+      currentSizeRangeIndex: -1, // 当前是哪个缩放比分比,
+      currentWidgetTotal: 0,
+      widgetParamsConfig: [], // 各组件动态数据集的参数配置情况
     };
   },
   computed: {
@@ -502,19 +500,19 @@ export default {
     defaultSize() {
       const obj = {
         index: -1,
-        size: '50'
-      }
+        size: "50",
+      };
       this.sizeRange.some((item, index) => {
-        if (item <= (100 * this.bigscreenScaleInWorkbench)) {
-          obj.index = index
-          obj.size = 100 * this.bigscreenScaleInWorkbench // item
+        if (item <= 100 * this.bigscreenScaleInWorkbench) {
+          obj.index = index;
+          obj.size = 100 * this.bigscreenScaleInWorkbench; // item
         }
-      })
+      });
       if (obj.index === -1) {
-        obj.index = 0
-        obj.size = this.sizeRange[0]
+        obj.index = 0;
+        obj.size = this.sizeRange[0];
       }
-      return obj
+      return obj;
     },
     // 大屏在设计模式的大小
     bigscreenWidthInWorkbench() {
@@ -530,6 +528,7 @@ export default {
     widgets: {
       handler(val) {
         this.handlerLayerWidget(val);
+        this.handlerdynamicDataParamsConfig(val);
         //以下部分是记录历史
         this.$nextTick(() => {
           this.revoke.push(this.widgets);
@@ -540,18 +539,18 @@ export default {
     defaultSize: {
       handler(val) {
         if (val !== -1) {
-          this.currentSizeRangeIndex = val.index
-          this.scaleNum = val.size
+          this.currentSizeRangeIndex = val.index;
+          this.scaleNum = val.size;
         }
       },
-      immediate: true
+      immediate: true,
     },
     bigscreenWidth() {
-      this.initVueRulerTool()
+      this.initVueRulerTool();
     },
     bigscreenHeight() {
-      this.initVueRulerTool()
-    }
+      this.initVueRulerTool();
+    },
   },
   created() {
     /* 以下是记录历史的 */
@@ -565,8 +564,8 @@ export default {
       this.grade = false;
     });
     this.$nextTick(() => {
-      this.initVueRulerTool() // 初始化 修正插件样式
-    })
+      this.initVueRulerTool(); // 初始化 修正插件样式
+    });
   },
   methods: {
     /**
@@ -574,41 +573,51 @@ export default {
      * sizeRange: [20, 40, 60, 72, 100, 150, 200, 300, 400]
      */
     setSize(num) {
-      if (num === 0) { // 缩小
-        if (this.currentSizeRangeIndex === 0) return
-        this.currentSizeRangeIndex -= 1
-      } else if (num === 1) { // 放大
-        if (this.currentSizeRangeIndex === 8) return
-        this.currentSizeRangeIndex += 1
-      } else if (num === 2) { // 正常比例
-        this.currentSizeRangeIndex = this.defaultSize.index
+      if (num === 0) {
+        // 缩小
+        if (this.currentSizeRangeIndex === 0) return;
+        this.currentSizeRangeIndex -= 1;
+      } else if (num === 1) {
+        // 放大
+        if (this.currentSizeRangeIndex === 8) return;
+        this.currentSizeRangeIndex += 1;
+      } else if (num === 2) {
+        // 正常比例
+        this.currentSizeRangeIndex = this.defaultSize.index;
       }
-      this.scaleNum = this.currentSizeRangeIndex === this.defaultSize.index ? this.defaultSize.size : this.sizeRange[this.currentSizeRangeIndex]
+      this.scaleNum =
+        this.currentSizeRangeIndex === this.defaultSize.index
+          ? this.defaultSize.size
+          : this.sizeRange[this.currentSizeRangeIndex];
     },
     // 初始化 修正插件样式
     initVueRulerTool() {
-      const vueRulerToolDom = this.$refs['vue-ruler-tool'].$el // 操作面板 第三方插件工具
-      const contentDom = vueRulerToolDom.querySelector('.vue-ruler-content')
-      const vueRulerX = vueRulerToolDom.querySelector('.vue-ruler-h') // 横向标尺
-      const vueRulerY = vueRulerToolDom.querySelector('.vue-ruler-v') // 纵向标尺
+      const vueRulerToolDom = this.$refs["vue-ruler-tool"].$el; // 操作面板 第三方插件工具
+      const contentDom = vueRulerToolDom.querySelector(".vue-ruler-content");
+      const vueRulerX = vueRulerToolDom.querySelector(".vue-ruler-h"); // 横向标尺
+      const vueRulerY = vueRulerToolDom.querySelector(".vue-ruler-v"); // 纵向标尺
       // vueRulerToolDom.style.cssText += ';width:' + (this.bigscreenWidth + 18) + 'px !important;height:' + (this.bigscreenHeight + 18) + 'px !important;'
-      contentDom.style.width = '100%'
-      contentDom.style.height = '100%'
+      contentDom.style.width = "100%";
+      contentDom.style.height = "100%";
 
-      let xHtmlContent = '' // '<span class="n" style="left: 2px;">0</span>'
-      let yHtmlContent = '' // '<span class="n" style="top: 2px;">0</span>'
-      let currentNum = 0
+      let xHtmlContent = ""; // '<span class="n" style="left: 2px;">0</span>'
+      let yHtmlContent = ""; // '<span class="n" style="top: 2px;">0</span>'
+      let currentNum = 0;
       while (currentNum < +this.bigscreenWidth) {
-        xHtmlContent += `<span class="n" style="left: ${currentNum + 2}px;">${currentNum}</span>`
-        currentNum += 50
+        xHtmlContent += `<span class="n" style="left: ${
+          currentNum + 2
+        }px;">${currentNum}</span>`;
+        currentNum += 50;
       }
-      currentNum = 0
+      currentNum = 0;
       while (currentNum < +this.bigscreenHeight) {
-        yHtmlContent += `<span class="n" style="top: ${currentNum + 2}px;">${currentNum}</span>`
-        currentNum += 50
+        yHtmlContent += `<span class="n" style="top: ${
+          currentNum + 2
+        }px;">${currentNum}</span>`;
+        currentNum += 50;
       }
-      vueRulerX.innerHTML = xHtmlContent
-      vueRulerY.innerHTML = yHtmlContent
+      vueRulerX.innerHTML = xHtmlContent;
+      vueRulerY.innerHTML = yHtmlContent;
     },
     /**
      * @description: 恢复
@@ -638,7 +647,13 @@ export default {
       const layerWidgetArr = [];
       for (let i = 0; i < val.length; i++) {
         const obj = {};
-        obj.icon = getToolByCode(val[i].type).icon;
+        const myItem = getToolByCode(val[i].type);
+        obj.icon = myItem.icon;
+        obj.code = myItem.code; // 组件类型code
+        obj.widgetId = val[i].value.widgetId || ""; // 唯一id
+        if (val[i].value.paramsKeys) {
+          obj.paramsKeys = val[i].value.paramsKeys;
+        }
         const options = val[i].options["setup"];
         options.forEach((el) => {
           if (el.name == "layerName") {
@@ -649,6 +664,12 @@ export default {
       }
       this.layerWidget = layerWidgetArr;
     },
+    // 返回每个组件的动态数据集参数配置情况
+    handlerdynamicDataParamsConfig(val) {
+      this.widgetParamsConfig = val.map((item) => {
+        return item.value.data;
+      });
+    },
     async initEchartData() {
       const reportCode = this.$route.query.reportCode;
       const { code, data } = await detailDashboard(reportCode);
@@ -672,7 +693,8 @@ export default {
       }
       this.setOptionsOnClickScreen();
       return {
-        backgroundColor: (data && data.backgroundColor) || "",
+        backgroundColor:
+          (data && data.backgroundColor) || (!data ? "#1e1e1e" : ""),
         backgroundImage: (data && data.backgroundImage) || "",
         height: (data && data.height) || "1080",
         title: (data && data.title) || "",
@@ -691,9 +713,20 @@ export default {
           position: widgets[i].value.position,
         };
         const tool = this.deepClone(getToolByCode(widgets[i].type));
+        if (!tool) {
+          const message =
+            "暂未提供该组件或该组件下线了,组件code: " + widgets[i].type;
+          console.error(message);
+          if (process.env.NODE_ENV === "development") {
+            // 40@remarks 看生产要不要提示
+            this.$message.error(message);
+          }
+          continue; // 找不到就跳过,避免整个报表都加载不出来
+        }
         const option = tool.options;
         const options = this.handleOptionsData(widgets[i].value, option);
         obj.options = options;
+        obj.value.widgetId = obj.value.setup.widgetId;
         widgetsData.push(obj);
       }
       return widgetsData;
@@ -753,6 +786,9 @@ export default {
         },
         widgets: this.widgets,
       };
+      screenData.widgets.forEach((widget) => {
+        widget.value.setup.widgetId = widget.value.widgetId;
+      });
       const { code, data } = await insertDashboard(screenData);
       if (code == "200") {
         this.$message.success("保存成功!");
@@ -831,9 +867,30 @@ export default {
     },
     dragStart(widgetCode) {
       this.dragWidgetCode = widgetCode;
+      this.currentWidgetTotal = this.widgets.length; // 当前操作面板上有多少各组件
     },
     dragEnd() {
       this.dragWidgetCode = "";
+      /**
+       * 40@remarks 新增组件到操作面板后,右边的配置有更新,但是当前选中的组件没更新,导致配置错乱的bug;
+       * 由于拖动组件拖到非操作面板上是不会添加组件,还需判断是否添加组件到操作面板上;
+       */
+      this.$nextTick(() => {
+        if (this.widgets.length === this.currentWidgetTotal + 1) {
+          // 确实新增了一个组件到操作面板上
+          console.log(
+            `新添加 '${
+              this.widgets[this.currentWidgetTotal].value.setup.layerName
+            }' 组件到操作面板`
+          );
+          const uuid = Number(Math.random().toString().substr(2)).toString(36);
+          this.widgets[this.currentWidgetTotal].value.widgetId = uuid;
+          this.layerWidget[this.currentWidgetTotal].widgetId = uuid;
+          const index = this.widgets.length - 1;
+          this.layerClick(index); // 选中当前新增的组件
+          this.grade = false; // 去除网格线
+        }
+      });
     },
     dragOver(evt) {
       evt.preventDefault();
@@ -855,12 +912,12 @@ export default {
       const targetScale =
         this.currentSizeRangeIndex === this.defaultSize.index
           ? this.bigscreenScaleInWorkbench
-          : this.sizeRange[this.currentSizeRangeIndex] / 100
+          : this.sizeRange[this.currentSizeRangeIndex] / 100;
       // 计算在缩放模式下的x y
       // const x = widgetLeftInWorkbench / this.bigscreenScaleInWorkbench
       // const y = widgetTopInWorkbench / this.bigscreenScaleInWorkbench
-      const x = widgetLeftInWorkbench / targetScale
-      const y = widgetTopInWorkbench / targetScale
+      const x = widgetLeftInWorkbench / targetScale;
+      const y = widgetTopInWorkbench / targetScale;
 
       // 复制一个组件
       let tool = getToolByCode(widgetType);
@@ -1077,10 +1134,28 @@ export default {
     deletelayer() {
       this.widgets.splice(this.rightClickIndex, 1);
     },
+    // 锁定
+    lockLayer() {
+      const obj = this.widgets[this.rightClickIndex];
+      this.$set(obj.value.position, "disabled", true);
+    },
+    //  解除锁定
+    noLockLayer() {
+      const obj = this.widgets[this.rightClickIndex];
+      this.$set(obj.value.position, "disabled", false);
+    },
     // 复制
     copylayer() {
       const obj = this.deepClone(this.widgets[this.rightClickIndex]);
+      obj.value.position.top += 40; // 复制的元素向右下角偏移一点
+      obj.value.position.left += 40;
+      obj.value.widgetId = Number(Math.random().toString().substr(2)).toString(
+        36
+      );
       this.widgets.splice(this.widgets.length, 0, obj);
+      this.$nextTick(() => {
+        this.layerClick(this.widgets.length - 1); // 复制后定位到最新的组件
+      });
     },
     // 置顶
     istopLayer() {
@@ -1277,7 +1352,7 @@ export default {
         &.btn-disable {
           cursor: no-drop;
           &:hover {
-            background: #20262C
+            background: #20262c;
           }
         }
       }
@@ -1382,7 +1457,6 @@ export default {
       &::-webkit-scrollbar-track-piece {
         /*修改滚动条的背景和圆角*/
         background: #29405c;
-        -webkit-border-radius: 7px;
       }
 
       &::-webkit-scrollbar-track {
@@ -1402,13 +1476,13 @@ export default {
       /*修改垂直滚动条的样式*/
       &::-webkit-scrollbar-thumb:vertical {
         background-color: #00113a;
-        -webkit-border-radius: 7px;
+        // -webkit-border-radius: 7px;
       }
 
       /*修改水平滚动条的样式*/
       &::-webkit-scrollbar-thumb:horizontal {
         background-color: #00113a;
-        -webkit-border-radius: 7px;
+        // -webkit-border-radius: 7px;
       }
     }
   }
@@ -1610,22 +1684,6 @@ li {
 
 ::-webkit-scrollbar {
   width: 0;
-}
-
-/* 滚动槽 */
-
-::-webkit-scrollbar-track {
-  -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.3);
-}
-
-/* 滚动条滑块 */
-
-::-webkit-scrollbar-thumb {
-  background: rgba(0, 0, 0, 0.1);
-  -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
-}
-
-::-webkit-scrollbar-thumb:window-inactive {
-  background: rgba(255, 0, 0, 0.4);
+  height: 10px;
 }
 </style>

+ 128 - 0
report-ui/src/views/bigscreenDesigner/designer/linkageLogic.js

@@ -0,0 +1,128 @@
+/*
+ * @Author: chengsl
+ * @Date: 2023-02-24 09:40:13
+ * @LastEditors: chengsl
+ * @LastEditTime: 2023-02-24 13:12:24
+ * @Description: 各联动组件的参数配置 参数paramsKey的值具体封装时再改
+ */
+import { eventBus as bus } from "@/utils/eventBus";
+export const lickageParamsConfig = [
+  // {
+  //   name: '按钮组',
+  //   code: 'widgetButtonGroup',
+  //   paramsKey: [] // 40@remarks 动态:[...row, index]
+  // },
+  {
+    name: '柱图',
+    code: 'widget-barchart',
+    paramsKey: ['name', 'value']
+  },
+  // ……
+  {
+    name: '折线图',
+    code: 'widget-linechart',
+    paramsKey: ['name', 'value']
+  },
+  {
+    name: '百分比图',
+    code: 'widgetPiePercentageChart',
+    paramsKey: ['value']
+  },
+]
+
+export const getOneConfigByCode = function(code) {
+  return lickageParamsConfig.find(item => { return item.code === code })
+}
+
+export const getOneConfigByName = function(name) {
+  return lickageParamsConfig.find(item => { return item.name === name })
+}
+
+/**
+ * 源组件 - 初始化联动逻辑
+ * @param self 组件实例对象 this
+ * @param isActiveClick 主动触发(非echart类click事件触发)
+ * @param buttonConfig 按钮组组件的配置
+ * 40@remarks
+ * 1、v-chart 需添加 ref="myVChart" 以获取实例
+ * 2、 发消息发过去的对象 待封装配置动态兼容
+ */
+export const originWidgetLinkageLogic = function(self, isActiveClick = false, buttonConfig = {}) {
+  // if (self.allComponentLinkage && self.allComponentLinkage.length && self.allComponentLinkage[self.widgetIndex].index !== -1 && self.allComponentLinkage[self.widgetIndex].linkageArr.length) {
+  if (self.optionsSetup.componentLinkage && self.optionsSetup.componentLinkage.length) {
+    if (isActiveClick) { // 主动触发
+      self.allComponentLinkage[self.widgetIndex].linkageArr.forEach(item => {
+        console.log(`bus_${item.originId}_${item.targetId}`, ' -联动逻辑点击-发送消息', buttonConfig)
+        bus.$emit(`bus_${item.originId}_${item.targetId}`, buttonConfig.currentData)
+      })
+    } else { // chart 组件
+      self.$refs.myVChart.chart.on('click', function(params) {
+        self.allComponentLinkage[self.widgetIndex].linkageArr.forEach(item => {
+          console.log(`bus_${item.originId}_${item.targetId}`, ' -联动逻辑点击-发送消息', params)
+          let message = {}
+          const widgetConfigTemp = getOneConfigByCode(self.value.widgetCode)
+          if (widgetConfigTemp && widgetConfigTemp.paramsKey.length) { // 动态加载各组件的参数来封装
+            widgetConfigTemp.paramsKey.forEach(key => {
+              message[key] = params[key]
+            })
+            // 40@remarks 部分组件 传参需要特殊处理下
+            // ……
+            // 40@remarks 专用于测试联动发消息 手动改造消息内容
+            // if (self.value.widgetCode === 'widgetMap2d') {
+            //   const nameTemp = ['苹果', '三星', '小米', '华为', 'OPPO', 'VIVO']
+            //   // message = {
+            //   //   name: nameTemp[(params.dataIndex % 6)],
+            //   //   value: params.value,
+            //   //   dataIndex: params.dataIndex
+            //   // }
+            //   // message.name = nameTemp[(+params.value % 6)]
+            //   message.name = nameTemp[(parseInt(Math.random() * 6) % 6)]
+            // }
+            // if (self.value.widgetCode === 'widget-piechart') {
+            //   message.name = (parseInt(Math.random() * 2) % 2) === 0 ? '深圳市' : '盐田区'
+            // }
+          } else {
+            message = {
+              name: params.name,
+              value: params.value
+            }
+          }
+          bus.$emit(`bus_${item.originId}_${item.targetId}`, message)
+        })
+      })
+    }
+  }
+}
+
+/**
+ * 目标组件 - 初始化联动逻辑
+ * @param self 组件实例对象 this
+ * @returns
+ */
+export const targetWidgetLinkageLogic = function(self) {
+  const busEvents = []
+  // 有无有关联的组件
+  if (!self.allComponentLinkage || !self.allComponentLinkage.length) return
+  self.allComponentLinkage.some(item => {
+    if (item.index !== -1 && item.linkageArr.length) {
+      item.linkageArr.some(obj => {
+        if (obj.targetId === self.value.setup.widgetId) {
+          self.hasLinkage = true
+          busEvents.push({
+            eventName: `bus_${obj.originId}_${obj.targetId}`,
+            paramsConfig: obj.paramsConfig
+          })
+          return true
+        }
+      })
+    }
+  })
+  if (self.hasLinkage) {
+    busEvents.forEach(item => {
+      bus.$on(item.eventName, e => {
+        console.log(item.eventName, ' 接收消息e', e)
+        self.setOptionsData(e, item.paramsConfig)
+      })
+    })
+  }
+}

+ 12 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/barCharts/widget-barchart.js

@@ -564,6 +564,18 @@ export const widgetBarchart = {
             },
           ],
         },
+        {
+          name: '组件联动',
+          list: [
+            {
+              type: 'componentLinkage',
+              label: '',
+              name: 'componentLinkage',
+              required: false,
+              value: []
+            }
+          ]
+        }
       ],
     ],
     // 数据

+ 3 - 3
report-ui/src/views/bigscreenDesigner/designer/tools/configure/form/widget-select.js

@@ -3,7 +3,7 @@
  * @Author: qianlishi qianlishi@anji-plus.com
  * @Date: 2023-01-09 13:02:59
  * @LastEditors: qianlishi qianlishi@anji-plus.com
- * @LastEditTime: 2023-01-12 16:44:50
+ * @LastEditTime: 2023-03-06 15:33:39
  */
 
 export const widgetSelect = {
@@ -33,7 +33,7 @@ export const widgetSelect = {
       {
         type: 'vue-color',
         label: '字体颜色',
-        name: 'color',
+        name: 'select_color',
         required: false,
         placeholder: '',
         value: '#FAD400',
@@ -41,7 +41,7 @@ export const widgetSelect = {
       {
         type: 'vue-color',
         label: '字体背景',
-        name: 'background',
+        name: 'select_fontSize',
         required: false,
         placeholder: '',
         value: 'rgba(115,170,229,.5)',

+ 12 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/lineCharts/widget-linechart.js

@@ -587,6 +587,18 @@ export const widgetLinechart = {
             },
           ],
         },
+        {
+          name: '组件联动',
+          list: [
+            {
+              type: 'componentLinkage',
+              label: '',
+              name: 'componentLinkage',
+              required: false,
+              value: []
+            }
+          ]
+        }
       ],
     ],
     // 数据

+ 12 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/percentCharts/widget-pie-percentage.js

@@ -169,6 +169,18 @@ export const widgetPiePercentage = {
               value: '#173164'
             },
           ]
+        },
+        {
+          name: '组件联动',
+          list: [
+            {
+              type: 'componentLinkage',
+              label: '',
+              name: 'componentLinkage',
+              required: false,
+              value: []
+            }
+          ]
         }
       ],
     ],

+ 4 - 3
report-ui/src/views/bigscreenDesigner/designer/tools/index.js

@@ -3,8 +3,8 @@
  * @version:
  * @Author: qianlishi
  * @Date: 2021-08-29 06:43:07
- * @LastEditors: qianlishi qianlishi@anji-plus.com
- * @LastEditTime: 2022-11-07 15:35:42
+ * @LastEditors: chengsl
+ * @LastEditTime: 2023-02-24 10:29:26
  */
 import { widgetTool } from "./main"
 const screenConfig = {
@@ -52,7 +52,7 @@ const screenConfig = {
         name: 'backgroundColor',
         required: false,
         placeholder: '',
-        value: 'rgba(45, 86, 126, 1)',
+        value: '#1E1E1E',
       },
       {
         type: 'custom-upload',
@@ -72,6 +72,7 @@ export const converArr = (data) => {
   let tempArr = [], newArr = []
   for (let i = 0; i < data.length; i++) {
     const item = data[i]
+    item.widgetId = ''
     if (tempArr.indexOf(item.type) === -1) {
       newArr.push({
         name: item.tabName,

+ 3 - 3
report-ui/src/views/bigscreenDesigner/designer/tools/main.js

@@ -3,8 +3,8 @@
  * @version:
  * @Author: qianlishi
  * @Date: 2021-08-29 07:46:46
- * @LastEditors: qianlishi qianlishi@anji-plus.com
- * @LastEditTime: 2023-01-09 13:16:19
+ * @LastEditors: chengsl
+ * @LastEditTime: 2023-02-23 15:23:20
  */
 
 import { widgetText } from "./configure/texts/widget-text"
@@ -70,7 +70,7 @@ export const widgetTool = [
   widgetLineCompare,
   widgetDecoratePie,
   widgetMoreBarLine,
-  widgetWordCloud,
+  // widgetWordCloud,
   widgetHeatmap,
   widgetRadar,
   widgetBarLineStack,

+ 25 - 2
report-ui/src/views/bigscreenDesigner/designer/widget/bar/widgetBarchart.vue

@@ -1,10 +1,11 @@
 <template>
   <div :style="styleObj">
-    <v-chart :options="options" autoresize />
+    <v-chart ref="myVChart" :options="options" autoresize />
   </div>
 </template>
 
 <script>
+import { originWidgetLinkageLogic, targetWidgetLinkageLogic } from '@/views/bigscreenDesigner/designer/linkageLogic'
 import { eventBusParams } from "@/utils/screen";
 export default {
   name: "WidgetBarchart",
@@ -12,6 +13,10 @@ export default {
   props: {
     value: Object,
     ispreview: Boolean,
+    widgetIndex: {
+      type: Number,
+      default: 0
+    }, // 当前组件,在工作区变量widgetInWorkbench中的索引
   },
   data() {
     return {
@@ -70,6 +75,9 @@ export default {
         background: this.optionsSetup.background,
       };
     },
+    allComponentLinkage() {
+      return this.$store.state.designer.allComponentLinkage
+    }
   },
   watch: {
     value: {
@@ -89,6 +97,8 @@ export default {
     this.optionsCollapse = this.value.setup;
     this.optionsSetup = this.value.setup;
     this.editorOptions();
+    targetWidgetLinkageLogic(this) // 联动-目标组件逻辑
+    originWidgetLinkageLogic(this) // 联动-源组件逻辑
 
     eventBusParams(
       this.optionsSetup,
@@ -302,9 +312,22 @@ export default {
       this.options = Object.assign({}, this.options);
     },
     // 数据解析
-    setOptionsData() {
+    setOptionsData(e, paramsConfig) {
       const optionsSetup = this.optionsSetup;
       const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      // 联动接收者逻辑开始
+      optionsData.dynamicData = optionsData.dynamicData || {} // 兼容 dynamicData undefined
+      const myDynamicData = optionsData.dynamicData
+      clearInterval(this.flagInter) // 不管咋,先干掉上一次的定时任务,避免多跑
+      if (e && optionsData.dataType !== 'staticData' && Object.keys(myDynamicData.contextData).length) {
+        const keyArr = Object.keys(myDynamicData.contextData)
+        paramsConfig.forEach(conf => {
+          if (keyArr.includes(conf.targetKey)) {
+            myDynamicData.contextData[conf.targetKey] = e[conf.originKey]
+          }
+        })
+      }
+      // 联动接收者逻辑结束
       optionsData.dataType == "staticData"
         ? this.staticDataFn(optionsData.staticData)
         : this.dynamicDataFn(optionsData.refreshTime);

+ 4 - 5
report-ui/src/views/bigscreenDesigner/designer/widget/form/widgetInput.vue

@@ -2,12 +2,13 @@
   <el-input
     ref="input"
     :style="styleObj"
-    v-model="inputValue" placeholder="请输入内容"
+    v-model="inputValue"
+    placeholder="请输入内容"
     @[eventChange]="change"
   />
 </template>
 <script>
-import {eventBus} from "@/utils/eventBus";
+import { eventBus } from "@/utils/eventBus";
 
 export default {
   name: "WidgetInput",
@@ -21,7 +22,7 @@ export default {
       optionsStyle: {},
       optionsData: {},
       optionsSetup: {},
-      options:{}
+      options: {},
     };
   },
   computed: {
@@ -44,7 +45,6 @@ export default {
         this.optionsSetup = val.setup;
         this.optionsData = val.data;
         this.optionsStyle = val.position;
-        this.setOptions()
       },
       deep: true,
     },
@@ -53,7 +53,6 @@ export default {
     this.optionsSetup = this.value.setup;
     this.optionsData = this.value.data;
     this.optionsStyle = this.value.position;
-    this.setOptions()
   },
   methods: {
     change(event) {

+ 17 - 9
report-ui/src/views/bigscreenDesigner/designer/widget/form/widgetSelect.vue

@@ -10,7 +10,7 @@
   />
 </template>
 <script>
-import {eventBus} from "@/utils/eventBus";
+import { eventBus } from "@/utils/eventBus";
 
 export default {
   name: "WidgetSelect",
@@ -24,17 +24,20 @@ export default {
       optionsStyle: {},
       optionsData: {},
       optionsSetup: {},
-      options:{}
+      options: {},
     };
   },
   computed: {
     styleObj() {
+      console.log(this.optionsSetup);
       return {
         position: this.ispreview ? "absolute" : "static",
         width: this.optionsStyle.width + "px",
         height: this.optionsStyle.height + "px",
         left: this.optionsStyle.left + "px",
         top: this.optionsStyle.top + "px",
+        background: this.optionsSetup.select_fontSize,
+        color: this.optionsSetup.select_color,
       };
     },
     eventChange() {
@@ -47,7 +50,7 @@ export default {
         this.optionsSetup = val.setup;
         this.optionsData = val.data;
         this.optionsStyle = val.position;
-        this.setOptions()
+        this.setOptions();
       },
       deep: true,
     },
@@ -56,7 +59,7 @@ export default {
     this.optionsSetup = this.value.setup;
     this.optionsData = this.value.data;
     this.optionsStyle = this.value.position;
-    this.setOptions()
+    this.setOptions();
   },
   methods: {
     change(event) {
@@ -67,13 +70,13 @@ export default {
       eventBus.$emit("eventParams", params);
     },
     setOptions() {
-        const optionsData = this.optionsData;
-        return optionsData.dataType == "staticData"
-          ? this.staticData(optionsData.staticData)
-          : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
+      const optionsData = this.optionsData;
+      return optionsData.dataType == "staticData"
+        ? this.staticData(optionsData.staticData)
+        : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
     },
     staticData(data) {
-      this.options = data
+      this.options = data;
     },
     //动态数据字典解析
     dynamicDataFn(val, refreshTime) {
@@ -108,6 +111,11 @@ export default {
 
     .el-input__inner {
       height: 100%;
+      background: inherit;
+      color: inherit;
+      &::placeholder {
+        color: inherit;
+      }
     }
   }
 }

+ 24 - 3
report-ui/src/views/bigscreenDesigner/designer/widget/line/widgetLinechart.vue

@@ -1,10 +1,11 @@
 <template>
   <div :style="styleObj">
-    <v-chart :options="options" autoresize />
+    <v-chart ref="myVChart" :options="options" autoresize />
   </div>
 </template>
 
 <script>
+import { originWidgetLinkageLogic, targetWidgetLinkageLogic } from '@/views/bigscreenDesigner/designer/linkageLogic'
 import { eventBusParams } from "@/utils/screen";
 export default {
   name: "WidgetLinechart",
@@ -12,6 +13,10 @@ export default {
   props: {
     value: Object,
     ispreview: Boolean,
+    widgetIndex: {
+      type: Number,
+      default: 0
+    }, // 当前组件,在工作区变量widgetInWorkbench中的索引
   },
   data() {
     return {
@@ -76,6 +81,9 @@ export default {
         background: this.optionsSetup.background,
       };
     },
+    allComponentLinkage() {
+      return this.$store.state.designer.allComponentLinkage
+    }
   },
   watch: {
     value: {
@@ -89,12 +97,14 @@ export default {
       deep: true,
     },
   },
-  created() {
+  mounted() {
     this.optionsStyle = this.value.position;
     this.optionsData = this.value.data;
     this.optionsCollapse = this.value.collapse;
     this.optionsSetup = this.value.setup;
     this.editorOptions();
+    targetWidgetLinkageLogic(this) // 联动-目标组件逻辑
+    originWidgetLinkageLogic(this) // 联动-源组件逻辑
     eventBusParams(
       this.optionsSetup,
       this.optionsData,
@@ -299,8 +309,19 @@ export default {
       this.options = Object.assign({}, this.options);
     },
     // 处理数据
-    setOptionsData() {
+    setOptionsData(e, paramsConfig) {
       const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      optionsData.dynamicData = optionsData.dynamicData || {} // 兼容 dynamicData undefined
+      const myDynamicData = optionsData.dynamicData
+      clearInterval(this.flagInter) // 不管咋,先干掉上一次的定时任务,避免多跑
+      if (e && optionsData.dataType !== 'staticData' && Object.keys(myDynamicData.contextData).length) {
+        const keyArr = Object.keys(myDynamicData.contextData)
+        paramsConfig.forEach(conf => {
+          if (keyArr.includes(conf.targetKey)) {
+            myDynamicData.contextData[conf.targetKey] = e[conf.originKey]
+          }
+        })
+      }
       optionsData.dataType == "staticData"
         ? this.staticDataFn(optionsData.staticData)
         : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);

+ 24 - 2
report-ui/src/views/bigscreenDesigner/designer/widget/percent/widgetPiePercentageChart.vue

@@ -1,10 +1,11 @@
 <template>
   <div :style="styleObj">
-    <v-chart :options="options" autoresize />
+    <v-chart ref="myVChart" :options="options" autoresize />
   </div>
 </template>
 
 <script>
+import { targetWidgetLinkageLogic } from '@/views/bigscreenDesigner/designer/linkageLogic'
 import { eventBusParams } from "@/utils/screen";
 let per = 60;
 export default {
@@ -13,6 +14,10 @@ export default {
   props: {
     value: Object,
     ispreview: Boolean,
+    widgetIndex: {
+      type: Number,
+      default: 0
+    }, // 当前组件,在工作区变量widgetInWorkbench中的索引
   },
   data() {
     return {
@@ -325,6 +330,9 @@ export default {
         background: this.optionsSetup.background,
       };
     },
+    allComponentLinkage() {
+      return this.$store.state.designer.allComponentLinkage
+    }
   },
   watch: {
     value: {
@@ -358,6 +366,7 @@ export default {
               this.angle = this.angle + 3
               myChart.setOption(options,true)
             }, 1000);*/
+    targetWidgetLinkageLogic(this) // 联动-目标组件逻辑
   },
   methods: {
     //轴point设置
@@ -437,8 +446,21 @@ export default {
       line["lineStyle"] = lineStyle;
     },
     // 数据解析
-    setOptionsData() {
+    setOptionsData(e, paramsConfig) {
       const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      optionsData.dynamicData = optionsData.dynamicData || {} // 兼容 dynamicData undefined
+
+      const myDynamicData = optionsData.dynamicData
+      clearInterval(this.flagInter) // 不管咋,先干掉上一次的定时任务,避免多跑
+      if (e && optionsData.dataType !== 'staticData' && Object.keys(myDynamicData.contextData).length) {
+        const keyArr = Object.keys(myDynamicData.contextData)
+        paramsConfig.forEach(conf => {
+          if (keyArr.includes(conf.targetKey)) {
+            myDynamicData.contextData[conf.targetKey] = e[conf.originKey]
+          }
+        })
+      }
+
       optionsData.dataType == "staticData"
         ? this.staticDataFn(optionsData.staticData)
         : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);

+ 5 - 1
report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue

@@ -6,7 +6,7 @@
  !-->
 <template>
   <div>
-    <component :is="type" :value="value" :ispreview="true" />
+    <component :is="type" :value="value" :ispreview="true" :widget-index="index" />
   </div>
 </template>
 
@@ -90,6 +90,10 @@ export default {
       type: [Object],
       default: () => {},
     },
+    index: {
+      type: Number,
+      default: 0
+    }, // 当前组件,在工作区变量widgetInWorkbench中的索引
   },
   data() {
     return {};

+ 6 - 8
report-ui/src/views/bigscreenDesigner/designer/widget/widget.vue

@@ -1,14 +1,9 @@
-<!--
- * @Author: lide1202@hotmail.com
- * @Date: 2021-3-13 11:04:24
- * @Last Modified by:   lide1202@hotmail.com
- * @Last Modified time: 2021-3-13 11:04:24
- !-->
 <template>
   <avue-draggable
     :step="step"
     :width="widgetsWidth"
     :height="widgetsHeight"
+    :disabled="widgetDisabled"
     :left="widgetsLeft"
     :top="widgetsTop"
     ref="draggable"
@@ -17,7 +12,7 @@
     @blur="handleBlur"
   >
     <!-- :z-index="-1" -->
-    <component :is="type" :value="value" />
+    <component :is="type" :widget-index="index" :value="value" />
   </avue-draggable>
 </template>
 
@@ -89,7 +84,7 @@ export default {
     widgetRadar,
     widgetBarLineStackChart,
     widgetSelect,
-    widgetInput
+    widgetInput,
   },
   model: {
     prop: "value",
@@ -136,6 +131,9 @@ export default {
     widgetsZIndex() {
       return this.value.position.zIndex || 1;
     },
+    widgetDisabled() {
+      return this.value.position.disabled || false;
+    },
   },
   mounted() {},
   methods: {

+ 11 - 0
report-ui/src/views/bigscreenDesigner/viewer/index.vue

@@ -12,6 +12,7 @@
         v-for="(widget, index) in widgets"
         :key="index"
         v-model="widget.value"
+        :index="index"
         :type="widget.type"
       />
     </div>
@@ -56,6 +57,16 @@ export default {
         transform: `scale(${ratioEquipment}, ${ratioEquipment})`,
         "transform-origin": "0 0"
       };
+      data.dashboard.widgets.forEach((item, index) => {
+        item.value.widgetId = item.value.setup.widgetId
+        if (item.value.setup.componentLinkage && item.value.setup.componentLinkage.length) {
+          this.$store.commit('SET_ALL_COMPONENT_LINKAGE', {
+            index,
+            widgetId: item.value.widgetId,
+            linkageArr: item.value.setup.componentLinkage
+          })
+        }
+      })
       this.widgets = data.dashboard.widgets;
     }
   }