Commit 4a874a1f97e955ecd559894efaf36cb484aa5690

Authored by qianbao
1 parent 384a3ad8

台南佳宽高完全自适应 会变形

src/views/bigscreenDesigner/designer/index.vue.宽高都自适应 0 → 100644
  1 +<!--
  2 + * @Descripttion: 大屏设计器
  3 + !-->
  4 +<template>
  5 + <div class="layout">
  6 + <div
  7 + v-if="toolIsShow"
  8 + class="layout-left"
  9 + :style="{ width: widthLeftForTools + 'px' }"
  10 + >
  11 + <el-tabs class="layout-left" type="border-card" :stretch="true">
  12 + <!-- 左侧组件栏-->
  13 + <el-tab-pane label="工具栏">
  14 + <span slot="label"><i class="el-icon-date icon"></i>工具栏</span>
  15 + <div class="chart-type">
  16 + <el-tabs class="type-left" tab-position="left">
  17 + <el-tab-pane
  18 + v-for="(item, index) in widgetTools"
  19 + :key="index"
  20 + :label="item.name"
  21 + >
  22 + <li
  23 + v-for="(it, idx) in item.list"
  24 + :key="idx"
  25 + draggable="true"
  26 + @dragstart="dragStart(it.code)"
  27 + @dragend="dragEnd()"
  28 + >
  29 + <div class="tools-item">
  30 + <span class="tools-item-icon">
  31 + <i class="iconfont" :class="it.icon"></i>
  32 + </span>
  33 + <span class="tools-item-text">{{ it.label }}</span>
  34 + </div>
  35 + </li>
  36 + </el-tab-pane>
  37 + </el-tabs>
  38 + </div>
  39 + </el-tab-pane>
  40 + <!-- 左侧图层-->
  41 + <el-tab-pane label="图层">
  42 + <draggable
  43 + v-model="layerWidget"
  44 + @update="datadragEnd"
  45 + :options="{ animation: 300 }"
  46 + >
  47 + <transition-group>
  48 + <div
  49 + v-for="(item, index) in layerWidget"
  50 + :key="'item' + index"
  51 + class="tools-item"
  52 + :class="widgetIndex == index ? 'is-active' : ''"
  53 + @click="layerClick(index)"
  54 + >
  55 + <span class="tools-item-icon">
  56 + <i class="iconfont" :class="item.icon"></i>
  57 + </span>
  58 + <span class="tools-item-text">{{ item.label }}</span>
  59 + </div>
  60 + </transition-group>
  61 + </draggable>
  62 + </el-tab-pane>
  63 + </el-tabs>
  64 + </div>
  65 + <!-- 是否显示左侧组件栏-->
  66 + <div class="layout-left-fold"
  67 + :style="{ width: widthLeftForToolsHideButton + 'px' }"
  68 + @click="toolIsShow = !toolIsShow">
  69 + <i :class="[toolIsShow?' el-icon-arrow-left':'el-icon-arrow-right']"/>
  70 + </div>
  71 + <!-- 上面操作导入、导出-->
  72 + <div
  73 + class="layout-middle"
  74 + :style="{ width: middleWidth + 'px', height: middleHeight + 'px' }"
  75 + >
  76 + <div class="top-button">
  77 + <span class="btn">
  78 + <el-tooltip
  79 + class="item"
  80 + effect="dark"
  81 + content="保存"
  82 + placement="bottom"
  83 + >
  84 + <i class="iconfont iconsave" @click="saveData"></i>
  85 + </el-tooltip>
  86 + </span>
  87 + <span class="btn">
  88 + <el-tooltip
  89 + class="item"
  90 + effect="dark"
  91 + content="预览"
  92 + placement="bottom"
  93 + >
  94 + <i class="iconfont iconyulan" @click="viewScreen"></i>
  95 + </el-tooltip>
  96 + </span>
  97 +
  98 + <span class="btn">
  99 + <el-tooltip
  100 + class="item"
  101 + effect="dark"
  102 + content="撤销"
  103 + placement="bottom"
  104 + >
  105 + <i class="iconfont iconundo" @click="handleUndo"></i>
  106 + </el-tooltip>
  107 + </span>
  108 +
  109 + <span class="btn">
  110 + <el-tooltip
  111 + class="item"
  112 + effect="dark"
  113 + content="恢复"
  114 + placement="bottom"
  115 + >
  116 + <i class="iconfont iconhuifubeifen" @click="handleRedo"></i>
  117 + </el-tooltip>
  118 + </span>
  119 +
  120 + <span class="btn" v-permission="'bigScreenManage:export'">
  121 + <el-tooltip
  122 + class="item"
  123 + effect="dark"
  124 + content="导入"
  125 + placement="bottom"
  126 + >
  127 + <el-upload
  128 + class="el-upload"
  129 + ref="upload"
  130 + :action="uploadUrl"
  131 + :headers="headers"
  132 + accept=".zip"
  133 + :on-success="handleUpload"
  134 + :on-error="handleError"
  135 + :show-file-list="false"
  136 + :limit="1"
  137 + >
  138 + <i class="iconfont icondaoru"></i>
  139 + </el-upload>
  140 + </el-tooltip>
  141 + </span>
  142 + <span class="btn border-left" v-permission="'bigScreenManage:import'">
  143 + <ul class="nav">
  144 + <li>
  145 + <i class="iconfont icondaochu"></i
  146 + ><i class="el-icon-arrow-down"></i>
  147 + <ul>
  148 + <li>
  149 + <el-tooltip
  150 + class="item"
  151 + effect="dark"
  152 + content="适合当前系统"
  153 + placement="right"
  154 + >
  155 + <div @click="exportDashboard(1)">导出(包含数据集)</div>
  156 + </el-tooltip>
  157 + </li>
  158 + <li>
  159 + <el-tooltip
  160 + class="item"
  161 + effect="dark"
  162 + content="适合跨系统"
  163 + placement="right"
  164 + >
  165 + <div @click="exportDashboard(0)">导出(不包含数据集)</div>
  166 + </el-tooltip>
  167 + </li>
  168 + </ul>
  169 + </li>
  170 + </ul>
  171 + </span>
  172 + </div>
  173 + <!-- 中间设计-->
  174 + <div
  175 + class="workbench-container"
  176 + :style="{
  177 + width: bigscreenWidthInWorkbench + 'px',
  178 + height: bigscreenHeightInWorkbench + 'px',
  179 + }"
  180 + @mousedown="handleMouseDown"
  181 + >
  182 + <vue-ruler-tool
  183 + v-model="dashboard.presetLine"
  184 + class="vueRuler"
  185 + :step-length="50"
  186 + :parent="true"
  187 + :position="'relative'"
  188 + :is-scale-revise="true"
  189 + :visible.sync="dashboard.presetLineVisible"
  190 + :style="{
  191 + //如果想尺子不变化,单独定义遍历等于工作区域
  192 + // width: bigscreenWidthRuler + 'px',
  193 + // height: bigscreenHeightRuler + 'px',
  194 + width: bigscreenWidthInWorkbench + 'px',
  195 + //高度尺子不变换,想变化放出来
  196 + height: bigscreenHeightInWorkbench + 'px',
  197 + }"
  198 + >
  199 + <div
  200 + id="workbench"
  201 + class="workbench"
  202 + :style="{
  203 + transform: workbenchTransform,
  204 + width: bigscreenWidth + 'px',
  205 + height: bigscreenHeight + 'px',
  206 + 'background-color': dashboard.backgroundColor,
  207 + 'background-image': 'url(' + dashboard.backgroundImage + ')',
  208 + 'background-position': '0% 0%',
  209 + 'background-size': '100% 100%',
  210 + 'background-repeat': 'initial',
  211 + 'background-attachment': 'initial',
  212 + 'background-origin': 'initial',
  213 + 'background-clip': 'initial',
  214 + }"
  215 + @click.self="setOptionsOnClickScreen"
  216 + @drop="widgetOnDragged($event)"
  217 + @dragover="dragOver($event)"
  218 + >
  219 + <div v-if="grade" class="bg-grid"></div>
  220 + <widget
  221 + ref="widgets"
  222 + v-for="(widget, index) in widgets"
  223 + :key="index"
  224 + v-model="widget.value"
  225 + :index="index"
  226 + :stepX="stepX"
  227 + :stepY="stepY"
  228 + :type="widget.type"
  229 + :bigscreen="{ bigscreenWidth, bigscreenHeight }"
  230 + @onActivated="setOptionsOnClickWidget"
  231 + @contextmenu.prevent.native="rightClick($event, index)"
  232 + @mousedown.prevent.native="widgetsClick(index)"
  233 + @mouseup.prevent.native="widgetsMouseup"
  234 + />
  235 + </div>
  236 + </vue-ruler-tool>
  237 + </div>
  238 + </div>
  239 + <!-- 右侧是否显示-->
  240 + <div
  241 + class="layout-left-fold"
  242 + :style="{ width: widthRightForToolsHideButton + 'px' }"
  243 + @click="setupIsShow = !setupIsShow">
  244 + <i :class="[setupIsShow?' el-icon-arrow-right':'el-icon-arrow-left']"/>
  245 + </div>
  246 + <!-- 右侧配置-->
  247 + <div class="layout-right" :style="{ width: widthLeftForOptions + 'px' }" v-if="setupIsShow">
  248 + <el-tabs v-model="activeName" type="border-card" :stretch="true">
  249 + <el-tab-pane
  250 + v-if="
  251 + this.isNotNull(widgetOptions.setup) || this.isNotNull(widgetOptions.collapse)
  252 + "
  253 + name="first"
  254 + label="配置"
  255 + >
  256 + <dynamicForm
  257 + ref="formData"
  258 + :options="widgetOptions.setup"
  259 + @onChanged="(val) => widgetValueChanged('setup', val)"
  260 + />
  261 + </el-tab-pane>
  262 + <el-tab-pane
  263 + v-if="this.isNotNull(widgetOptions.data)"
  264 + name="second"
  265 + label="数据"
  266 + >
  267 + <dynamicForm
  268 + ref="formData"
  269 + :options="widgetOptions.data"
  270 + @onChanged="(val) => widgetValueChanged('data', val)"
  271 + />
  272 + </el-tab-pane>
  273 + <el-tab-pane
  274 + v-if="this.isNotNull(widgetOptions.position)"
  275 + name="third"
  276 + label="坐标"
  277 + >
  278 + <dynamicForm
  279 + ref="formData"
  280 + :options="widgetOptions.position"
  281 + @onChanged="(val) => widgetValueChanged('position', val)"
  282 + />
  283 + </el-tab-pane>
  284 + </el-tabs>
  285 + </div>
  286 +
  287 + <content-menu
  288 + :visible.sync="visibleContentMenu"
  289 + :style-obj="styleObj"
  290 + @deletelayer="deletelayer"
  291 + @copylayer="copylayer"
  292 + @istopLayer="istopLayer"
  293 + @setlowLayer="setlowLayer"
  294 + @moveupLayer="moveupLayer"
  295 + @movedownLayer="movedownLayer"
  296 + />
  297 + </div>
  298 +</template>
  299 +
  300 +<script>
  301 +import {
  302 + insertDashboard,
  303 + detailDashboard,
  304 + importDashboard,
  305 + exportDashboard,
  306 +} from "@/api/bigscreen";
  307 +import { widgetTools, getToolByCode } from "./tools/index";
  308 +import widget from "./widget/widget.vue";
  309 +import dynamicForm from "./components/dynamicForm.vue";
  310 +import draggable from "vuedraggable";
  311 +import VueRulerTool from "vue-ruler-tool"; // 大屏设计页面的标尺插件
  312 +import contentMenu from "./components/contentMenu";
  313 +import { getToken } from "@/utils/auth";
  314 +import { Revoke } from "@/utils/revoke";
  315 +import { mapMutations } from 'vuex';
  316 +import process from "process";
  317 +
  318 +export default {
  319 + name: "Login",
  320 + components: {
  321 + draggable,
  322 + VueRulerTool,
  323 + widget,
  324 + dynamicForm,
  325 + contentMenu
  326 + },
  327 + data() {
  328 + return {
  329 + uploadUrl:process.env.BASE_API +"/reportDashboard/import/" +this.$route.query.reportCode,
  330 + grade: false,
  331 + layerWidget: [],
  332 + widgetTools: widgetTools, // 左侧工具栏的组件图标,将js变量加入到当前作用域
  333 + widthLeftForTools: 200, // 左侧工具栏宽度
  334 + widthLeftForToolsHideButton: 15, // 左侧工具栏折叠按钮宽度
  335 + widthRightForToolsHideButton: 15, // 右侧工具栏折叠按钮宽度
  336 + widthLeftForOptions: 300, // 右侧属性配置区
  337 + widthPaddingTools: 18,//vueRuler
  338 + toolIsShow: true, // 左侧工具栏是否显示
  339 + setupIsShow: true, // 右侧配置是否显示
  340 + bigscreenWidth: 1920, // 大屏设计的大小
  341 + bigscreenHeight: 1080,
  342 + revoke: null,
  343 +
  344 + // 工作台大屏画布,保存到表gaea_report_dashboard中
  345 + dashboard: {
  346 + id: null,
  347 + title: "", // 大屏页面标题
  348 + width: 1920, // 大屏设计宽度
  349 + height: 1080, // 大屏设计高度
  350 + backgroundColor: "", // 大屏背景色
  351 + backgroundImage: "", // 大屏背景图片
  352 + refreshSeconds: null, // 大屏刷新时间间隔
  353 + presetLine: [], // 辅助线
  354 + presetLineVisible: true, // 辅助线是否显示
  355 + data: {},
  356 + },
  357 + masterData:{},//主表数据源
  358 + // 大屏的标记
  359 + screenCode: "",
  360 + dragWidgetCode: "", //从工具栏拖拽的组件code
  361 + // 大屏画布中的组件
  362 + widgets: [
  363 + {
  364 + // type和value最终存到数据库中去,保存到gaea_report_dashboard_widget中
  365 + type: "widget-text",
  366 + value: {
  367 + setup: {},
  368 + data: {},
  369 + position: {
  370 + width: 100,
  371 + height: 100,
  372 + left: 0,
  373 + top: 0,
  374 + zIndex: 0,
  375 + },
  376 + },
  377 + // options属性是从工具栏中拿到的tools中拿到
  378 + options: [],
  379 + },
  380 + ], // 工作区中拖放的组件
  381 +
  382 + // 当前激活组件
  383 + widgetIndex: 0,
  384 + // 当前激活组件右侧配置属性
  385 + widgetOptions: {
  386 + setup: [], // 配置
  387 + data: [], // 数据
  388 + position: [], // 坐标
  389 + },
  390 + flagWidgetClickStopPropagation: false, // 点击组件时阻止事件冒泡传递到画布click事件上
  391 + styleObj: {
  392 + left: 0,
  393 + top: 0,
  394 + },
  395 + visibleContentMenu: false,
  396 + rightClickIndex: -1,
  397 + activeName: "first",
  398 + };
  399 + },
  400 + computed: {
  401 + stepX() {
  402 + return Number(100 / (this.bigscreenScaleInWorkbenchX * 100));
  403 + },
  404 + stepY() {
  405 + return Number(100 / (this.bigscreenScaleInWorkbenchY * 100));
  406 + },
  407 + headers() {
  408 + return {
  409 + Authorization: getToken(), // 直接从本地获取token就行
  410 + };
  411 + },
  412 + // 左侧、右侧折叠切换时,动态计算中间区的宽度
  413 + middleWidth() {
  414 + if(!this.setupIsShow && !this.toolIsShow){
  415 + return document.documentElement.clientWidth - this.widthPaddingTools;
  416 + }
  417 + return this.bodyWidth - this.widthLeftAndRight();
  418 + },
  419 + middleHeight() {
  420 + return this.bodyHeight;
  421 + },
  422 + // 设计台按大屏的缩放比例
  423 + bigscreenScaleInWorkbench() {
  424 + let widthScale =
  425 + (this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth;
  426 + let heightScale =
  427 + (this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight;
  428 + return Math.min(widthScale, heightScale);
  429 + },
  430 + bigscreenScaleInWorkbenchX() {
  431 + let widthScale =
  432 + (this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth;
  433 + return widthScale;
  434 + },
  435 + bigscreenScaleInWorkbenchY() {
  436 + let heightScale =
  437 + (this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight;
  438 + return heightScale;
  439 + },
  440 + workbenchTransform() {
  441 + return `scale(${this.bigscreenScaleInWorkbenchX}, ${this.bigscreenScaleInWorkbenchY})`;
  442 + },
  443 + // 大屏在设计模式的大小
  444 + bigscreenWidthInWorkbench() {
  445 + return this.getPXUnderScaleX(this.bigscreenWidth) + this.widthPaddingTools;
  446 + },
  447 + bigscreenHeightInWorkbench() {
  448 + return (
  449 + this.getPXUnderScaleY(this.bigscreenHeight) + this.widthPaddingTools
  450 + );
  451 + },
  452 + // 尺子的宽度高度
  453 + // bigscreenWidthRuler() {
  454 + // return this.middleWidth;
  455 + // },
  456 + // bigscreenHeightRuler() {
  457 + // return this.middleHeight;
  458 + // },
  459 + },
  460 + watch: {
  461 + widgets: {
  462 + handler(val) {
  463 + this.handlerLayerWidget(val);
  464 + //以下部分是记录历史
  465 + this.$nextTick(() => {
  466 + this.revoke.push(this.widgets);
  467 + });
  468 + },
  469 + deep: true,
  470 + },
  471 + },
  472 + created() {
  473 + /* 以下是记录历史的 */
  474 + this.revoke = new Revoke();
  475 + },
  476 + mounted() {
  477 + // 如果是新的设计工作台
  478 + this.initEchartData();
  479 + this.widgets = [];
  480 + window.addEventListener("mouseup", () => {
  481 + this.grade = false;
  482 + });
  483 + },
  484 + methods: {
  485 + ...mapMutations('dataSource', ['SET_STATIC_DATA']),
  486 + /**
  487 + * @description: 恢复
  488 + * @param {*}
  489 + * @return {*}
  490 + */
  491 + handleUndo() {
  492 + const record = this.revoke.undo();
  493 + if (!record) {
  494 + return false;
  495 + }
  496 + this.widgets = record;
  497 + },
  498 + /**
  499 + * @description: 重做
  500 + * @param {*}
  501 + * @return {*}
  502 + */
  503 + handleRedo() {
  504 + const record = this.revoke.redo();
  505 + if (!record) {
  506 + return false;
  507 + }
  508 + this.widgets = record;
  509 + },
  510 + handlerLayerWidget(val) {
  511 + const layerWidgetArr = [];
  512 + for (let i = 0; i < val.length; i++) {
  513 + const obj = {};
  514 + obj.icon = getToolByCode(val[i].type).icon;
  515 + const options = val[i].options["setup"];
  516 + options.forEach((el) => {
  517 + if (el.name == "layerName") {
  518 + obj.label = el.value;
  519 + }
  520 + });
  521 + layerWidgetArr.push(obj);
  522 + }
  523 + this.layerWidget = layerWidgetArr;
  524 + },
  525 + async initEchartData() {
  526 + const reportCode = this.$route.query.reportCode;
  527 + const { code, data } = await detailDashboard(reportCode);
  528 + if (code != 200) return;
  529 + const processData = this.handleInitEchartsData(data);
  530 + const screenData = this.handleBigScreen(data.dashboard);
  531 + this.widgets = processData;
  532 + this.dashboard = screenData;
  533 + this.bigscreenWidth = this.dashboard.width;
  534 + this.bigscreenHeight = this.dashboard.height;
  535 + //判断数据源是否配置了主数据源,如果配置了主数据,将主数据转换成静态的保存
  536 + if(this.isNotBlankObj(screenData)){
  537 + this.setMasterData(screenData);
  538 + //将动态数据部分赋值
  539 + //console.log("将动态数据部分赋值",this.widgetOptions);
  540 + this.setWidgetOptionsData(screenData.data);
  541 + }
  542 + },
  543 + // 数据处理
  544 + setMasterData(screenData){
  545 + // 数据类型 静态 or 动态
  546 + const screenD = screenData.data;
  547 + const refreshTime = screenD["refreshTime"]||60000*30;
  548 + screenD.dataType == "staticData"
  549 + ? this.staticDataFn(screenD.staticData)
  550 + : this.dynamicDataFn(screenD.dynamicData, refreshTime);
  551 + },
  552 + staticDataFn(val) {
  553 + //获取静态数据
  554 + this.masterData=val;
  555 + this.SET_STATIC_DATA(this.masterData);
  556 + },
  557 + dynamicDataFn(val, refreshTime) {
  558 + if (!val) return;
  559 + if (this.ispreview) {
  560 + this.getEchartData(val);
  561 + this.flagInter = setInterval(() => {
  562 + this.getEchartData(val);
  563 + }, refreshTime);
  564 + } else {
  565 + this.getEchartData(val);
  566 + }
  567 + },
  568 + getEchartData(val) {
  569 + const data = this.queryEchartsData(val);
  570 + data.then(res => {
  571 + this.renderingFn(res);
  572 + });
  573 + },
  574 + renderingFn(val) {
  575 + if(this.isNotBlankArray(val)){
  576 + for (let i = 0; i < val.length; i++) {
  577 + const one = val[i];
  578 + const sValue = (this.isBlankObject(one)|| this.isBlank(one['sValue']))?"":one['sValue'];
  579 + if(this.isNotBlankObj(one) && this.isNotBlank(one['sName'])){
  580 + const sName = one['sName'];
  581 + this.masterData[sName]=sValue;
  582 + }
  583 + }
  584 + }
  585 + this.SET_STATIC_DATA(this.masterData);
  586 + },
  587 +
  588 + handleBigScreen(data) {
  589 + const optionScreen = getToolByCode("screen").options;
  590 + const setup = optionScreen.setup;
  591 + for (const key in data) {
  592 + for (let i = 0; i < setup.length; i++) {
  593 + if (key == setup[i].name) {
  594 + setup[i].value = data[key];
  595 + }
  596 + }
  597 + }
  598 + this.setOptionsOnClickScreen();
  599 + return {
  600 + backgroundColor: (data && data.backgroundColor) || "",
  601 + backgroundImage: (data && data.backgroundImage) || "",
  602 + height: (data && data.height) || 1080,
  603 + title: (data && data.title) || "",
  604 + description: (data && data.description) || "",
  605 + width: (data && data.width) || 1920,
  606 + data: (data && data.data) || {},
  607 + };
  608 + },
  609 + handleInitEchartsData(data) {
  610 + const widgets = data.dashboard ? data.dashboard.widgets : [];
  611 + const widgetsData = [];
  612 + for (let i = 0; i < widgets.length; i++) {
  613 + let obj = {};
  614 + obj.type = widgets[i].type;
  615 + obj.value = {
  616 + setup: widgets[i].value.setup,
  617 + data: widgets[i].value.data,
  618 + position: widgets[i].value.position,
  619 + };
  620 + const tool = this.deepClone(getToolByCode(widgets[i].type));
  621 + const option = tool.options;
  622 + const options = this.handleOptionsData(widgets[i].value, option);
  623 + obj.options = options;
  624 + widgetsData.push(obj);
  625 + }
  626 + return widgetsData;
  627 + },
  628 + handleOptionsData(data, option) {
  629 + for (const key in data.setup) {
  630 + for (let i = 0; i < option.setup.length; i++) {
  631 + let item = option.setup[i];
  632 + if (Object.prototype.toString.call(item) == "[object Object]") {
  633 + if (key == option.setup[i].name) {
  634 + option.setup[i].value = data.setup[key];
  635 + }
  636 + } else if (Object.prototype.toString.call(item) == "[object Array]") {
  637 + for (let j = 0; j < item.length; j++) {
  638 + const list = item[j].list;
  639 + list.forEach((el) => {
  640 + if (key == el.name) {
  641 + el.value = data.setup[key];
  642 + }
  643 + });
  644 + }
  645 + }
  646 + }
  647 + }
  648 + // position
  649 + for (const key in data.position) {
  650 + for (let i = 0; i < option.position.length; i++) {
  651 + if (key == option.position[i].name) {
  652 + option.position[i].value = data.position[key];
  653 + }
  654 + }
  655 + }
  656 + // data
  657 + for (const key in data.data) {
  658 + for (let i = 0; i < option.data.length; i++) {
  659 + if (key == option.data[i].name) {
  660 + option.data[i].value = data.data[key];
  661 + }
  662 + }
  663 + }
  664 + return option;
  665 + },
  666 + // 保存数据
  667 + async saveData() {
  668 + if (!this.widgets || this.widgets.length == 0) {
  669 + this.$message.error("请添加组件");
  670 + return;
  671 + }
  672 + // console.log("保存数据DATA",this.dashboard);
  673 + const screenData = {
  674 + reportCode: this.$route.query.reportCode,
  675 + dashboard: {
  676 + title: this.dashboard.title,
  677 + width: this.dashboard.width,
  678 + height: this.dashboard.height,
  679 + backgroundColor: this.dashboard.backgroundColor,
  680 + data: this.dashboard.data,
  681 + backgroundImage: this.dashboard.backgroundImage,
  682 + },
  683 + widgets: this.widgets,
  684 + };
  685 + // console.log(screenData);
  686 + const { code, data } = await insertDashboard(screenData);
  687 + if (code == "200") {
  688 + this.$message.success("保存成功!");
  689 + }
  690 + },
  691 + // 预览
  692 + viewScreen() {
  693 + let routeUrl = this.$router.resolve({
  694 + path: "/bigscreen/viewer",
  695 + query: { reportCode: this.$route.query.reportCode },
  696 + });
  697 + window.open(routeUrl.href, "_blank");
  698 + },
  699 + // 导出
  700 + async exportDashboard(val) {
  701 + const fileName = this.$route.query.reportCode + ".zip";
  702 +
  703 + const param = {
  704 + reportCode: this.$route.query.reportCode,
  705 + showDataSet: val,
  706 + };
  707 + exportDashboard(param).then((res) => {
  708 + const that = this;
  709 + const type = res.type;
  710 + if (type == "application/json") {
  711 + let reader = new FileReader();
  712 + reader.readAsText(res, "utf-8");
  713 + reader.onload = function () {
  714 + const data = JSON.parse(reader.result);
  715 + that.$message.error(data.message);
  716 + };
  717 + return;
  718 + }
  719 +
  720 + const blob = new Blob([res], { type: "application/octet-stream" });
  721 + if (window.navigator.msSaveOrOpenBlob) {
  722 + //msSaveOrOpenBlob方法返回bool值
  723 + navigator.msSaveBlob(blob, fileName); //本地保存
  724 + } else {
  725 + const link = document.createElement("a"); //a标签下载
  726 + link.href = window.URL.createObjectURL(blob);
  727 + link.download = fileName;
  728 + link.click();
  729 + window.URL.revokeObjectURL(link.href);
  730 + }
  731 + });
  732 + },
  733 + // 上传成功的回调
  734 + handleUpload(response, file, fileList) {
  735 + //清除el-upload组件中的文件
  736 + this.$refs.upload.clearFiles();
  737 + //刷新大屏页面
  738 + this.initEchartData();
  739 + if (response.code == "200") {
  740 + this.$message({
  741 + message: "导入成功!",
  742 + type: "success",
  743 + });
  744 + } else {
  745 + this.$message({
  746 + message: response.message,
  747 + type: "error",
  748 + });
  749 + }
  750 + },
  751 + handleError(err) {
  752 + this.$message({
  753 + message: "上传失败!",
  754 + type: "error",
  755 + });
  756 + },
  757 + //中间区域减去的宽度
  758 + widthLeftAndRight(){
  759 + let widthLeftAndRight = 0;
  760 + if (this.toolIsShow) {
  761 + widthLeftAndRight += this.widthLeftForTools; // 左侧工具栏宽度
  762 + widthLeftAndRight += this.widthLeftForToolsHideButton; // 左侧工具栏折叠按钮宽度
  763 + }
  764 + if (this.setupIsShow) {
  765 + widthLeftAndRight += this.widthLeftForOptions; // 右侧配置栏宽度
  766 + widthLeftAndRight += this.widthRightForToolsHideButton; // 右侧工具栏折叠按钮宽度
  767 + }
  768 + // console.log("中间区域增加的宽度",widthLeftAndRight,this.setupIsShow,this.toolIsShow)
  769 + return widthLeftAndRight;
  770 + },
  771 + // 在缩放模式下的大小
  772 + getPXUnderScaleX(px) {
  773 + return this.bigscreenScaleInWorkbenchX * px;
  774 + },
  775 + getPXUnderScaleY(px) {
  776 + return this.bigscreenScaleInWorkbenchY * px;
  777 + },
  778 + dragStart(widgetCode) {
  779 + this.dragWidgetCode = widgetCode;
  780 + },
  781 + dragEnd() {
  782 + this.dragWidgetCode = "";
  783 + },
  784 + dragOver(evt) {
  785 + evt.preventDefault();
  786 + evt.stopPropagation();
  787 + evt.dataTransfer.dropEffect = "copy";
  788 + },
  789 + // 拖动一个组件放到工作区中去,在拖动结束时,放到工作区对应的坐标点上去
  790 + widgetOnDragged(evt) {
  791 + let widgetType = this.dragWidgetCode;
  792 +
  793 + // 获取结束坐标和列名
  794 + let eventX = evt.clientX; // 结束在屏幕的x坐标
  795 + let eventY = evt.clientY; // 结束在屏幕的y坐标
  796 +
  797 + let workbenchPosition = this.getDomTopLeftById("workbench");
  798 + let widgetTopInWorkbench = eventY - workbenchPosition.top;
  799 + let widgetLeftInWorkbench = eventX - workbenchPosition.left;
  800 +
  801 + // 计算在缩放模式下的x y
  802 + let x = widgetLeftInWorkbench / this.bigscreenScaleInWorkbench;
  803 + let y = widgetTopInWorkbench / this.bigscreenScaleInWorkbench;
  804 +
  805 + // 复制一个组件
  806 + let tool = getToolByCode(widgetType);
  807 + let widgetJson = {
  808 + type: widgetType,
  809 + value: {
  810 + setup: {},
  811 + data: {},
  812 + position: {
  813 + width: 0,
  814 + height: 0,
  815 + left: 0,
  816 + top: 0,
  817 + zIndex: 0,
  818 + },
  819 + },
  820 + options: tool.options,
  821 + };
  822 + // 处理默认值
  823 + const widgetJsonValue = this.handleDefaultValue(widgetJson);
  824 +
  825 + //可以拖拽放到鼠标的位置
  826 + widgetJsonValue.value.position.left =
  827 + x - widgetJsonValue.value.position.width / 2;
  828 + widgetJsonValue.value.position.top =
  829 + y - widgetJsonValue.value.position.height / 2;
  830 +
  831 + // 将选中的复制组件,放到工作区中去
  832 + this.widgets.push(this.deepClone(widgetJsonValue));
  833 + // 激活新组件的配置属性
  834 + this.setOptionsOnClickWidget(this.widgets.length - 1);
  835 + },
  836 +
  837 + // 对组件默认值处理
  838 + handleDefaultValue(widgetJson) {
  839 + for (const key in widgetJson) {
  840 + if (key == "options") {
  841 + // collapse、data、position、setup
  842 + // setup 处理
  843 + for (let i = 0; i < widgetJson.options.setup.length; i++) {
  844 + const item = widgetJson.options.setup[i];
  845 + if (Object.prototype.toString.call(item) == "[object Object]") {
  846 + widgetJson.value.setup[item.name] = item.value;
  847 + } else if (
  848 + Object.prototype.toString.call(item) == "[object Array]"
  849 + ) {
  850 + for (let j = 0; j < item.length; j++) {
  851 + const list = item[j].list;
  852 + list.forEach((el) => {
  853 + widgetJson.value.setup[el.name] = el.value;
  854 + });
  855 + }
  856 + }
  857 + }
  858 + // position
  859 + for (let i = 0; i < widgetJson.options.position.length; i++) {
  860 + const item = widgetJson.options.position[i];
  861 + if (item.value) {
  862 + widgetJson.value.position[item.name] = item.value;
  863 + }
  864 + }
  865 + // data 处理
  866 + if (widgetJson.options.data && widgetJson.options.data.length > 0) {
  867 + for (let i = 0; i < widgetJson.options.data.length; i++) {
  868 + const item = widgetJson.options.data[i];
  869 + if (item.value) {
  870 + widgetJson.value.data[item.name] = item.value;
  871 + }
  872 + }
  873 + }
  874 + }
  875 + }
  876 + return widgetJson;
  877 + },
  878 + layerClick(index) {
  879 + this.widgetIndex = index;
  880 + this.widgetsClick(index);
  881 + },
  882 + // 如果是点击大屏设计器中的底层,加载大屏底层属性
  883 + setOptionsOnClickScreen() {
  884 + this.screenCode = "screen";
  885 + // 选中不同的组件 右侧都显示第一栏
  886 + this.activeName = "first";
  887 + this.widgetOptions = getToolByCode("screen")["options"];
  888 + },
  889 + getScreenData(data){
  890 + const screenData = {};
  891 + if(this.isNotBlankArray(data)){
  892 + for (let i = 0; i < data.length; i++) {
  893 + const one =data[i];
  894 + screenData[one.name]=one.value;
  895 + }
  896 + }
  897 + return screenData;
  898 + },
  899 +
  900 + // 如果是点击某个组件,获取该组件的配置项
  901 + setOptionsOnClickWidget(obj) {
  902 + this.screenCode = "";
  903 + if (typeof obj == "number") {
  904 + this.widgetOptions = {};
  905 + // 直接赋值数据不刷新。。。
  906 + this.$nextTick(() => {
  907 + this.widgetOptions = this.deepClone(this.widgets[obj]["options"]);
  908 + });
  909 + return;
  910 + }
  911 + if (obj.index < 0 || obj.index >= this.widgets.length) {
  912 + return;
  913 + }
  914 + this.widgetIndex = obj.index;
  915 + this.widgets[obj.index].value.position = obj;
  916 + this.widgets[obj.index].options.position.forEach((el) => {
  917 + for (const key in obj) {
  918 + if (el.name == key) {
  919 + el.value = obj[key];
  920 + }
  921 + }
  922 + });
  923 + this.widgetOptions = this.deepClone(this.widgets[obj.index]["options"]);
  924 + },
  925 + widgetsClick(index) {
  926 + const draggableArr = this.$refs.widgets;
  927 + for (let i = 0; i < draggableArr.length; i++) {
  928 + if (i == index) {
  929 + this.$refs.widgets[i].$refs.draggable.setActive(true);
  930 + } else {
  931 + this.$refs.widgets[i].$refs.draggable.setActive(false);
  932 + }
  933 + }
  934 + this.setOptionsOnClickWidget(index);
  935 + this.grade = true;
  936 + },
  937 + widgetsMouseup(e) {
  938 + this.grade = false;
  939 + },
  940 + handleMouseDown() {
  941 + const draggableArr = this.$refs.widgets;
  942 + for (let i = 0; i < draggableArr.length; i++) {
  943 + this.$refs.widgets[i].$refs.draggable.setActive(false);
  944 + }
  945 + },
  946 + setWidgetOptionsData(val){
  947 + let newData = new Array();
  948 + const cloneVal = this.deepClone(val);
  949 + this.widgetOptions.data.forEach((el) => {
  950 + if (Object.hasOwn(cloneVal, el.name)) {
  951 + el["value"] = cloneVal[el.name];
  952 + }
  953 + newData.push(el);
  954 + });
  955 + this.widgetOptions.data = newData;
  956 + },
  957 + // 将当前选中的组件,右侧属性值更新
  958 + widgetValueChanged(key, val) {
  959 + if (this.screenCode == "screen") {
  960 + if (key === 'setup') {
  961 + // 全局配置更改
  962 + let newSetup = new Array();
  963 + this.dashboard = this.deepClone(val);
  964 + if (this.bigscreenWidth !== this.dashboard.width && this.dashboard.width) {
  965 + this.bigscreenWidth = this.dashboard.width;
  966 + }
  967 + if (this.bigscreenHeight !== this.dashboard.height && this.dashboard.height) {
  968 + this.bigscreenHeight = this.dashboard.height;
  969 + }
  970 +
  971 + this.widgetOptions.setup.forEach((el) => {
  972 + if (el.name == "width") {
  973 + el.value = this.bigscreenWidth;
  974 + } else if (el.name == "height") {
  975 + el.value = this.bigscreenHeight;
  976 + } else if (Object.hasOwn(this.dashboard, el.name)) {
  977 + el["value"] = this.dashboard[el.name];
  978 + }
  979 + newSetup.push(el);
  980 + });
  981 + this.widgetOptions.setup = newSetup;
  982 + } else if (key === 'data') {
  983 + // 全局数据更改
  984 + this.dashboard.data=val;
  985 + let newData = new Array();
  986 + const cloneVal = this.deepClone(val);
  987 + this.widgetOptions.data.forEach((el) => {
  988 + if (Object.hasOwn(cloneVal, el.name)) {
  989 + el["value"] = cloneVal[el.name];
  990 + }
  991 + newData.push(el);
  992 + });
  993 + this.widgetOptions.data = newData;
  994 + this.setMasterData(this.dashboard);
  995 + }
  996 + } else {
  997 + for (let i = 0; i < this.widgets.length; i++) {
  998 + if (this.widgetIndex == i) {
  999 + this.widgets[i].value[key] = this.deepClone(val);
  1000 + this.setDefaultValue(this.widgets[i].options[key], val);
  1001 + }
  1002 + }
  1003 + }
  1004 + },
  1005 + rightClick(event, index) {
  1006 + this.rightClickIndex = index;
  1007 + const left = event.clientX;
  1008 + const top = event.clientY;
  1009 + if (left || top) {
  1010 + this.styleObj = {
  1011 + left: left + "px",
  1012 + top: top + "px",
  1013 + display: "block",
  1014 + };
  1015 + }
  1016 + this.visibleContentMenu = true;
  1017 + return false;
  1018 + },
  1019 + setDefaultValue(options, val) {
  1020 + for (let i = 0; i < options.length; i++) {
  1021 + if (Object.prototype.toString.call(options[i]) == "[object Object]") {
  1022 + for (const k in val) {
  1023 + if (options[i].name == k) {
  1024 + options[i].value = val[k];
  1025 + }
  1026 + }
  1027 + } else if (
  1028 + Object.prototype.toString.call(options[i]) == "[object Array]"
  1029 + ) {
  1030 + for (let j = 0; j < options[i].length; j++) {
  1031 + const list = options[i][j].list;
  1032 + for (let z = 0; z < list.length; z++) {
  1033 + for (const k in val) {
  1034 + if (list[z].name == k) {
  1035 + list[z].value = val[k];
  1036 + }
  1037 + }
  1038 + }
  1039 + }
  1040 + }
  1041 + }
  1042 + },
  1043 + datadragEnd(evt) {
  1044 + evt.preventDefault();
  1045 + this.widgets = this.swapArr(this.widgets, evt.oldIndex, evt.newIndex);
  1046 + },
  1047 + // 数组 元素互换位置
  1048 + swapArr(arr, oldIndex, newIndex) {
  1049 + arr[oldIndex] = arr.splice(newIndex, 1, arr[oldIndex])[0];
  1050 + return arr;
  1051 + },
  1052 + // 删除
  1053 + deletelayer() {
  1054 + this.widgets.splice(this.rightClickIndex, 1);
  1055 + },
  1056 + // 复制
  1057 + copylayer() {
  1058 + const obj = this.deepClone(this.widgets[this.rightClickIndex]);
  1059 + this.widgets.splice(this.widgets.length, 0, obj);
  1060 + },
  1061 + // 置顶
  1062 + istopLayer() {
  1063 + if (this.rightClickIndex + 1 < this.widgets.length) {
  1064 + const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
  1065 + this.widgets.push(temp);
  1066 + }
  1067 + },
  1068 + // 置底
  1069 + setlowLayer() {
  1070 + if (this.rightClickIndex != 0) {
  1071 + this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
  1072 + }
  1073 + },
  1074 + // 上移一层
  1075 + moveupLayer() {
  1076 + if (this.rightClickIndex != 0) {
  1077 + this.widgets[this.rightClickIndex] = this.widgets.splice(
  1078 + this.rightClickIndex - 1,
  1079 + 1,
  1080 + this.widgets[this.rightClickIndex]
  1081 + )[0];
  1082 + } else {
  1083 + this.widgets.push(this.widgets.shift());
  1084 + }
  1085 + },
  1086 + // 下移一层
  1087 + movedownLayer() {
  1088 + if (this.rightClickIndex != this.widgets.length - 1) {
  1089 + this.widgets[this.rightClickIndex] = this.widgets.splice(
  1090 + this.rightClickIndex + 1,
  1091 + 1,
  1092 + this.widgets[this.rightClickIndex]
  1093 + )[0];
  1094 + } else {
  1095 + this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
  1096 + }
  1097 + },
  1098 + },
  1099 +};
  1100 +</script>
  1101 +
  1102 +<style scoped lang="scss">
  1103 +.mr10 {
  1104 + margin-right: 10px;
  1105 +}
  1106 +
  1107 +.ml20 {
  1108 + margin-left: 20px;
  1109 +}
  1110 +
  1111 +.border-right {
  1112 + border-right: 1px solid #273b4d;
  1113 +}
  1114 +
  1115 +.border-left {
  1116 + border-left: 1px solid #273b4d;
  1117 +}
  1118 +
  1119 +.el-icon-arrow-down {
  1120 + font-size: 10px;
  1121 +}
  1122 +
  1123 +.is-active {
  1124 + background: #31455d !important;
  1125 + color: #bfcbd9 !important;
  1126 +}
  1127 +
  1128 +.layout {
  1129 + display: -webkit-box;
  1130 + display: -ms-flexbox;
  1131 + display: flex;
  1132 + width: 100%;
  1133 + height: 100%;
  1134 + -webkit-box-sizing: border-box;
  1135 + box-sizing: border-box;
  1136 + overflow: hidden;
  1137 +
  1138 + .layout-left {
  1139 + display: inline-block;
  1140 + height: 100%;
  1141 + box-sizing: border-box;
  1142 + -webkit-box-sizing: border-box;
  1143 + border: 0px;
  1144 + background-color: #263445;
  1145 +
  1146 + //工具栏一个元素
  1147 + .tools-item {
  1148 + display: flex;
  1149 + position: relative;
  1150 + width: 100%;
  1151 + height: 48px;
  1152 + align-items: center;
  1153 + -webkit-box-align: center;
  1154 + padding: 0 6px;
  1155 + cursor: pointer;
  1156 + font-size: 12px;
  1157 + margin-bottom: 1px;
  1158 +
  1159 + .tools-item-icon {
  1160 + color: #409eff;
  1161 + margin-right: 10px;
  1162 + width: 53px;
  1163 + height: 30px;
  1164 + line-height: 30px;
  1165 + text-align: center;
  1166 + display: block;
  1167 + border: 1px solid #3a4659;
  1168 + background: #282a30;
  1169 + }
  1170 + .tools-item-text {
  1171 + }
  1172 + }
  1173 + }
  1174 +
  1175 + .layout-left-fold {
  1176 + display: -webkit-box;
  1177 + display: -ms-flexbox;
  1178 + display: flex;
  1179 + height: 100%;
  1180 +
  1181 + font-size: 12px;
  1182 + overflow: hidden;
  1183 + background-color: #242a30;
  1184 + cursor: pointer;
  1185 + padding-top: 26%;
  1186 +
  1187 + i {
  1188 + font-size: 18px;
  1189 + width: 18px;
  1190 + height: 23px;
  1191 + margin-left: 0px;
  1192 + color: #bfcbd9;
  1193 + }
  1194 + }
  1195 +
  1196 + .layout-middle {
  1197 + //display: flex;
  1198 + position: relative;
  1199 + //width: calc(100% - 445px);
  1200 + height: 100%;
  1201 + background-color: rgb(36, 42, 48);
  1202 + box-sizing: border-box;
  1203 + -webkit-box-sizing: border-box;
  1204 + border: 1px solid rgb(36, 42, 48);
  1205 + align-items: center;
  1206 + vertical-align: middle;
  1207 + text-align: center;
  1208 +
  1209 + .top-button {
  1210 + display: flex;
  1211 + flex-direction: row;
  1212 + height: 40px;
  1213 + line-height: 40px;
  1214 + margin-left: 9px;
  1215 +
  1216 + .btn {
  1217 + color: #788994;
  1218 + width: 55px;
  1219 + text-align: center;
  1220 + display: block;
  1221 + cursor: pointer;
  1222 +
  1223 + .el-icon-arrow-down {
  1224 + transform: rotate(0deg);
  1225 + -ms-transform: rotate(0deg); /* IE 9 */
  1226 + -moz-transform: rotate(0deg); /* Firefox */
  1227 + -webkit-transform: rotate(0deg); /* Safari 和 Chrome */
  1228 + -o-transform: rotate(0deg); /* Opera */
  1229 + transition: all 0.4s ease-in-out;
  1230 + }
  1231 +
  1232 + &:hover {
  1233 + background: rgb(25, 29, 34);
  1234 +
  1235 + .el-icon-arrow-down {
  1236 + transform: rotate(180deg);
  1237 + -ms-transform: rotate(180deg); /* IE 9 */
  1238 + -moz-transform: rotate(180deg); /* Firefox */
  1239 + -webkit-transform: rotate(180deg); /* Safari 和 Chrome */
  1240 + -o-transform: rotate(180deg); /* Opera */
  1241 + transition: all 0.4s ease-in-out;
  1242 + }
  1243 + }
  1244 + }
  1245 + }
  1246 +
  1247 + .workbench-container {
  1248 + position: relative;
  1249 + -webkit-transform-origin: 0 0;
  1250 + transform-origin: 0 0;
  1251 + -webkit-box-sizing: border-box;
  1252 + box-sizing: border-box;
  1253 + margin: 0;
  1254 + padding: 0;
  1255 +
  1256 + .vueRuler {
  1257 + width: 100%;
  1258 + padding: 18px 0px 0px 18px;
  1259 + }
  1260 +
  1261 + .workbench {
  1262 + background-color: #1e1e1e;
  1263 + position: relative;
  1264 + -webkit-user-select: none;
  1265 + -moz-user-select: none;
  1266 + -ms-user-select: none;
  1267 + user-select: none;
  1268 + -webkit-transform-origin: 0 0;
  1269 + transform-origin: 0 0;
  1270 + margin: 0;
  1271 + padding: 0;
  1272 + }
  1273 +
  1274 + .bg-grid {
  1275 + position: absolute;
  1276 + top: 0;
  1277 + left: 0;
  1278 + width: 100%;
  1279 + height: 100%;
  1280 + background-size: 30px 30px, 30px 30px;
  1281 + background-image: linear-gradient(
  1282 + hsla(0, 0%, 100%, 0.1) 1px,
  1283 + transparent 0
  1284 + ),
  1285 + linear-gradient(90deg, hsla(0, 0%, 100%, 0.1) 1px, transparent 0);
  1286 + // z-index: 2;
  1287 + }
  1288 + }
  1289 +
  1290 + .bottom-text {
  1291 + width: 100%;
  1292 + color: #a0a0a0;
  1293 + font-size: 16px;
  1294 + position: absolute;
  1295 + bottom: 20px;
  1296 + }
  1297 + }
  1298 +
  1299 + .layout-right {
  1300 + display: inline-block;
  1301 + height: 100%;
  1302 + }
  1303 +
  1304 + /deep/ .el-tabs--border-card {
  1305 + border: 0;
  1306 +
  1307 + .el-tabs__header {
  1308 + .el-tabs__nav {
  1309 + .el-tabs__item {
  1310 + background-color: #242f3b;
  1311 + border: 0px;
  1312 + }
  1313 +
  1314 + .el-tabs__item.is-active {
  1315 + background-color: #31455d;
  1316 + }
  1317 + }
  1318 + }
  1319 +
  1320 + .el-tabs__content {
  1321 + background-color: #242a30;
  1322 + height: calc(100vh - 39px);
  1323 + overflow-x: hidden;
  1324 + overflow-y: auto;
  1325 +
  1326 + .el-tab-pane {
  1327 + color: #bfcbd9;
  1328 + }
  1329 +
  1330 + &::-webkit-scrollbar {
  1331 + width: 5px;
  1332 + height: 14px;
  1333 + }
  1334 +
  1335 + &::-webkit-scrollbar-track,
  1336 + &::-webkit-scrollbar-thumb {
  1337 + border-radius: 1px;
  1338 + border: 0 solid transparent;
  1339 + }
  1340 +
  1341 + &::-webkit-scrollbar-track-piece {
  1342 + /*修改滚动条的背景和圆角*/
  1343 + background: #29405c;
  1344 + -webkit-border-radius: 7px;
  1345 + }
  1346 +
  1347 + &::-webkit-scrollbar-track {
  1348 + box-shadow: 1px 1px 5px rgba(116, 148, 170, 0.5) inset;
  1349 + }
  1350 +
  1351 + &::-webkit-scrollbar-thumb {
  1352 + min-height: 20px;
  1353 + background-clip: content-box;
  1354 + box-shadow: 0 0 0 5px rgba(116, 148, 170, 0.5) inset;
  1355 + }
  1356 +
  1357 + &::-webkit-scrollbar-corner {
  1358 + background: transparent;
  1359 + }
  1360 +
  1361 + /*修改垂直滚动条的样式*/
  1362 + &::-webkit-scrollbar-thumb:vertical {
  1363 + background-color: #00113a;
  1364 + -webkit-border-radius: 7px;
  1365 + }
  1366 +
  1367 + /*修改水平滚动条的样式*/
  1368 + &::-webkit-scrollbar-thumb:horizontal {
  1369 + background-color: #00113a;
  1370 + -webkit-border-radius: 7px;
  1371 + }
  1372 + }
  1373 + }
  1374 +}
  1375 +
  1376 +ul,
  1377 +li {
  1378 + list-style: none;
  1379 + margin: 0;
  1380 + padding: 0;
  1381 +}
  1382 +
  1383 +.nav {
  1384 + width: 40px;
  1385 + padding: 0;
  1386 + list-style: none;
  1387 + /* overflow: hidden; */
  1388 +}
  1389 +
  1390 +.nav {
  1391 + zoom: 1;
  1392 +}
  1393 +
  1394 +.nav:before,
  1395 +.nav:after {
  1396 + content: "";
  1397 + display: table;
  1398 +}
  1399 +
  1400 +.nav:after {
  1401 + clear: both;
  1402 +}
  1403 +
  1404 +.nav > li {
  1405 + width: 55px;
  1406 + text-align: left;
  1407 + position: relative;
  1408 +}
  1409 +
  1410 +.nav > li a {
  1411 + float: left;
  1412 + padding: 12px 30px;
  1413 + color: #999;
  1414 + font-bold: 12px;
  1415 + text-decoration: none;
  1416 +}
  1417 +
  1418 +.nav > li:hover {
  1419 + color: #788994;
  1420 +}
  1421 +
  1422 +.nav > li ul {
  1423 + visibility: hidden;
  1424 + position: absolute;
  1425 + z-index: 1000;
  1426 + list-style: none;
  1427 + left: 0;
  1428 + padding: 0;
  1429 + background-color: rgb(36, 42, 48);
  1430 + opacity: 0;
  1431 + _margin: 0;
  1432 + width: 120px;
  1433 + transition: all 0.2s ease-in-out;
  1434 +}
  1435 +
  1436 +.nav > li:hover > ul {
  1437 + opacity: 1;
  1438 + visibility: visible;
  1439 + margin: 0;
  1440 +
  1441 + li:hover {
  1442 + background-color: rgb(25, 29, 34);
  1443 + }
  1444 +}
  1445 +
  1446 +.nav ul li {
  1447 + float: left;
  1448 + display: block;
  1449 + border: 0;
  1450 + width: 100%;
  1451 + font-size: 12px;
  1452 +}
  1453 +
  1454 +.nav ul a {
  1455 + padding: 10px;
  1456 + width: 100%;
  1457 + display: block;
  1458 + float: none;
  1459 + height: 120px;
  1460 + border: 1px solid #30445c;
  1461 + background-color: rgb(25, 29, 34);
  1462 + transition: all 0.2s ease-in-out;
  1463 +}
  1464 +
  1465 +.nav ul a:hover {
  1466 + border: 1px solid #3c5e88;
  1467 +}
  1468 +
  1469 +.nav ul li:first-child > a:hover:before {
  1470 + border-bottom-color: #04acec;
  1471 +}
  1472 +
  1473 +.nav ul ul {
  1474 + top: 0;
  1475 + left: 120px;
  1476 + width: 400px;
  1477 + height: 300px;
  1478 + overflow: auto;
  1479 + padding: 10px;
  1480 + _margin: 0;
  1481 +}
  1482 +
  1483 +.nav ul ul li {
  1484 + width: 120px;
  1485 + height: 120px;
  1486 + margin-right: 3px;
  1487 + display: block;
  1488 + float: left;
  1489 +}
  1490 +
  1491 +.nav .item {
  1492 + padding: 5px;
  1493 +}
  1494 +
  1495 +/deep/ .vue-ruler-h {
  1496 + opacity: 0.3;
  1497 +}
  1498 +
  1499 +/deep/ .vue-ruler-v {
  1500 + opacity: 0.3;
  1501 +}
  1502 +.layout-left {
  1503 + width: 200px;
  1504 + background: #242a30;
  1505 + overflow-x: hidden;
  1506 + overflow-y: auto;
  1507 + .chart-type {
  1508 + display: flex;
  1509 + flex-direction: row;
  1510 + overflow: hidden;
  1511 + .type-left {
  1512 + width: 100%;
  1513 + height: calc(100vh - 80px);
  1514 + text-align: center;
  1515 + /deep/.el-tabs__header {
  1516 + width: 30%;
  1517 + margin-right: 0;
  1518 + .el-tabs__nav-wrap {
  1519 + &::after {
  1520 + background: transparent;
  1521 + }
  1522 + .el-tabs__item {
  1523 + text-align: center;
  1524 + width: 100% !important;
  1525 + color: #fff;
  1526 + padding: 0;
  1527 + font-size: 12px !important;
  1528 + }
  1529 + }
  1530 + }
  1531 + /deep/.el-tabs__content {
  1532 + width: 70%;
  1533 + }
  1534 + }
  1535 + }
  1536 + //工具栏一个元素
  1537 + .tools-item {
  1538 + display: flex;
  1539 + position: relative;
  1540 + width: 100%;
  1541 + height: 48px;
  1542 + align-items: center;
  1543 + -webkit-box-align: center;
  1544 + padding: 0 6px;
  1545 + cursor: pointer;
  1546 + font-size: 12px;
  1547 + margin-bottom: 1px;
  1548 +
  1549 + .tools-item-icon {
  1550 + color: #409eff;
  1551 + margin-right: 10px;
  1552 + width: 53px;
  1553 + height: 30px;
  1554 + line-height: 30px;
  1555 + text-align: center;
  1556 + display: block;
  1557 + border: 1px solid #3a4659;
  1558 + background: #282a30;
  1559 + }
  1560 + .tools-item-text {
  1561 + font-size: 12px !important;
  1562 + }
  1563 + }
  1564 + /deep/.el-tabs__content {
  1565 + padding: 0;
  1566 + }
  1567 +}
  1568 +///* 设置滚动条的样式 */
  1569 +//::-webkit-scrollbar {
  1570 +// width: 0;
  1571 +//}
  1572 +//
  1573 +///* 滚动槽 */
  1574 +//::-webkit-scrollbar-track {
  1575 +// -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.3);
  1576 +//}
  1577 +//
  1578 +///* 滚动条滑块 */
  1579 +//::-webkit-scrollbar-thumb {
  1580 +// background: rgba(0, 0, 0, 0.1);
  1581 +// -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
  1582 +//}
  1583 +//
  1584 +//::-webkit-scrollbar-thumb:window-inactive {
  1585 +// background: rgba(255, 0, 0, 0.4);
  1586 +//}
  1587 +/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
  1588 +::-webkit-scrollbar{
  1589 + width: 0;
  1590 + background-color: #242a30;
  1591 +}
  1592 +
  1593 +/*定义滚动条轨道 内阴影+圆角*/
  1594 +::-webkit-scrollbar-track {
  1595 + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  1596 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  1597 + border-radius: 10px;
  1598 + background-color: #F5F5F5;
  1599 +}
  1600 +
  1601 +/*定义滑块 内阴影+圆角*/
  1602 +::-webkit-scrollbar-thumb{
  1603 + border-radius: 10px;
  1604 + box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  1605 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  1606 + background-color: #c8c8c8;
  1607 +}
  1608 +</style>
... ...