Bladeren bron

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

Raod 2 jaren geleden
bovenliggende
commit
d988e42322

+ 2 - 2
report-ui/config/dev.env.js

@@ -4,6 +4,6 @@ const prodEnv = require('./prod.env')
 
 module.exports = merge(prodEnv, {
   NODE_ENV: '"development"',
-  BASE_API: '"http://127.0.0.1:9095"'
-  // BASE_API: '"http://10.108.26.197:9095"'
+  // BASE_API: '"http://127.0.0.1:9095"'
+  BASE_API: '"http://10.108.26.197:9095"'
 })

+ 508 - 0
report-ui/src/assets/styles/screen.scss

@@ -0,0 +1,508 @@
+.mr10 {
+  margin-right: 10px;
+}
+
+.ml20 {
+  margin-left: 20px;
+}
+
+.border-right {
+  border-right: 1px solid #273b4d;
+}
+
+.border-left {
+  border-left: 1px solid #273b4d;
+}
+
+.el-icon-arrow-down {
+  font-size: 10px;
+}
+
+.is-active {
+  background: #31455d !important;
+  color: #bfcbd9 !important;
+}
+
+.layout {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  width: 100%;
+  height: 100%;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  overflow: hidden;
+
+  .layout-left {
+    display: inline-block;
+    height: 100%;
+    box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    border: 0px;
+    background-color: #263445;
+
+    //工具栏一个元素
+    .tools-item {
+      display: flex;
+      position: relative;
+      width: 100%;
+      height: 48px;
+      align-items: center;
+      -webkit-box-align: center;
+      padding: 0 6px;
+      cursor: pointer;
+      font-size: 12px;
+      margin-bottom: 1px;
+
+      .tools-item-icon {
+        color: #409eff;
+        margin-right: 10px;
+        width: 53px;
+        height: 30px;
+        line-height: 30px;
+        text-align: center;
+        display: block;
+        border: 1px solid #3a4659;
+        background: #282a30;
+      }
+
+      .tools-item-text {}
+    }
+  }
+
+  .layout-left-fold {
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    height: 100%;
+
+    font-size: 12px;
+    overflow: hidden;
+    background-color: #242a30;
+    cursor: pointer;
+    padding-top: 26%;
+
+    i {
+      font-size: 18px;
+      width: 18px;
+      height: 23px;
+      margin-left: 0px;
+      color: #bfcbd9;
+    }
+  }
+
+  .layout-middle {
+    // display: flex;
+    position: relative;
+    //width: calc(100% - 445px);
+    height: 100%;
+    background-color: rgb(36, 42, 48);
+    box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    border: 1px solid rgb(36, 42, 48);
+    align-items: center;
+    vertical-align: middle;
+    text-align: center;
+
+    .top-button {
+      display: flex;
+      flex-direction: row;
+      height: 40px;
+      line-height: 40px;
+      margin-left: 9px;
+
+      .btn {
+        color: #788994;
+        width: 55px;
+        text-align: center;
+        display: block;
+        cursor: pointer;
+
+        .el-icon-arrow-down {
+          transform: rotate(0deg);
+          -ms-transform: rotate(0deg);
+          /* IE 9 */
+          -moz-transform: rotate(0deg);
+          /* Firefox */
+          -webkit-transform: rotate(0deg);
+          /* Safari 和 Chrome */
+          -o-transform: rotate(0deg);
+          /* Opera */
+          transition: all 0.4s ease-in-out;
+        }
+
+        &:hover {
+          background: rgb(25, 29, 34);
+
+          .el-icon-arrow-down {
+            transform: rotate(180deg);
+            -ms-transform: rotate(180deg);
+            /* IE 9 */
+            -moz-transform: rotate(180deg);
+            /* Firefox */
+            -webkit-transform: rotate(180deg);
+            /* Safari 和 Chrome */
+            -o-transform: rotate(180deg);
+            /* Opera */
+            transition: all 0.4s ease-in-out;
+          }
+        }
+      }
+
+      .btn-disable {
+        opacity: 0.3;
+        cursor: no-drop;
+      }
+
+      .scale-num {
+        color: #788994;
+        opacity: 1;
+        cursor: pointer;
+
+        &.btn-disable {
+          cursor: no-drop;
+
+          &:hover {
+            background: #20262c;
+          }
+        }
+      }
+    }
+
+    .workbench-container {
+      position: relative;
+      -webkit-transform-origin: 0 0;
+      transform-origin: 0 0;
+      -webkit-box-sizing: border-box;
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+      overflow: auto;
+
+      .vueRuler {
+        // width: 100%;
+        // padding: 18px 0px 0px 18px;
+        padding: 0;
+      }
+
+      .workbench {
+        background-color: #1e1e1e;
+        position: relative;
+        -webkit-user-select: none;
+        -moz-user-select: none;
+        -ms-user-select: none;
+        user-select: none;
+        -webkit-transform-origin: 0 0;
+        transform-origin: 0 0;
+        margin: 0;
+        padding: 0;
+      }
+
+      .bg-grid {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-size: 30px 30px, 30px 30px;
+        background-image: linear-gradient(hsla(0, 0%, 100%, 0.1) 1px,
+            transparent 0),
+          linear-gradient(90deg, hsla(0, 0%, 100%, 0.1) 1px, transparent 0);
+        // z-index: 2;
+      }
+    }
+
+    .bottom-text {
+      width: 100%;
+      color: #a0a0a0;
+      font-size: 16px;
+      position: absolute;
+      bottom: 20px;
+    }
+  }
+
+  .layout-right {
+    display: inline-block;
+    height: 100%;
+  }
+
+  /deep/ .el-tabs--border-card {
+    border: 0;
+
+    .el-tabs__header {
+      .el-tabs__nav {
+        .el-tabs__item {
+          background-color: #242f3b;
+          border: 0px;
+        }
+
+        .el-tabs__item.is-active {
+          background-color: #31455d;
+        }
+      }
+    }
+
+    .el-tabs__content {
+      background-color: #242a30;
+      height: calc(100vh - 39px);
+      overflow-x: hidden;
+      overflow-y: auto;
+
+      .el-tab-pane {
+        color: #bfcbd9;
+      }
+
+      &::-webkit-scrollbar {
+        width: 5px;
+        height: 14px;
+      }
+
+      &::-webkit-scrollbar-track,
+      &::-webkit-scrollbar-thumb {
+        border-radius: 1px;
+        border: 0 solid transparent;
+      }
+
+      &::-webkit-scrollbar-track-piece {
+        /*修改滚动条的背景和圆角*/
+        background: #29405c;
+      }
+
+      &::-webkit-scrollbar-track {
+        box-shadow: 1px 1px 5px rgba(116, 148, 170, 0.5) inset;
+      }
+
+      &::-webkit-scrollbar-thumb {
+        min-height: 20px;
+        background-clip: content-box;
+        box-shadow: 0 0 0 5px rgba(116, 148, 170, 0.5) inset;
+      }
+
+      &::-webkit-scrollbar-corner {
+        background: transparent;
+      }
+
+      /*修改垂直滚动条的样式*/
+      &::-webkit-scrollbar-thumb:vertical {
+        background-color: #00113a;
+        // -webkit-border-radius: 7px;
+      }
+
+      /*修改水平滚动条的样式*/
+      &::-webkit-scrollbar-thumb:horizontal {
+        background-color: #00113a;
+        // -webkit-border-radius: 7px;
+      }
+    }
+  }
+}
+
+ul,
+li {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+
+.nav {
+  width: 40px;
+  padding: 0;
+  list-style: none;
+  /* overflow: hidden; */
+}
+
+.nav {
+  zoom: 1;
+}
+
+.nav:before,
+.nav:after {
+  content: "";
+  display: table;
+}
+
+.nav:after {
+  clear: both;
+}
+
+.nav>li {
+  width: 55px;
+  text-align: left;
+  position: relative;
+}
+
+.nav>li a {
+  float: left;
+  padding: 12px 30px;
+  color: #999;
+  font: bold 12px;
+  text-decoration: none;
+}
+
+.nav>li:hover {
+  color: #788994;
+}
+
+.nav>li ul {
+  visibility: hidden;
+  position: absolute;
+  z-index: 1000;
+  list-style: none;
+  left: 0;
+  padding: 0;
+  background-color: rgb(36, 42, 48);
+  opacity: 0;
+  _margin: 0;
+  width: 120px;
+  transition: all 0.2s ease-in-out;
+}
+
+.nav>li:hover>ul {
+  opacity: 1;
+  visibility: visible;
+  margin: 0;
+
+  li:hover {
+    background-color: rgb(25, 29, 34);
+  }
+}
+
+.nav ul li {
+  float: left;
+  display: block;
+  border: 0;
+  width: 100%;
+  font-size: 12px;
+}
+
+.nav ul a {
+  padding: 10px;
+  width: 100%;
+  display: block;
+  float: none;
+  height: 120px;
+  border: 1px solid #30445c;
+  background-color: rgb(25, 29, 34);
+  transition: all 0.2s ease-in-out;
+}
+
+.nav ul a:hover {
+  border: 1px solid #3c5e88;
+}
+
+.nav ul li:first-child>a:hover:before {
+  border-bottom-color: #04acec;
+}
+
+.nav ul ul {
+  top: 0;
+  left: 120px;
+  width: 400px;
+  height: 300px;
+  overflow: auto;
+  padding: 10px;
+  _margin: 0;
+}
+
+.nav ul ul li {
+  width: 120px;
+  height: 120px;
+  margin-right: 3px;
+  display: block;
+  float: left;
+}
+
+.nav .item {
+  padding: 5px;
+}
+
+/deep/ .vue-ruler-h {
+  opacity: 0.3;
+}
+
+/deep/ .vue-ruler-v {
+  opacity: 0.3;
+}
+
+.layout-left {
+  width: 200px;
+  background: #242a30;
+  overflow-x: hidden;
+  overflow-y: auto;
+
+  .chart-type {
+    display: flex;
+    flex-direction: row;
+    overflow: hidden;
+
+    .type-left {
+      width: 100%;
+      height: calc(100vh - 80px);
+      text-align: center;
+
+      /deep/.el-tabs__header {
+        width: 30%;
+        margin-right: 0;
+
+        .el-tabs__nav-wrap {
+          &::after {
+            background: transparent;
+          }
+
+          .el-tabs__item {
+            text-align: center;
+            width: 100% !important;
+            color: #fff;
+            padding: 0;
+            font-size: 12px !important;
+          }
+        }
+      }
+
+      /deep/.el-tabs__content {
+        width: 70%;
+      }
+    }
+  }
+
+  //工具栏一个元素
+  .tools-item {
+    display: flex;
+    position: relative;
+    width: 100%;
+    height: 48px;
+    align-items: center;
+    -webkit-box-align: center;
+    padding: 0 6px;
+    cursor: pointer;
+    font-size: 12px;
+    margin-bottom: 1px;
+
+    .tools-item-icon {
+      color: #409eff;
+      margin-right: 10px;
+      width: 53px;
+      height: 30px;
+      line-height: 30px;
+      text-align: center;
+      display: block;
+      border: 1px solid #3a4659;
+      background: #282a30;
+    }
+
+    .tools-item-text {
+      font-size: 12px !important;
+    }
+  }
+
+  /deep/.el-tabs__content {
+    padding: 0;
+  }
+}
+
+/* 设置滚动条的样式 */
+
+::-webkit-scrollbar {
+  width: 0;
+  height: 10px;
+}

+ 36 - 34
report-ui/src/mixins/common.js

@@ -1,40 +1,40 @@
 import Cookies from 'js-cookie'
 import { getStorageItem } from '@/utils/storage'
 export default {
-  data () {
+  data() {
     return {
     }
   },
   computed: {
     // 网页高度
-    bodyWidth () {
+    bodyWidth() {
       return document.body.clientWidth
     },
     // 网页宽度
-    bodyHeight () {
+    bodyHeight() {
       return document.body.clientHeight
     },
   },
-  created () {
+  created() {
   },
-  mounted () {
+  mounted() {
   },
-  destroyed () {
+  destroyed() {
   },
   methods: {
-    setCookies (key, val, option) {
+    setCookies(key, val, option) {
       if (option == null) {
         option = { expires: 15 }
       }
       Cookies.set(key, val, option)
     },
-    goBack () {
+    goBack() {
       this.$router.go(-1)
     },
-    refresh () {
+    refresh() {
       this.$router.go(0)
     },
-    parseString (object) {
+    parseString(object) {
       if (typeof object === 'undefined' || object == null) {
         return ''
       }
@@ -49,7 +49,7 @@ export default {
       }
       return ''
     },
-    isBlank (val) {
+    isBlank(val) {
       if (typeof val === 'undefined') {
         return true
       }
@@ -59,7 +59,7 @@ export default {
       return false
     },
     // 封装定制删除数组中的值
-    contains (a, obj) {
+    contains(a, obj) {
       let i = a.length
       while (i--) {
         if (a[i] === obj) {
@@ -82,13 +82,13 @@ export default {
     /**
      *
      */
-    resetForm (data) {
+    resetForm(data) {
       let formKeys = Object.keys(data)
       for (let k of formKeys) {
         data[k] = null
       }
     },
-    sortArray (propertyName) {
+    sortArray(propertyName) {
       return function (object1, object2) {
         let value1 = object1[propertyName];
         let value2 = object2[propertyName];
@@ -103,7 +103,7 @@ export default {
       }
     },
     // 获取对象类型
-    getObjectType (obj) {
+    getObjectType(obj) {
       let toString = Object.prototype.toString
       let map = {
         '[object Boolean]': 'boolean',
@@ -122,23 +122,22 @@ export default {
       }
       return map[toString.call(obj)]
     },
-    isNumber (obj) {
+    isNumber(obj) {
       return this.getObjectType(obj) == 'number'
     },
-    isString (obj) {
+    isString(obj) {
       return this.getObjectType(obj) == 'string'
     },
-    isArray (obj) {
+    isArray(obj) {
       return this.getObjectType(obj) == 'array'
     },
-    hasOwn (obj, key) {
+    hasOwn(obj, key) {
       return Object.prototype.hasOwnProperty.call(obj, key)
     },
-
-    isNotBlank (val) {
+    isNotBlank(val) {
       return !this.isBlank(val)
     },
-    isBlank (val) {
+    isBlank(val) {
       if (this.isNull(val)) {
         return true
       }
@@ -153,10 +152,10 @@ export default {
       }
       return false
     },
-    isNotNull (val) {
+    isNotNull(val) {
       return !this.isNull(val)
     },
-    isNull (val) {
+    isNull(val) {
       // 特殊判断
       if (val && parseInt(val) === 0) return false
       const list = ['$parent']
@@ -182,7 +181,7 @@ export default {
     },
 
     // 对象深拷贝
-    deepClone (data) {
+    deepClone(data) {
       let type = this.getObjectType(data)
       let obj
       if (type === 'array') {
@@ -218,7 +217,7 @@ export default {
     },
 
     // 合并json
-    mergeObject () {
+    mergeObject() {
       let target = arguments[0] || {}
       let deep = false
       let arr = Array.prototype.slice.call(arguments)
@@ -261,7 +260,7 @@ export default {
     },
 
     // 获取dom在屏幕中的top和left
-    getDomTopLeftById (id) {
+    getDomTopLeftById(id) {
       let dom = document.getElementById(id)
       let top = 0
       let left = 0
@@ -271,7 +270,7 @@ export default {
       }
       return { top: top, left: left }
     },
-    objToOne (obj) {
+    objToOne(obj) {
       console.log(obj)
       let tmpData = {}
       for (let index in obj) {
@@ -291,13 +290,16 @@ export default {
         return Object.prototype.toString.call(value) === "[object Array]";
       }
     },
-    urlEncode (val) {
+    isObjectFn(value) {
+      return Object.prototype.toString.call(value) === "[object Object]";
+    },
+    urlEncode(val) {
       return encodeURIComponent(val)
     },
-    urlDecode (val) {
+    urlDecode(val) {
       return decodeURIComponent(val)
     },
-    urlEncodeObject (obj, ingoreFields) {
+    urlEncodeObject(obj, ingoreFields) {
       if (toString.call(obj) != '[object Object]') {
         return obj
       }
@@ -316,7 +318,7 @@ export default {
     },
 
     // 根据数据字典,查询指定字典dict指定值code的,返回整个dictItem{id, text, extend}
-    getDictItemByCode (dict, code) {
+    getDictItemByCode(dict, code) {
       let dicts = getStorageItem('AJReportDict')
       if (!dicts.hasOwnProperty(dict)) {
         return null
@@ -334,7 +336,7 @@ export default {
       return null
     },
     // 根据数据字典,查询指定字典dict指定值code的dictItem.text
-    getDictLabelByCode (dict, code) {
+    getDictLabelByCode(dict, code) {
       let dictItem = this.getDictItemByCode(dict, code)
       if (dictItem != null) {
         return dictItem['text']
@@ -343,7 +345,7 @@ export default {
       }
     },
     // 根据数据字典,查询指定字典dict指定值code的dictItem.extend
-    getDictExtendByCode (dict, code) {
+    getDictExtendByCode(dict, code) {
       let dictItem = this.getDictItemByCode(dict, code)
       if (dictItem == null) {
         return null

+ 355 - 0
report-ui/src/utils/screenMixins.js

@@ -0,0 +1,355 @@
+import { Revoke } from "@/utils/revoke";
+import { getToken } from "@/utils/auth";
+import { getToolByCode } from "@/views/bigscreenDesigner/designer/tools/index";
+import { insertDashboard, detailDashboard, exportDashboard, } from "@/api/bigscreen";
+const mixin = {
+  data() {
+    return {
+      reportCode: this.$route.query.reportCode,
+      uploadUrl: process.env.BASE_API + "/reportDashboard/import/" + this.reportCode,
+      rightClickIndex: -1,
+    }
+  },
+  computed: {
+    step() {
+      return Number(100 / (this.bigscreenScaleInWorkbench * 100));
+    },
+    headers() {
+      return {
+        Authorization: getToken(),
+      };
+    },
+    // 初始的缩放百分比 和 下标
+    defaultSize() {
+      const obj = {
+        index: -1,
+        size: "50",
+      };
+      this.sizeRange.some((item, index) => {
+        if (item <= 100 * this.bigscreenScaleInWorkbench) {
+          obj.index = index;
+          obj.size = 100 * this.bigscreenScaleInWorkbench;
+        }
+      });
+      if (obj.index === -1) {
+        obj.index = 0;
+        obj.size = this.sizeRange[0];
+      }
+      return obj;
+    },
+  },
+  watch: {
+    defaultSize: {
+      handler(val) {
+        if (val !== -1) {
+          this.currentSizeRangeIndex = val.index;
+          this.scaleNum = val.size;
+        }
+      },
+      immediate: true,
+    },
+    bigscreenWidth() {
+      this.initVueRulerTool();
+    },
+    bigscreenHeight() {
+      this.initVueRulerTool();
+    },
+  },
+  created() {
+    this.revoke = new Revoke();
+    this.getData();
+  },
+  methods: {
+    /**
+  * @param num: 0缩小 1放大 2默认比例
+  * sizeRange: [20, 40, 60, 72, 100, 150, 200, 300, 400]
+  */
+    setSize(num) {
+      switch (num) {
+        case 0: this.currentSizeRangeIndex === 0 ? '' : this.currentSizeRangeIndex -= 1;
+          break;
+        case 1: this.currentSizeRangeIndex === 8 ? '' : this.currentSizeRangeIndex += 1;
+          break;
+        case 2: this.currentSizeRangeIndex = this.defaultSize.index;
+      }
+      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"); // 纵向标尺
+      contentDom.style.width = "100%";
+      contentDom.style.height = "100%";
+
+      let xHtmlContent = "";
+      let yHtmlContent = "";
+      let currentNum = 0;
+      while (currentNum < +this.bigscreenWidth) {
+        xHtmlContent += `<span class="n" style="left: ${currentNum + 2}px;">${currentNum}</span>`;
+        currentNum += 50;
+      }
+      currentNum = 0;
+      while (currentNum < +this.bigscreenHeight) {
+        yHtmlContent += `<span class="n" style="top: ${currentNum + 2}px;">${currentNum}</span>`;
+        currentNum += 50;
+      }
+      vueRulerX.innerHTML = xHtmlContent;
+      vueRulerY.innerHTML = yHtmlContent;
+    },
+    // 初始化接口数据
+    async getData() {
+      const { code, data } = await detailDashboard(this.reportCode);
+      if (code != 200) return;
+      this.widgets = this.initWidgetsData(data);
+      this.dashboard = this.initScreenData(data.dashboard);
+      this.bigscreenWidth = this.dashboard.width;
+      this.bigscreenHeight = this.dashboard.height;
+    },
+    // 组件数据
+    initWidgetsData(data) {
+      const widgets = data.dashboard ? data.dashboard.widgets : [];
+      const widgetsData = [];
+      for (let i = 0; i < widgets.length; i++) {
+        const widget = widgets[i]
+        const { setup, data, position } = { ...widget.value }
+        const obj = {
+          type: widget.type,
+          value: { setup, data, position }
+        };
+        const tool = this.deepClone(getToolByCode(widget.type));
+        if (!tool) {
+          const message = "暂未提供该组件或该组件下线了,组件code: " + widget.type;
+          if (process.env.NODE_ENV === "development") {
+            this.$message.error(message);
+          }
+          continue; // 找不到就跳过,避免整个报表都加载不出来
+        }
+        obj.options = this.setDefaultWidgetConfigValue(widget.value, tool.options);
+        obj.value.widgetId = obj.value.setup.widgetId;
+        widgetsData.push(obj);
+      }
+      return widgetsData;
+    },
+    // 重写默认数据
+    setDefaultWidgetConfigValue(data, option) {
+      this.setConfigValue(data.setup, option.setup)
+      this.setConfigValue(data.position, option.position)
+      this.setConfigValue(data.data, option.data)
+      return option;
+    },
+    setConfigValue(objValue, setup) {
+      Object.keys(objValue).forEach(key => {
+        setup.forEach(item => {
+          if (this.isObjectFn(item) && key == item.name) {
+            item.value = objValue[key]
+          }
+          if (this.isArrayFn(item)) {
+            item.forEach(itemChild => {
+              itemChild.list.forEach(el => {
+                if (key == el.name) {
+                  el.value = objValue[key]
+                }
+              })
+            })
+          }
+        })
+      })
+    },
+    // 大屏数据
+    initScreenData(data) {
+      const optionScreen = getToolByCode("screen").options;
+      this.setConfigValue(data, optionScreen.setup)
+      this.setOptionsOnClickScreen();
+      return {
+        backgroundColor:
+          (data && data.backgroundColor) || (!data ? "#1e1e1e" : ""),
+        backgroundImage: (data && data.backgroundImage) || "",
+        height: (data && data.height) || "1080",
+        title: (data && data.title) || "",
+        width: (data && data.width) || "1920",
+      };
+    },
+    // 保存数据
+    async saveData() {
+      if (!this.widgets || this.widgets.length == 0) {
+        return this.$message.error("请添加组件");
+      }
+      const { title, width, height, backgroundColor, backgroundImage } = { ...this.dashboard }
+      const screenData = {
+        reportCode: this.reportCode,
+        dashboard: { title, width, height, backgroundColor, backgroundImage },
+        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("保存成功!");
+      }
+    },
+    // 预览
+    viewScreen() {
+      let routeUrl = this.$router.resolve({
+        path: "/bigscreen/viewer",
+        query: { reportCode: this.reportCode },
+      });
+      window.open(routeUrl.href, "_blank");
+    },
+    async exportDashboard(val) {
+      const fileName = this.reportCode + ".zip";
+
+      const param = {
+        reportCode: this.reportCode,
+        showDataSet: val,
+      };
+      exportDashboard(param).then((res) => {
+        const that = this;
+        const type = res.type;
+        if (type == "application/json") {
+          let reader = new FileReader();
+          reader.readAsText(res, "utf-8");
+          reader.onload = function () {
+            const data = JSON.parse(reader.result);
+            that.$message.error(data.message);
+          };
+          return;
+        }
+        const blob = new Blob([res], { type: "application/octet-stream" });
+        if (window.navigator.msSaveOrOpenBlob) {
+          //msSaveOrOpenBlob方法返回bool值
+          navigator.msSaveBlob(blob, fileName); //本地保存
+        } else {
+          const link = document.createElement("a"); //a标签下载
+          link.href = window.URL.createObjectURL(blob);
+          link.download = fileName;
+          link.click();
+          window.URL.revokeObjectURL(link.href);
+        }
+      });
+    },
+    handleUndo() {
+      const record = this.revoke.undo();
+      if (!record) {
+        return false;
+      }
+      this.widgets = record;
+    },
+    handleRedo() {
+      const record = this.revoke.redo();
+      if (!record) {
+        return false;
+      }
+      this.widgets = record;
+    },
+    handleUpload(response, file, fileList) {
+      this.$refs.upload.clearFiles();
+      this.initEchartData();
+      if (response.code == "200") {
+        this.$message({
+          message: "导入成功!",
+          type: "success",
+        });
+      } else {
+        this.$message({
+          message: response.message,
+          type: "error",
+        });
+      }
+    },
+    handleError(err) {
+      this.$message({
+        message: "上传失败!",
+        type: "error",
+      });
+    },
+    // 右键
+    rightClick(event, index) {
+      this.rightClickIndex = index;
+      const left = event.clientX;
+      const top = event.clientY;
+      if (left || top) {
+        this.styleObj = {
+          left: left + "px",
+          top: top + "px",
+          display: "block",
+        };
+      }
+      this.visibleContentMenu = true;
+      return false;
+    },
+    // 数组 元素互换位置
+    swapArr(arr, oldIndex, newIndex) {
+      arr[oldIndex] = arr.splice(newIndex, 1, arr[oldIndex])[0];
+      return arr;
+    },
+    // 删除
+    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() {
+      if (this.rightClickIndex + 1 < this.widgets.length) {
+        const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
+        this.widgets.push(temp);
+      }
+    },
+    // 置底
+    setlowLayer() {
+      if (this.rightClickIndex != 0) {
+        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
+      }
+    },
+    // 上移一层
+    moveupLayer() {
+      if (this.rightClickIndex != 0) {
+        this.widgets[this.rightClickIndex] = this.widgets.splice(
+          this.rightClickIndex - 1,
+          1,
+          this.widgets[this.rightClickIndex]
+        )[0];
+      } else {
+        this.widgets.push(this.widgets.shift());
+      }
+    },
+    // 下移一层
+    movedownLayer() {
+      if (this.rightClickIndex != this.widgets.length - 1) {
+        this.widgets[this.rightClickIndex] = this.widgets.splice(
+          this.rightClickIndex + 1,
+          1,
+          this.widgets[this.rightClickIndex]
+        )[0];
+      } else {
+        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
+      }
+    },
+  }
+}
+
+export default mixin

+ 11 - 929
report-ui/src/views/bigscreenDesigner/designer/index.vue

@@ -130,13 +130,9 @@
             content="缩小"
             placement="bottom"
           >
-            <!-- <svg-icon style="font-size:16px;" icon-class="jianhao" class-name="icon" /> -->
             <i class="el-icon-minus" style="font-size: 16px" />
           </el-tooltip>
         </span>
-        <!--
-          class="btn scale-num"
-          :style="currentSizeRangeIndex === defaultSize.index ? 'cursor: no-drop;' : ''" -->
         <span
           :class="{
             btn: true,
@@ -169,7 +165,6 @@
             content="放大"
             placement="bottom"
           >
-            <!-- <svg-icon style="font-size:16px;" icon-class="jiahao" class-name="icon" /> -->
             <i class="el-icon-plus" style="font-size: 16px" />
           </el-tooltip>
         </span>
@@ -228,10 +223,6 @@
         </span>
       </div>
       <!-- 中间操作内容  主体 -->
-      <!-- :style="{
-          width: bigscreenWidthInWorkbench + 'px',
-          height: bigscreenHeightInWorkbench + 'px',
-        }" -->
       <div class="workbench-container" @mousedown="handleMouseDown">
         <div
           :style="{
@@ -359,20 +350,13 @@
 </template>
 
 <script>
-import {
-  insertDashboard,
-  detailDashboard,
-  importDashboard,
-  exportDashboard,
-} from "@/api/bigscreen";
 import { widgetTools, getToolByCode } from "./tools/index";
+import mixin from "@/utils/screenMixins";
 import widget from "./widget/widget.vue";
 import dynamicForm from "./components/dynamicForm.vue";
 import draggable from "vuedraggable";
 import VueRulerTool from "vue-ruler-tool"; // 大屏设计页面的标尺插件
 import contentMenu from "./components/contentMenu";
-import { getToken } from "@/utils/auth";
-import { Revoke } from "@/utils/revoke"; //处理历史记录 2022-02-22
 
 export default {
   name: "Login",
@@ -383,12 +367,9 @@ export default {
     dynamicForm,
     contentMenu,
   },
+  mixins: [mixin],
   data() {
     return {
-      uploadUrl:
-        process.env.BASE_API +
-        "/reportDashboard/import/" +
-        this.$route.query.reportCode,
       grade: false,
       layerWidget: [],
       widgetTools: widgetTools, // 左侧工具栏的组件图标,将js变量加入到当前作用域
@@ -401,19 +382,7 @@ export default {
       bigscreenWidth: 1920, // 大屏设计的大小
       bigscreenHeight: 1080,
       revoke: null, //处理历史记录 2022-02-22
-
-      // 工作台大屏画布,保存到表gaea_report_dashboard中
-      dashboard: {
-        id: null,
-        title: "", // 大屏页面标题
-        width: 1920, // 大屏设计宽度
-        height: 1080, // 大屏设计高度
-        backgroundColor: "#1E1E1E", // 大屏背景色
-        backgroundImage: "", // 大屏背景图片
-        refreshSeconds: null, // 大屏刷新时间间隔
-        presetLine: [], // 辅助线
-        presetLineVisible: true, // 辅助线是否显示
-      },
+      dashboard: {},
       // 大屏的标记
       screenCode: "",
       dragWidgetCode: "", //从工具栏拖拽的组件code
@@ -437,7 +406,6 @@ export default {
           options: [],
         },
       ], // 工作区中拖放的组件
-
       // 当前激活组件
       widgetIndex: 0,
       // 当前激活组件右侧配置属性
@@ -452,7 +420,7 @@ export default {
         top: 0,
       },
       visibleContentMenu: false,
-      rightClickIndex: -1,
+
       activeName: "first",
       scaleNum: 0, // 当前缩放百分比的值
       sizeRange: [20, 40, 60, 80, 100, 150, 200, 300, 400], // 缩放百分比
@@ -462,14 +430,6 @@ export default {
     };
   },
   computed: {
-    step() {
-      return Number(100 / (this.bigscreenScaleInWorkbench * 100));
-    },
-    headers() {
-      return {
-        Authorization: getToken(), // 直接从本地获取token就行
-      };
-    },
     // 左侧折叠切换时,动态计算中间区的宽度
     middleWidth() {
       let widthLeftAndRight = 0;
@@ -496,24 +456,6 @@ export default {
     workbenchTransform() {
       return `scale(${this.bigscreenScaleInWorkbench}, ${this.bigscreenScaleInWorkbench})`;
     },
-    // 初始的缩放百分比 和 下标
-    defaultSize() {
-      const obj = {
-        index: -1,
-        size: "50",
-      };
-      this.sizeRange.some((item, index) => {
-        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];
-      }
-      return obj;
-    },
     // 大屏在设计模式的大小
     bigscreenWidthInWorkbench() {
       return this.getPXUnderScale(this.bigscreenWidth) + this.widthPaddingTools;
@@ -536,29 +478,8 @@ export default {
       },
       deep: true,
     },
-    defaultSize: {
-      handler(val) {
-        if (val !== -1) {
-          this.currentSizeRangeIndex = val.index;
-          this.scaleNum = val.size;
-        }
-      },
-      immediate: true,
-    },
-    bigscreenWidth() {
-      this.initVueRulerTool();
-    },
-    bigscreenHeight() {
-      this.initVueRulerTool();
-    },
-  },
-  created() {
-    /* 以下是记录历史的 */
-    this.revoke = new Revoke();
   },
   mounted() {
-    // 如果是新的设计工作台
-    this.initEchartData();
     this.widgets = [];
     window.addEventListener("mouseup", () => {
       this.grade = false;
@@ -568,81 +489,6 @@ export default {
     });
   },
   methods: {
-    /**
-     * @param num: 0缩小 1放大 2默认比例
-     * 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;
-      }
-      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"); // 纵向标尺
-      // vueRulerToolDom.style.cssText += ';width:' + (this.bigscreenWidth + 18) + 'px !important;height:' + (this.bigscreenHeight + 18) + 'px !important;'
-      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;
-      while (currentNum < +this.bigscreenWidth) {
-        xHtmlContent += `<span class="n" style="left: ${
-          currentNum + 2
-        }px;">${currentNum}</span>`;
-        currentNum += 50;
-      }
-      currentNum = 0;
-      while (currentNum < +this.bigscreenHeight) {
-        yHtmlContent += `<span class="n" style="top: ${
-          currentNum + 2
-        }px;">${currentNum}</span>`;
-        currentNum += 50;
-      }
-      vueRulerX.innerHTML = xHtmlContent;
-      vueRulerY.innerHTML = yHtmlContent;
-    },
-    /**
-     * @description: 恢复
-     * @param {*}
-     * @return {*}
-     */
-    handleUndo() {
-      const record = this.revoke.undo();
-      if (!record) {
-        return false;
-      }
-      this.widgets = record;
-    },
-    /**
-     * @description: 重做
-     * @param {*}
-     * @return {*}
-     */
-    handleRedo() {
-      const record = this.revoke.redo();
-      if (!record) {
-        return false;
-      }
-      this.widgets = record;
-    },
     handlerLayerWidget(val) {
       const layerWidgetArr = [];
       for (let i = 0; i < val.length; i++) {
@@ -670,196 +516,6 @@ export default {
         return item.value.data;
       });
     },
-    async initEchartData() {
-      const reportCode = this.$route.query.reportCode;
-      const { code, data } = await detailDashboard(reportCode);
-      if (code != 200) return;
-      const processData = this.handleInitEchartsData(data);
-      const screenData = this.handleBigScreen(data.dashboard);
-      this.widgets = processData;
-      this.dashboard = screenData;
-      this.bigscreenWidth = this.dashboard.width;
-      this.bigscreenHeight = this.dashboard.height;
-    },
-    handleBigScreen(data) {
-      const optionScreen = getToolByCode("screen").options;
-      const setup = optionScreen.setup;
-      for (const key in data) {
-        for (let i = 0; i < setup.length; i++) {
-          if (key == setup[i].name) {
-            setup[i].value = data[key];
-          }
-        }
-      }
-      this.setOptionsOnClickScreen();
-      return {
-        backgroundColor:
-          (data && data.backgroundColor) || (!data ? "#1e1e1e" : ""),
-        backgroundImage: (data && data.backgroundImage) || "",
-        height: (data && data.height) || "1080",
-        title: (data && data.title) || "",
-        width: (data && data.width) || "1920",
-      };
-    },
-    handleInitEchartsData(data) {
-      const widgets = data.dashboard ? data.dashboard.widgets : [];
-      const widgetsData = [];
-      for (let i = 0; i < widgets.length; i++) {
-        let obj = {};
-        obj.type = widgets[i].type;
-        obj.value = {
-          setup: widgets[i].value.setup,
-          data: widgets[i].value.data,
-          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;
-    },
-    handleOptionsData(data, option) {
-      for (const key in data.setup) {
-        for (let i = 0; i < option.setup.length; i++) {
-          let item = option.setup[i];
-          if (Object.prototype.toString.call(item) == "[object Object]") {
-            if (key == option.setup[i].name) {
-              option.setup[i].value = data.setup[key];
-            }
-          } else if (Object.prototype.toString.call(item) == "[object Array]") {
-            for (let j = 0; j < item.length; j++) {
-              const list = item[j].list;
-              list.forEach((el) => {
-                if (key == el.name) {
-                  el.value = data.setup[key];
-                }
-              });
-            }
-          }
-        }
-      }
-      // position
-      for (const key in data.position) {
-        for (let i = 0; i < option.position.length; i++) {
-          if (key == option.position[i].name) {
-            option.position[i].value = data.position[key];
-          }
-        }
-      }
-      // data
-      for (const key in data.data) {
-        for (let i = 0; i < option.data.length; i++) {
-          if (key == option.data[i].name) {
-            option.data[i].value = data.data[key];
-          }
-        }
-      }
-      return option;
-    },
-    // 保存数据
-    async saveData() {
-      if (!this.widgets || this.widgets.length == 0) {
-        this.$message.error("请添加组件");
-        return;
-      }
-      const screenData = {
-        reportCode: this.$route.query.reportCode,
-        dashboard: {
-          title: this.dashboard.title,
-          width: this.dashboard.width,
-          height: this.dashboard.height,
-          backgroundColor: this.dashboard.backgroundColor,
-          backgroundImage: this.dashboard.backgroundImage,
-        },
-        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("保存成功!");
-      }
-    },
-    // 预览
-    viewScreen() {
-      let routeUrl = this.$router.resolve({
-        path: "/bigscreen/viewer",
-        query: { reportCode: this.$route.query.reportCode },
-      });
-      window.open(routeUrl.href, "_blank");
-    },
-    //  导出
-    async exportDashboard(val) {
-      const fileName = this.$route.query.reportCode + ".zip";
-
-      const param = {
-        reportCode: this.$route.query.reportCode,
-        showDataSet: val,
-      };
-      exportDashboard(param).then((res) => {
-        const that = this;
-        const type = res.type;
-        if (type == "application/json") {
-          let reader = new FileReader();
-          reader.readAsText(res, "utf-8");
-          reader.onload = function () {
-            const data = JSON.parse(reader.result);
-            that.$message.error(data.message);
-          };
-          return;
-        }
-
-        const blob = new Blob([res], { type: "application/octet-stream" });
-        if (window.navigator.msSaveOrOpenBlob) {
-          //msSaveOrOpenBlob方法返回bool值
-          navigator.msSaveBlob(blob, fileName); //本地保存
-        } else {
-          const link = document.createElement("a"); //a标签下载
-          link.href = window.URL.createObjectURL(blob);
-          link.download = fileName;
-          link.click();
-          window.URL.revokeObjectURL(link.href);
-        }
-      });
-    },
-    // 上传成功的回调
-    handleUpload(response, file, fileList) {
-      //清除el-upload组件中的文件
-      this.$refs.upload.clearFiles();
-      //刷新大屏页面
-      this.initEchartData();
-      if (response.code == "200") {
-        this.$message({
-          message: "导入成功!",
-          type: "success",
-        });
-      } else {
-        this.$message({
-          message: response.message,
-          type: "error",
-        });
-      }
-    },
-    handleError(err) {
-      this.$message({
-        message: "上传失败!",
-        type: "error",
-      });
-    },
 
     // 在缩放模式下的大小
     getPXUnderScale(px) {
@@ -950,20 +606,18 @@ export default {
       // 激活新组件的配置属性
       this.setOptionsOnClickWidget(this.widgets.length - 1);
     },
-
     // 对组件默认值处理
     handleDefaultValue(widgetJson) {
+      console.log(widgetJson);
       for (const key in widgetJson) {
         if (key == "options") {
           // collapse、data、position、setup
           // setup 处理
           for (let i = 0; i < widgetJson.options.setup.length; i++) {
             const item = widgetJson.options.setup[i];
-            if (Object.prototype.toString.call(item) == "[object Object]") {
+            if (this.isObjectFn(item)) {
               widgetJson.value.setup[item.name] = item.value;
-            } else if (
-              Object.prototype.toString.call(item) == "[object Array]"
-            ) {
+            } else if (this.isArrayFn(item)) {
               for (let j = 0; j < item.length; j++) {
                 const list = item[j].list;
                 list.forEach((el) => {
@@ -1003,7 +657,6 @@ export default {
       this.activeName = "first";
       this.widgetOptions = getToolByCode("screen")["options"];
     },
-
     // 如果是点击某个组件,获取该组件的配置项
     setOptionsOnClickWidget(obj) {
       this.screenCode = "";
@@ -1052,7 +705,7 @@ export default {
       console.log("val", val);
       console.log(this.widgetOptions);
       if (this.screenCode == "screen") {
-        let newSetup = new Array();
+        let newSetup = [];
         this.dashboard = this.deepClone(val);
         console.log("asd", this.dashboard);
         console.log(this.widgetOptions);
@@ -1083,31 +736,15 @@ export default {
         }
       }
     },
-    rightClick(event, index) {
-      this.rightClickIndex = index;
-      const left = event.clientX;
-      const top = event.clientY;
-      if (left || top) {
-        this.styleObj = {
-          left: left + "px",
-          top: top + "px",
-          display: "block",
-        };
-      }
-      this.visibleContentMenu = true;
-      return false;
-    },
     setDefaultValue(options, val) {
       for (let i = 0; i < options.length; i++) {
-        if (Object.prototype.toString.call(options[i]) == "[object Object]") {
+        if (this.isObjectFn(options[i])) {
           for (const k in val) {
             if (options[i].name == k) {
               options[i].value = val[k];
             }
           }
-        } else if (
-          Object.prototype.toString.call(options[i]) == "[object Array]"
-        ) {
+        } else if (this.isArrayFn(options[i])) {
           for (let j = 0; j < options[i].length; j++) {
             const list = options[i][j].list;
             for (let z = 0; z < list.length; z++) {
@@ -1125,565 +762,10 @@ export default {
       evt.preventDefault();
       this.widgets = this.swapArr(this.widgets, evt.oldIndex, evt.newIndex);
     },
-    // 数组 元素互换位置
-    swapArr(arr, oldIndex, newIndex) {
-      arr[oldIndex] = arr.splice(newIndex, 1, arr[oldIndex])[0];
-      return arr;
-    },
-    // 删除
-    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() {
-      if (this.rightClickIndex + 1 < this.widgets.length) {
-        const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
-        this.widgets.push(temp);
-      }
-    },
-    // 置底
-    setlowLayer() {
-      if (this.rightClickIndex != 0) {
-        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
-      }
-    },
-    // 上移一层
-    moveupLayer() {
-      if (this.rightClickIndex != 0) {
-        this.widgets[this.rightClickIndex] = this.widgets.splice(
-          this.rightClickIndex - 1,
-          1,
-          this.widgets[this.rightClickIndex]
-        )[0];
-      } else {
-        this.widgets.push(this.widgets.shift());
-      }
-    },
-    // 下移一层
-    movedownLayer() {
-      if (this.rightClickIndex != this.widgets.length - 1) {
-        this.widgets[this.rightClickIndex] = this.widgets.splice(
-          this.rightClickIndex + 1,
-          1,
-          this.widgets[this.rightClickIndex]
-        )[0];
-      } else {
-        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
-      }
-    },
   },
 };
 </script>
 
 <style scoped lang="scss">
-.mr10 {
-  margin-right: 10px;
-}
-
-.ml20 {
-  margin-left: 20px;
-}
-
-.border-right {
-  border-right: 1px solid #273b4d;
-}
-
-.border-left {
-  border-left: 1px solid #273b4d;
-}
-
-.el-icon-arrow-down {
-  font-size: 10px;
-}
-
-.is-active {
-  background: #31455d !important;
-  color: #bfcbd9 !important;
-}
-
-.layout {
-  display: -webkit-box;
-  display: -ms-flexbox;
-  display: flex;
-  width: 100%;
-  height: 100%;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  overflow: hidden;
-
-  .layout-left {
-    display: inline-block;
-    height: 100%;
-    box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    border: 0px;
-    background-color: #263445;
-
-    //工具栏一个元素
-    .tools-item {
-      display: flex;
-      position: relative;
-      width: 100%;
-      height: 48px;
-      align-items: center;
-      -webkit-box-align: center;
-      padding: 0 6px;
-      cursor: pointer;
-      font-size: 12px;
-      margin-bottom: 1px;
-
-      .tools-item-icon {
-        color: #409eff;
-        margin-right: 10px;
-        width: 53px;
-        height: 30px;
-        line-height: 30px;
-        text-align: center;
-        display: block;
-        border: 1px solid #3a4659;
-        background: #282a30;
-      }
-      .tools-item-text {
-      }
-    }
-  }
-
-  .layout-left-fold {
-    display: -webkit-box;
-    display: -ms-flexbox;
-    display: flex;
-    height: 100%;
-
-    font-size: 12px;
-    overflow: hidden;
-    background-color: #242a30;
-    cursor: pointer;
-    padding-top: 26%;
-
-    i {
-      font-size: 18px;
-      width: 18px;
-      height: 23px;
-      margin-left: 0px;
-      color: #bfcbd9;
-    }
-  }
-
-  .layout-middle {
-    // display: flex;
-    position: relative;
-    //width: calc(100% - 445px);
-    height: 100%;
-    background-color: rgb(36, 42, 48);
-    box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    border: 1px solid rgb(36, 42, 48);
-    align-items: center;
-    vertical-align: middle;
-    text-align: center;
-
-    .top-button {
-      display: flex;
-      flex-direction: row;
-      height: 40px;
-      line-height: 40px;
-      margin-left: 9px;
-
-      .btn {
-        color: #788994;
-        width: 55px;
-        text-align: center;
-        display: block;
-        cursor: pointer;
-
-        .el-icon-arrow-down {
-          transform: rotate(0deg);
-          -ms-transform: rotate(0deg); /* IE 9 */
-          -moz-transform: rotate(0deg); /* Firefox */
-          -webkit-transform: rotate(0deg); /* Safari 和 Chrome */
-          -o-transform: rotate(0deg); /* Opera */
-          transition: all 0.4s ease-in-out;
-        }
-
-        &:hover {
-          background: rgb(25, 29, 34);
-
-          .el-icon-arrow-down {
-            transform: rotate(180deg);
-            -ms-transform: rotate(180deg); /* IE 9 */
-            -moz-transform: rotate(180deg); /* Firefox */
-            -webkit-transform: rotate(180deg); /* Safari 和 Chrome */
-            -o-transform: rotate(180deg); /* Opera */
-            transition: all 0.4s ease-in-out;
-          }
-        }
-      }
-      .btn-disable {
-        opacity: 0.3;
-        cursor: no-drop;
-      }
-      .scale-num {
-        color: #788994;
-        opacity: 1;
-        cursor: pointer;
-        &.btn-disable {
-          cursor: no-drop;
-          &:hover {
-            background: #20262c;
-          }
-        }
-      }
-    }
-
-    .workbench-container {
-      position: relative;
-      -webkit-transform-origin: 0 0;
-      transform-origin: 0 0;
-      -webkit-box-sizing: border-box;
-      box-sizing: border-box;
-      margin: 0;
-      padding: 0;
-      overflow: auto;
-
-      .vueRuler {
-        // width: 100%;
-        // padding: 18px 0px 0px 18px;
-        padding: 0;
-      }
-
-      .workbench {
-        background-color: #1e1e1e;
-        position: relative;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        user-select: none;
-        -webkit-transform-origin: 0 0;
-        transform-origin: 0 0;
-        margin: 0;
-        padding: 0;
-      }
-
-      .bg-grid {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-size: 30px 30px, 30px 30px;
-        background-image: linear-gradient(
-            hsla(0, 0%, 100%, 0.1) 1px,
-            transparent 0
-          ),
-          linear-gradient(90deg, hsla(0, 0%, 100%, 0.1) 1px, transparent 0);
-        // z-index: 2;
-      }
-    }
-
-    .bottom-text {
-      width: 100%;
-      color: #a0a0a0;
-      font-size: 16px;
-      position: absolute;
-      bottom: 20px;
-    }
-  }
-
-  .layout-right {
-    display: inline-block;
-    height: 100%;
-  }
-
-  /deep/ .el-tabs--border-card {
-    border: 0;
-
-    .el-tabs__header {
-      .el-tabs__nav {
-        .el-tabs__item {
-          background-color: #242f3b;
-          border: 0px;
-        }
-
-        .el-tabs__item.is-active {
-          background-color: #31455d;
-        }
-      }
-    }
-
-    .el-tabs__content {
-      background-color: #242a30;
-      height: calc(100vh - 39px);
-      overflow-x: hidden;
-      overflow-y: auto;
-
-      .el-tab-pane {
-        color: #bfcbd9;
-      }
-
-      &::-webkit-scrollbar {
-        width: 5px;
-        height: 14px;
-      }
-
-      &::-webkit-scrollbar-track,
-      &::-webkit-scrollbar-thumb {
-        border-radius: 1px;
-        border: 0 solid transparent;
-      }
-
-      &::-webkit-scrollbar-track-piece {
-        /*修改滚动条的背景和圆角*/
-        background: #29405c;
-      }
-
-      &::-webkit-scrollbar-track {
-        box-shadow: 1px 1px 5px rgba(116, 148, 170, 0.5) inset;
-      }
-
-      &::-webkit-scrollbar-thumb {
-        min-height: 20px;
-        background-clip: content-box;
-        box-shadow: 0 0 0 5px rgba(116, 148, 170, 0.5) inset;
-      }
-
-      &::-webkit-scrollbar-corner {
-        background: transparent;
-      }
-
-      /*修改垂直滚动条的样式*/
-      &::-webkit-scrollbar-thumb:vertical {
-        background-color: #00113a;
-        // -webkit-border-radius: 7px;
-      }
-
-      /*修改水平滚动条的样式*/
-      &::-webkit-scrollbar-thumb:horizontal {
-        background-color: #00113a;
-        // -webkit-border-radius: 7px;
-      }
-    }
-  }
-}
-
-ul,
-li {
-  list-style: none;
-  margin: 0;
-  padding: 0;
-}
-
-.nav {
-  width: 40px;
-  padding: 0;
-  list-style: none;
-  /* overflow: hidden; */
-}
-
-.nav {
-  zoom: 1;
-}
-
-.nav:before,
-.nav:after {
-  content: "";
-  display: table;
-}
-
-.nav:after {
-  clear: both;
-}
-
-.nav > li {
-  width: 55px;
-  text-align: left;
-  position: relative;
-}
-
-.nav > li a {
-  float: left;
-  padding: 12px 30px;
-  color: #999;
-  font: bold 12px;
-  text-decoration: none;
-}
-
-.nav > li:hover {
-  color: #788994;
-}
-
-.nav > li ul {
-  visibility: hidden;
-  position: absolute;
-  z-index: 1000;
-  list-style: none;
-  left: 0;
-  padding: 0;
-  background-color: rgb(36, 42, 48);
-  opacity: 0;
-  _margin: 0;
-  width: 120px;
-  transition: all 0.2s ease-in-out;
-}
-
-.nav > li:hover > ul {
-  opacity: 1;
-  visibility: visible;
-  margin: 0;
-
-  li:hover {
-    background-color: rgb(25, 29, 34);
-  }
-}
-
-.nav ul li {
-  float: left;
-  display: block;
-  border: 0;
-  width: 100%;
-  font-size: 12px;
-}
-
-.nav ul a {
-  padding: 10px;
-  width: 100%;
-  display: block;
-  float: none;
-  height: 120px;
-  border: 1px solid #30445c;
-  background-color: rgb(25, 29, 34);
-  transition: all 0.2s ease-in-out;
-}
-
-.nav ul a:hover {
-  border: 1px solid #3c5e88;
-}
-
-.nav ul li:first-child > a:hover:before {
-  border-bottom-color: #04acec;
-}
-
-.nav ul ul {
-  top: 0;
-  left: 120px;
-  width: 400px;
-  height: 300px;
-  overflow: auto;
-  padding: 10px;
-  _margin: 0;
-}
-
-.nav ul ul li {
-  width: 120px;
-  height: 120px;
-  margin-right: 3px;
-  display: block;
-  float: left;
-}
-
-.nav .item {
-  padding: 5px;
-}
-
-/deep/ .vue-ruler-h {
-  opacity: 0.3;
-}
-
-/deep/ .vue-ruler-v {
-  opacity: 0.3;
-}
-.layout-left {
-  width: 200px;
-  background: #242a30;
-  overflow-x: hidden;
-  overflow-y: auto;
-  .chart-type {
-    display: flex;
-    flex-direction: row;
-    overflow: hidden;
-    .type-left {
-      width: 100%;
-      height: calc(100vh - 80px);
-      text-align: center;
-      /deep/.el-tabs__header {
-        width: 30%;
-        margin-right: 0;
-        .el-tabs__nav-wrap {
-          &::after {
-            background: transparent;
-          }
-          .el-tabs__item {
-            text-align: center;
-            width: 100% !important;
-            color: #fff;
-            padding: 0;
-            font-size: 12px !important;
-          }
-        }
-      }
-      /deep/.el-tabs__content {
-        width: 70%;
-      }
-    }
-  }
-  //工具栏一个元素
-  .tools-item {
-    display: flex;
-    position: relative;
-    width: 100%;
-    height: 48px;
-    align-items: center;
-    -webkit-box-align: center;
-    padding: 0 6px;
-    cursor: pointer;
-    font-size: 12px;
-    margin-bottom: 1px;
-
-    .tools-item-icon {
-      color: #409eff;
-      margin-right: 10px;
-      width: 53px;
-      height: 30px;
-      line-height: 30px;
-      text-align: center;
-      display: block;
-      border: 1px solid #3a4659;
-      background: #282a30;
-    }
-    .tools-item-text {
-      font-size: 12px !important;
-    }
-  }
-  /deep/.el-tabs__content {
-    padding: 0;
-  }
-}
-/* 设置滚动条的样式 */
-
-::-webkit-scrollbar {
-  width: 0;
-  height: 10px;
-}
+@import "@/assets/styles/screen.scss";
 </style>

+ 505 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/scaleCharts/widget-scale.js

@@ -0,0 +1,505 @@
+
+export const widgetScale = {
+  code: 'widget-scale',
+  type: 'scaleCharts',
+  tabName: '刻度尺',
+  label: '刻度尺',
+  icon: 'iconicon_tubiao_bingtu',
+  options: {
+    // 配置
+    setup: [
+      {
+        type: 'el-input-text',
+        label: '图层名称',
+        name: 'layerName',
+        required: false,
+        placeholder: '',
+        value: '刻度尺',
+      },
+      {
+        type: 'el-input-text',
+        label: '图层唯一标识',
+        name: 'uuid',
+        disabled: true,
+        value: 'widget-scale' + Date.now()
+      },
+      {
+        type: 'el-switch',
+        label: '竖展示',
+        name: 'verticalShow',
+        required: false,
+        placeholder: '',
+        value: false,
+      },
+      {
+        type: 'vue-color',
+        label: '背景颜色',
+        name: 'background',
+        required: false,
+        placeholder: '',
+        value: ''
+      },
+      [
+        {
+          name: '标题设置',
+          list: [
+            {
+              type: 'el-switch',
+              label: '标题显示',
+              name: 'isNoTitle',
+              required: false,
+              placeholder: '',
+              value: true,
+            },
+            {
+              type: 'el-input-text',
+              label: '标题名',
+              name: 'titleText',
+              required: false,
+              placeholder: '',
+              value: '',
+            },
+            {
+              type: 'vue-color',
+              label: '字体颜色',
+              name: 'textColor',
+              required: false,
+              placeholder: '',
+              value: '#FFD700'
+            },
+            {
+              type: 'el-input-number',
+              label: '字体字号',
+              name: 'textFontSize',
+              required: false,
+              placeholder: '',
+              value: 20
+            },
+            {
+              type: 'el-select',
+              label: '字体粗细',
+              name: 'textFontWeight',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'bold', name: '粗体' },
+                { code: 'bolder', name: '特粗体' },
+                { code: 'lighter', name: '细体' }
+              ],
+              value: 'normal'
+            },
+            {
+              type: 'el-select',
+              label: '字体风格',
+              name: 'textFontStyle',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'italic', name: 'italic斜体' },
+                { code: 'oblique', name: 'oblique斜体' },
+              ],
+              value: 'normal'
+            },
+            {
+              type: 'el-select',
+              label: '字体位置',
+              name: 'textAlign',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'center', name: '居中' },
+                { code: 'left', name: '左对齐' },
+                { code: 'right', name: '右对齐' },
+              ],
+              value: 'center'
+            },
+            {
+              type: 'el-input-text',
+              label: '副标题名',
+              name: 'subText',
+              required: false,
+              placeholder: '',
+              value: ''
+            },
+            {
+              type: 'vue-color',
+              label: '字体颜色',
+              name: 'subTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgba(30, 144, 255, 1)'
+            },
+            {
+              type: 'el-input-number',
+              label: '字体字号',
+              name: 'subTextFontSize',
+              required: false,
+              placeholder: '',
+              value: 20
+            },
+            {
+              type: 'el-select',
+              label: '字体粗细',
+              name: 'subTextFontWeight',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'bold', name: '粗体' },
+                { code: 'bolder', name: '特粗体' },
+                { code: 'lighter', name: '细体' }
+              ],
+              value: 'normal'
+            },
+            {
+              type: 'el-select',
+              label: '字体风格',
+              name: 'subTextFontStyle',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'italic', name: 'italic斜体' },
+                { code: 'oblique', name: 'oblique斜体' },
+              ],
+              value: 'normal'
+            },
+          ],
+        },
+        {
+          name: '刻度设定',
+          list: [
+            {
+              type: 'el-input-number',
+              label: '最大刻度',
+              name: 'maxScale',
+              require: false,
+              placeholder: '',
+              value: 100,
+            },
+            {
+              type: 'vue-color',
+              label: '刻度颜色',
+              name: 'scaleColor',
+              required: false,
+              placeholder: '',
+              value: 'rgba(56, 128, 138,1)'
+            },
+            {
+              type: 'el-input-number',
+              label: '刻度宽度',
+              name: 'scaleBarWidth',
+              required: false,
+              placeholder: '',
+              value: 2,
+            },
+            {
+              type: 'el-input-number',
+              label: '刻度值字号',
+              name: 'scaleFontSize',
+              required: false,
+              placeholder: '',
+              value: 16,
+            },
+            {
+              type: 'vue-color',
+              label: '刻度值颜色',
+              name: 'scaleDataColor',
+              required: false,
+              placeholder: '',
+              value: 'rgba(56, 128, 138,1)'
+            },
+            {
+              type: 'el-select',
+              label: '刻度值粗细',
+              name: 'scaleFontWeight',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'bold', name: '粗体' },
+                { code: 'bolder', name: '特粗体' },
+                { code: 'lighter', name: '细体' }
+              ],
+              value: 'normal'
+            },
+          ],
+        },
+        {
+          name: '外框设置',
+          list: [
+            {
+              type: 'el-input-number',
+              label: '宽度',
+              name: 'outBarWidth',
+              required: false,
+              placeholder: '',
+              value: 45,
+            },
+            {
+              type: 'vue-color',
+              label: '颜色',
+              name: 'outBarColor',
+              require: false,
+              placeholder: '',
+              value: '#00FEFF',
+            },
+            {
+              type: 'el-slider',
+              label: '圆角',
+              name: 'outBarRadius',
+              require: false,
+              placeholder: '',
+              value: 50,
+            },
+          ],
+        },
+        {
+          name: '内框设置',
+          list: [
+            {
+              type: 'el-input-number',
+              label: '宽度',
+              name: 'inBarWidth',
+              required: false,
+              placeholder: '',
+              value: 35,
+            },
+            {
+              type: 'vue-color',
+              label: '空白区颜色',
+              name: 'inBarColor',
+              require: false,
+              placeholder: '',
+              value: 'rgba(56, 128, 138,1)',
+            },
+            {
+              type: 'el-slider',
+              label: '圆角',
+              name: 'inBarRadius',
+              require: false,
+              placeholder: '',
+              value: 50,
+            },
+          ],
+        },
+        {
+          name: '数值设定',
+          list: [
+            {
+              type: 'el-switch',
+              label: '显示',
+              name: 'isShow',
+              required: false,
+              placeholder: '',
+              value: true,
+            },
+            {
+              type: 'el-input-number',
+              label: '字体字号',
+              name: 'fontSize',
+              required: false,
+              placeholder: '',
+              value: 16,
+            },
+            {
+              type: 'el-select',
+              label: '字体粗细',
+              name: 'fontWeight',
+              required: false,
+              placeholder: '',
+              selectOptions: [
+                { code: 'normal', name: '正常' },
+                { code: 'bold', name: '粗体' },
+                { code: 'bolder', name: '特粗体' },
+                { code: 'lighter', name: '细体' }
+              ],
+              value: 'normal'
+            },
+          ],
+        },
+        {
+          name: '渐变色',
+          list: [
+            {
+              type: 'vue-color',
+              label: '0%',
+              name: 'bar0Color',
+              required: false,
+              placeholder: '',
+              value: '#00FEFF'
+            },
+            {
+              type: 'vue-color',
+              label: '30%',
+              name: 'bar30Color',
+              required: false,
+              placeholder: '',
+              value: '#93FE94'
+            },
+            {
+              type: 'vue-color',
+              label: '70%',
+              name: 'bar70Color',
+              required: false,
+              placeholder: '',
+              value: '#E4D225'
+            },
+            {
+              type: 'vue-color',
+              label: '100%',
+              name: 'bar100Color',
+              required: false,
+              placeholder: '',
+              value: '#E01F28'
+            },
+          ],
+        },
+        {
+          name: '提示语设置',
+          list: [
+            {
+              type: 'el-input-number',
+              label: '字体字号',
+              name: 'tipFontSize',
+              required: false,
+              placeholder: '',
+              value: 16
+            },
+            {
+              type: 'vue-color',
+              label: '字体颜色',
+              name: 'tipsColor',
+              required: false,
+              placeholder: '',
+              value: '#00FEFF'
+            },
+          ],
+        },
+        {
+          name: '坐标轴边距设置',
+          list: [
+            {
+              type: 'el-slider',
+              label: '左边距(像素)',
+              name: 'marginLeft',
+              required: false,
+              placeholder: '',
+              value: 60,
+            }, {
+              type: 'el-slider',
+              label: '顶边距(像素)',
+              name: 'marginTop',
+              required: false,
+              placeholder: '',
+              value: 20,
+            }, {
+              type: 'el-slider',
+              label: '右边距(像素)',
+              name: 'marginRight',
+              required: false,
+              placeholder: '',
+              value: 30,
+            }, {
+              type: 'el-slider',
+              label: '底边距(像素)',
+              name: 'marginBottom',
+              required: false,
+              placeholder: '',
+              value: 10,
+            },
+          ],
+        },
+      ],
+    ],
+    // 数据
+    data: [
+      {
+        type: 'el-radio-group',
+        label: '数据类型',
+        name: 'dataType',
+        require: false,
+        placeholder: '',
+        selectValue: true,
+        selectOptions: [
+          {
+            code: 'staticData',
+            name: '静态数据',
+          },
+          {
+            code: 'dynamicData',
+            name: '动态数据',
+          },
+        ],
+        value: 'staticData',
+      },
+      {
+        type: 'el-input-number',
+        label: '刷新时间(毫秒)',
+        name: 'refreshTime',
+        relactiveDom: 'dataType',
+        relactiveDomValue: 'dynamicData',
+        value: 5000
+      },
+      {
+        type: 'el-button',
+        label: '静态数据',
+        name: 'staticData',
+        required: false,
+        placeholder: '',
+        relactiveDom: 'dataType',
+        relactiveDomValue: 'staticData',
+        value: [{"num": 50 }]
+      },
+      {
+        type: 'dycustComponents',
+        label: '',
+        name: 'dynamicData',
+        required: false,
+        placeholder: '',
+        relactiveDom: 'dataType',
+        chartType: 'widget-scale',
+        relactiveDomValue: 'dynamicData',
+        dictKey: 'TEXT_PROPERTIES',
+        value: '',
+      },
+    ],
+    // 坐标
+    position: [
+      {
+        type: 'el-input-number',
+        label: '左边距',
+        name: 'left',
+        required: false,
+        placeholder: '',
+        value: 0,
+      },
+      {
+        type: 'el-input-number',
+        label: '上边距',
+        name: 'top',
+        required: false,
+        placeholder: '',
+        value: 0,
+      },
+      {
+        type: 'el-input-number',
+        label: '宽度',
+        name: 'width',
+        required: false,
+        placeholder: '该容器在1920px大屏中的宽度',
+        value: 250,
+      },
+      {
+        type: 'el-input-number',
+        label: '高度',
+        name: 'height',
+        required: false,
+        placeholder: '该容器在1080px大屏中的高度',
+        value: 400,
+      },
+    ],
+  }
+}

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

@@ -41,6 +41,7 @@ import { widgetBarLineStack } from "./configure/barlineCharts/widget-bar-line-st
 import { widgetSelect } from "./configure/form/widget-select";
 import { widgetInput } from "./configure/form/widget-input";
 import { widgetFormTime } from "./configure/form/widget-form-time";
+import {widgetScale} from "./configure/scaleCharts/widget-scale";
 
 export const widgetTool = [
   // type=html类型的组件
@@ -71,10 +72,11 @@ export const widgetTool = [
   widgetLineCompare,
   widgetDecoratePie,
   widgetMoreBarLine,
-  // widgetWordCloud,
+  widgetWordCloud,
   widgetHeatmap,
   widgetRadar,
   widgetBarLineStack,
+  widgetScale,
   widgetSelect,
   widgetInput,
   widgetFormTime

+ 1 - 2
report-ui/src/views/bigscreenDesigner/designer/widget/form/widgetFormTime.vue

@@ -31,7 +31,6 @@ export default {
   },
   computed: {
     styleObj() {
-      console.log(this.optionsSetup);
       return {
         position: this.ispreview ? "absolute" : "static",
         width: this.optionsStyle.width + "px",
@@ -121,4 +120,4 @@ export default {
     }
   }
 }
-</style>
+</style>

+ 524 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/scale/widgetScale.vue

@@ -0,0 +1,524 @@
+<template>
+  <div :style="styleObj">
+    <v-chart :options="options" autoresize/>
+  </div>
+</template>
+
+<script>
+import echarts from "echarts";
+import {eventBusParams} from "@/utils/screen";
+
+let scale = [];
+let max;
+let min;
+let Gradient = [];
+
+export default {
+  name: "widgetScale",
+  components: {},
+  props: {
+    value: Object,
+    ispreview: Boolean,
+  },
+  data() {
+    return {
+      options: {
+        yAxis: [
+          {
+            // 对底部高度有影响
+            show: true,
+            data: [],
+            min: 0,
+            max: max,
+            axisLine: {
+              show: false
+            }
+          },
+          {
+            show: false,
+            min: 0,
+            max: max,
+          },
+          {
+            type: 'category',
+            position: 'left',
+            offset: -5,
+            axisLabel: {
+              fontSize: 10,
+              color: 'white'
+            },
+            axisLine: {
+              show: false
+            },
+            axisTick: {
+              show: false
+            },
+          }
+        ],
+        xAxis: [
+          // 宽度
+          {
+            show: false,
+            min: -10,
+            max: 10,
+            data: []
+          },
+          {
+            show: false,
+            min: -10,
+            max: 10,
+            data: []
+          },
+          {
+            show: false,
+            min: -10,
+            max: 10,
+            data: []
+          },
+          { // 刻度位置
+            show: false,
+            min: -3,
+            max: 10,
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(56, 128, 138,1)',
+              }
+            }
+          }
+        ],
+        series: [
+          {
+            name: "值",
+            type: "bar",
+            barWidth: 35,
+            xAxisIndex: 0,
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 1, 0, 0, Gradient),
+                barBorderRadius: 50,
+              }
+            },
+            z: 2,
+            data: [
+              {
+                label: {
+                  normal: {
+                    show: true,
+                    position: "top",
+                    backgroundColor: {},
+                    width: 10,
+                    height: 50,
+                    rich: {
+                      back: {
+                        align: 'center',
+                        lineHeight: 50,
+                        fontSize: 16,
+                        fontFamily: 'digifacewide',
+                      },
+                    }
+                  }
+                }
+              }
+            ],
+          },
+          {
+            name: '白框',
+            type: 'bar',
+            xAxisIndex: 1,
+            barGap: '-100%',
+            data: [max - 1],
+            barWidth: 35,
+            itemStyle: {
+              normal: {
+                color: '#0C2F6F',
+                barBorderRadius: 50,
+              }
+            },
+            z: 1
+          },
+          {
+            name: '外框',
+            type: 'bar',
+            xAxisIndex: 2,
+            barGap: '-100%',
+            data: [max],
+            barWidth: 45,
+            itemStyle: {
+              normal: {
+                color: 'rgba(56, 128, 138,1)',
+                barBorderRadius: 50,
+              }
+            },
+            z: 0
+          },
+          {
+            name: '刻度',
+            type: 'bar',
+            yAxisIndex: 0,
+            xAxisIndex: 3,
+            label: {
+              normal: {
+                show: true,
+                position: 'left',
+                distance: 10,
+                color: 'rgba(56, 128, 138,1)',
+                fontSize: 16,
+                fontWeight: 'normal',
+                formatter: function (params) {
+                  if (params.dataIndex % 10 === 0) {
+                    return params.dataIndex;
+                  } else if (params.dataIndex == max) {
+                    return params.dataIndex;
+                  } else {
+                    return ""
+                  }
+                }
+              }
+            },
+            barGap: '-40%',
+            data: scale,
+            barWidth: 2,
+            itemStyle: {
+              normal: {
+                color: 'rgba(56, 128, 138,1)',
+              }
+            },
+            z: 0
+          }
+        ],
+      },
+      optionsStyle: {}, // 样式
+      optionsData: {}, // 数据
+      optionsCollapse: {}, // 图标属性
+      optionsSetup: {},
+    };
+  },
+  computed: {
+    styleObj() {
+      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.background,
+      };
+    },
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.optionsStyle = val.position;
+        this.optionsData = val.data;
+        this.optionsCollapse = val.collapse;
+        this.optionsSetup = val.setup;
+        this.editorOptions();
+      },
+      deep: true,
+    },
+  },
+  created() {
+    this.optionsStyle = this.value.position;
+    this.optionsData = this.value.data;
+    this.optionsCollapse = this.value.collapse;
+    this.optionsSetup = this.value.setup;
+    this.editorOptions();
+    eventBusParams(
+      this.optionsSetup,
+      this.optionsData,
+      (dynamicData, optionsSetup) => {
+        this.getEchartData(dynamicData, optionsSetup);
+      }
+    );
+  },
+  methods: {
+    // 修改图标options属性
+    editorOptions() {
+      this.setOptionsTitle();
+      this.setOptionsMaxScale();
+      this.setOptionsYAxis();
+      this.setOptionsScale();
+      this.setOptionsOutBar();
+      this.setOptionsMargin();
+      this.setOptionsData();
+      this.setOptionsInBar();
+
+    },
+    // 标题设置
+    setOptionsTitle() {
+      const optionsSetup = this.optionsSetup;
+      const title = {};
+      title.text = optionsSetup.titleText;
+      title.show = optionsSetup.isNoTitle;
+      title.left = optionsSetup.textAlign;
+      title.textStyle = {
+        color: optionsSetup.textColor,
+        fontSize: optionsSetup.textFontSize,
+        fontWeight: optionsSetup.textFontWeight,
+        fontStyle: optionsSetup.textFontStyle,
+      };
+      title.subtext = optionsSetup.subText;
+      title.subtextStyle = {
+        color: optionsSetup.subTextColor,
+        fontWeight: optionsSetup.subTextFontWeight,
+        fontSize: optionsSetup.subTextFontSize,
+        fontStyle: optionsSetup.subTextFontStyle,
+      };
+      this.options.title = title;
+    },
+    // 最大刻度设置
+    setOptionsMaxScale() {
+      const optionsSetup = this.optionsSetup;
+      max = optionsSetup.maxScale;
+      scale = this.setScale(max);
+    },
+    setScale(max) {
+      let scale = [];
+      for (let i = 0; i <= max; i++) {
+        if (i <= 0 || i >= max) {
+          scale.push('-2')
+        } else {
+          if ((i - 10) % 20 === 0) {
+            scale.push('-2');
+          } else if ((i - 10) % 4 === 0) {
+            scale.push('-1');
+          } else {
+            scale.push('');
+          }
+        }
+      }
+      return scale;
+    },
+    setOptionsYAxis() {
+      this.options.yAxis[0].max = max;
+      this.options.yAxis[1].max = max;
+    },
+    // 刻度设定
+    setOptionsScale() {
+      const optionsSetup = this.optionsSetup;
+      const series = this.options.series[3];
+      //刻度
+      series.data = scale;
+      series.barWidth = optionsSetup.scaleBarWidth;
+      series.itemStyle = {
+        normal: {
+          color: optionsSetup.scaleColor,
+        }
+      };
+      //刻度值
+      series.label = {
+        normal: {
+          show: true,
+          position: 'left',
+          distance: 10,
+          fontSize: optionsSetup.scaleFontSize,
+          color: optionsSetup.scaleDataColor,
+          fontWeight: optionsSetup.scaleFontWeight,
+          formatter: function (params) {
+            if (params.dataIndex % 10 === 0) {
+              return params.dataIndex;
+            } else if (params.dataIndex == max) {
+              return params.dataIndex;
+            } else {
+              return ""
+            }
+          }
+        }
+      };
+    },
+    // 外框设置
+    setOptionsOutBar() {
+      const optionsSetup = this.optionsSetup;
+      const series = this.options.series[2];
+      series.barWidth = optionsSetup.outBarWidth;
+      series.itemStyle = {
+        normal: {
+          color: optionsSetup.outBarColor,
+          barBorderRadius: optionsSetup.outBarRadius,
+        }
+      };
+      series.data = [max];
+    },
+    // 内框设置
+    setOptionsInBar() {
+      const optionsSetup = this.optionsSetup;
+      const series1 = this.options.series[1];
+      series1.barWidth = optionsSetup.inBarWidth;
+      series1.itemStyle = {
+        normal: {
+          color: optionsSetup.inBarColor,
+          barBorderRadius: optionsSetup.inBarRadius,
+        }
+      };
+      series1.data = [max - 1];
+      const series0 = this.options.series[0];
+      series0.barWidth = optionsSetup.inBarWidth;
+      series0.itemStyle = {
+        normal: {
+          color: new echarts.graphic.LinearGradient(0, 1, 0, 0, Gradient),
+          barBorderRadius: optionsSetup.inBarRadius,
+        }
+      };
+    },
+    // 渐变色设置
+    setOptionsColor(inputValue, max) {
+      const optionsSetup = this.optionsSetup;
+      let gradient = [];
+      if (inputValue > (max * 0.7)) {
+        gradient.push(
+          {
+            offset: 0,
+            color: optionsSetup.bar0Color,
+          },
+          {
+            offset: 0.3,
+            color: optionsSetup.bar30Color,
+          },
+          {
+            offset: 0.7,
+            color: optionsSetup.bar70Color,
+          },
+          {
+            offset: 1,
+            color: optionsSetup.bar100Color,
+          })
+      } else if (inputValue > (max * 0.3)) {
+        gradient.push(
+          {
+            offset: 0,
+            color: optionsSetup.bar0Color,
+          },
+          {
+            offset: 0.5,
+            color: optionsSetup.bar30Color,
+          },
+          {
+            offset: 1,
+            color: optionsSetup.bar70Color,
+          })
+      } else {
+        gradient.push(
+          {
+            offset: 0,
+            color: optionsSetup.bar0Color,
+          },
+          {
+            offset: 1,
+            color: optionsSetup.bar30Color,
+          })
+      }
+      return gradient;
+    },
+    setShowValue(inputValue, max) {
+      let showValue = inputValue;
+      if (inputValue > max) {
+        showValue = max
+      } else {
+        if (inputValue < 0) {
+          showValue = 0
+        } else {
+          showValue = inputValue
+        }
+      }
+      return showValue;
+    },
+    // 提示语设置 tooltip
+    setOptionsTooltip() {
+      const optionsSetup = this.optionsSetup;
+      const tooltip = {
+        trigger: "item",
+        show: true,
+        textStyle: {
+          color: optionsSetup.lineColor,
+          fontSize: optionsSetup.tipFontSize,
+        },
+      };
+      this.options.tooltip = tooltip;
+    },
+    // 边距设置
+    setOptionsMargin() {
+      const optionsSetup = this.optionsSetup;
+      const grid = {
+        left: optionsSetup.marginLeft,
+        right: optionsSetup.marginRight,
+        bottom: optionsSetup.marginBottom,
+        top: optionsSetup.marginTop,
+        containLabel: true,
+      };
+      this.options.grid = grid;
+    },
+    setOptionsData() {
+      const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      optionsData.dataType == "staticData"
+        ? this.staticDataFn(optionsData.staticData)
+        : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
+    },
+    // 静态数据
+    staticDataFn(val) {
+      const optionsSetup = this.optionsSetup;
+      const num = val[0]["num"];
+      // 渐变色
+      const gradient = this.setOptionsColor(num, optionsSetup.maxScale);
+      Gradient = gradient;
+      // 数值设定
+      const series = this.options.series;
+      const data = {
+        value: this.setShowValue(num, optionsSetup.maxScale),
+        label: {
+          normal: {
+            show: optionsSetup.isShow,
+            position: "top",
+            backgroundColor: {},
+            width: 10,
+            height: 50,
+            formatter: '{back| ' + num + ' }',
+            rich: {
+              back: {
+                align: 'center',
+                lineHeight: 50,
+                fontSize: optionsSetup.fontSize,
+                fontWeight: optionsSetup.fontWeight,
+                fontFamily: 'digifacewide',
+                color: gradient[gradient.length - 1].color,
+              },
+            }
+          }
+        }
+      }
+      series[0].data[0] = data;
+    },
+    dynamicDataFn(val, refreshTime) {
+      if (!val) return;
+      if (this.ispreview) {
+        this.getEchartData(val);
+        this.flagInter = setInterval(() => {
+          this.getEchartData(val);
+        }, refreshTime);
+      } else {
+        this.getEchartData(val);
+      }
+    },
+    getEchartData(val) {
+      const data = this.queryEchartsData(val);
+      data.then((res) => {
+        this.renderingFn(res);
+      });
+    },
+    renderingFn(val) {
+      for (const key in this.options.series) {
+        if (this.options.series[key].type == "pie") {
+          this.options.series[key].data = val;
+        }
+      }
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.echarts {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+</style>

+ 2 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue

@@ -43,6 +43,7 @@ import widgetBarLineStackChart from "./barline/widgetBarLineStackChart";
 import widgetSelect from "./form/widgetSelect";
 import widgetInput from "./form/widgetInput.vue";
 import widgetFormTime from "./form/widgetFormTime.vue";
+import widgetScale from "./scale/widgetScale.vue";
 
 export default {
   name: "WidgetTemp",
@@ -77,6 +78,7 @@ export default {
     widgetHeatmap,
     widgetRadar,
     widgetBarLineStackChart,
+    widgetScale,
     widgetSelect,
     widgetInput,
     widgetFormTime,

+ 2 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/widget.vue

@@ -50,6 +50,7 @@ import widgetBarLineStackChart from "./barline/widgetBarLineStackChart";
 import widgetSelect from "./form/widgetSelect";
 import widgetInput from "./form/widgetInput.vue";
 import widgetFormTime from "./form/widgetFormTime.vue";
+import widgetScale from "./scale/widgetScale.vue";
 
 export default {
   name: "Widget",
@@ -84,6 +85,7 @@ export default {
     widgetHeatmap,
     widgetRadar,
     widgetBarLineStackChart,
+    widgetScale,
     widgetSelect,
     widgetInput,
     widgetFormTime,