#
Junjie
30 分钟以前 d4e6820f6cc65ab6d7315abeff8360dbf5fd4a91
src/main/webapp/static/js/dashboard/dashboard.js
@@ -11,8 +11,10 @@
    el: "#app",
    data: function () {
      return {
        rawPayload: null,
        loading: true,
        refreshing: false,
        switchingSystem: false,
        countdown: REFRESH_SECONDS,
        countdownTimer: null,
        resizeHandler: null,
@@ -95,6 +97,12 @@
    },
    mounted: function () {
      var self = this;
      this.refreshDocumentTitle();
      if (window.WCS_I18N && typeof window.WCS_I18N.onReady === "function") {
        window.WCS_I18N.onReady(function () {
          self.refreshLocalizedState();
        });
      }
      this.$nextTick(function () {
        self.initCharts();
        self.loadDashboard(false);
@@ -108,6 +116,48 @@
      this.disposeCharts();
    },
    methods: {
      formatMessage: function (text, params) {
        var list = Array.isArray(params) ? params : [params];
        return String(text == null ? "" : text).replace(/\{(\d+)\}/g, function (match, index) {
          return list[index] == null ? "" : list[index];
        });
      },
      i18n: function (key, fallback, params) {
        if (window.WCS_I18N && typeof window.WCS_I18N.t === "function") {
          var translated = window.WCS_I18N.t(key, params);
          if (translated && translated !== key) {
            return translated;
          }
        }
        return this.formatMessage(fallback || key, params);
      },
      translateLegacyText: function (text) {
        if (text == null || text === "") {
          return text;
        }
        if (window.WCS_I18N && typeof window.WCS_I18N.tl === "function") {
          return window.WCS_I18N.tl(String(text));
        }
        return text;
      },
      getCurrentLocale: function () {
        if (window.WCS_I18N && typeof window.WCS_I18N.getLocale === "function") {
          return window.WCS_I18N.getLocale();
        }
        return "zh-CN";
      },
      refreshDocumentTitle: function () {
        document.title = this.i18n("dashboard.title", "系统仪表盘");
      },
      refreshLocalizedState: function () {
        this.refreshDocumentTitle();
        if (this.rawPayload) {
          this.applyData(this.rawPayload);
          return;
        }
        this.$forceUpdate();
        this.updateCharts();
      },
      loadDashboard: function (manual) {
        var self = this;
        if (this.refreshing) {
@@ -124,11 +174,11 @@
              self.countdown = REFRESH_SECONDS;
              return;
            }
            self.$message.error((res && res.msg) || "仪表盘数据加载失败");
            self.$message.error((res && res.msg) || self.i18n("dashboard.loadFailed", "仪表盘数据加载失败"));
          },
          error: function () {
            if (manual) {
              self.$message.error("仪表盘数据加载失败,请检查接口状态");
              self.$message.error(self.i18n("dashboard.loadFailedDetail", "仪表盘数据加载失败,请检查接口状态"));
            }
          },
          complete: function () {
@@ -138,12 +188,165 @@
        });
      },
      applyData: function (payload) {
        this.overview = payload.overview || this.overview;
        this.tasks = payload.tasks || this.tasks;
        this.devices = payload.devices || this.devices;
        this.network = payload.network || this.network;
        this.ai = payload.ai || this.ai;
        var tasks = payload && payload.tasks ? payload.tasks : {};
        var devices = payload && payload.devices ? payload.devices : {};
        var network = payload && payload.network ? payload.network : {};
        var ai = payload && payload.ai ? payload.ai : {};
        this.rawPayload = payload || {};
        this.refreshDocumentTitle();
        this.overview = payload && payload.overview ? payload.overview : this.overview;
        this.tasks = {
          overview: tasks.overview || this.tasks.overview,
          directionStats: this.normalizeTaskDirectionMetrics(tasks.directionStats),
          stageStats: this.normalizeTaskStageMetrics(tasks.stageStats),
          statusStats: this.normalizeMetricList(tasks.statusStats),
          recentTasks: this.normalizeRecentTasks(tasks.recentTasks)
        };
        this.devices = {
          overview: devices.overview || this.devices.overview,
          typeStats: this.normalizeDeviceTypeStats(devices.typeStats)
        };
        this.network = {
          overview: network.overview || this.network.overview,
          samplingConfig: network.samplingConfig || this.network.samplingConfig,
          statusStats: this.normalizeNetworkStatusMetrics(network.statusStats),
          focusDevices: this.normalizeFocusDevices(network.focusDevices)
        };
        this.ai = {
          overview: ai.overview || this.ai.overview,
          routeStats: this.normalizeAiRouteStats(ai.routeStats),
          routeList: this.normalizeAiRouteList(ai.routeList)
        };
        this.updateCharts();
      },
      normalizeTaskDirectionMetrics: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (item && item.name === "入库任务") {
            result.name = self.i18n("dashboard.taskDirectionInbound", "入库任务");
          } else if (item && item.name === "出库任务") {
            result.name = self.i18n("dashboard.taskDirectionOutbound", "出库任务");
          } else if (item && item.name === "移库任务") {
            result.name = self.i18n("dashboard.taskDirectionMove", "移库任务");
          } else {
            result.name = self.translateLegacyText(item && item.name);
          }
          return result;
        });
      },
      normalizeTaskStageMetrics: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (item && item.name === "执行中") {
            result.name = self.i18n("dashboard.taskRunningLabel", "执行中");
          } else if (item && item.name === "待人工") {
            result.name = self.i18n("dashboard.taskManualLabel", "待人工");
          } else if (item && item.name === "已完成") {
            result.name = self.i18n("dashboard.taskCompletedLabel", "已完成");
          } else if (item && item.name === "新建") {
            result.name = self.i18n("dashboard.taskNewLabel", "新建");
          } else {
            result.name = self.translateLegacyText(item && item.name);
          }
          return result;
        });
      },
      normalizeMetricList: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          result.name = self.translateLegacyText(item && item.name);
          return result;
        });
      },
      normalizeRecentTasks: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          result.taskType = self.translateLegacyText(item && item.taskType);
          result.status = self.translateLegacyText(item && item.status);
          result.source = self.translateLegacyText(item && item.source);
          result.target = self.translateLegacyText(item && item.target);
          result.device = self.translateLegacyText(item && item.device);
          return result;
        });
      },
      normalizeAiRouteStats: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (item && item.name === "可用") {
            result.name = self.i18n("dashboard.aiRouteStatusAvailable", "可用");
          } else if (item && item.name === "冷却中") {
            result.name = self.i18n("dashboard.aiRouteStatusCooling", "冷却中");
          } else if (item && item.name === "已禁用") {
            result.name = self.i18n("dashboard.aiRouteStatusDisabled", "已禁用");
          } else {
            result.name = self.translateLegacyText(item && item.name);
          }
          return result;
        });
      },
      normalizeNetworkStatusMetrics: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (item && item.name === "正常") {
            result.name = self.i18n("dashboard.networkOkLabel", "正常");
          } else if (item && item.name === "波动") {
            result.name = self.i18n("dashboard.networkUnstableLabel", "波动");
          } else if (item && item.name === "超时/异常") {
            result.name = self.i18n("dashboard.networkOfflineLabel", "超时/异常");
          } else if (item && item.name === "暂无数据") {
            result.name = self.i18n("dashboard.networkNoDataLabel", "暂无数据");
          } else {
            result.name = self.translateLegacyText(item && item.name);
          }
          return result;
        });
      },
      normalizeDeviceTypeStats: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          result.name = self.translateLegacyText(item && item.name);
          return result;
        });
      },
      normalizeAiRouteList: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (result.statusType === "success") {
            result.statusText = self.i18n("dashboard.aiRouteStatusAvailable", "可用");
          } else if (result.statusType === "warning") {
            result.statusText = self.i18n("dashboard.aiRouteStatusCooling", "冷却中");
          } else {
            result.statusText = self.i18n("dashboard.aiRouteStatusDisabled", "已禁用");
          }
          result.lastError = self.translateLegacyText(item && item.lastError);
          return result;
        });
      },
      normalizeFocusDevices: function (list) {
        var self = this;
        return cloneMetricList(list).map(function (item) {
          var result = Object.assign({}, item);
          if (result.statusType === "success") {
            result.statusText = self.i18n("dashboard.networkOkLabel", "正常");
          } else if (result.statusType === "warning") {
            result.statusText = self.i18n("dashboard.networkUnstableLabel", "波动");
          } else if (result.statusType === "danger") {
            result.statusText = self.i18n("dashboard.networkOfflineLabel", "超时/异常");
          } else {
            result.statusText = self.i18n("dashboard.networkNoDataLabel", "暂无数据");
          }
          result.message = self.translateLegacyText(item && item.message);
          return result;
        });
      },
      initCharts: function () {
        this.disposeCharts();
@@ -247,6 +450,8 @@
      },
      buildDeviceTypeOption: function () {
        var data = cloneMetricList(this.devices.typeStats);
        var onlineText = this.i18n("dashboard.deviceOnlineLegend", "在线");
        var offlineText = this.i18n("dashboard.deviceOfflineLegend", "离线");
        return {
          color: ["#2fa38e", "#d8e2ec"],
          legend: {
@@ -255,7 +460,7 @@
            itemWidth: 10,
            itemHeight: 10,
            textStyle: { color: "#60778d", fontSize: 12 },
            data: ["在线", "离线"]
            data: [onlineText, offlineText]
          },
          grid: {
            left: 76,
@@ -282,7 +487,7 @@
            axisLabel: { color: "#60778d", fontSize: 12 }
          },
          series: [{
            name: "在线",
            name: onlineText,
            type: "bar",
            stack: "device",
            barWidth: 18,
@@ -291,7 +496,7 @@
              borderRadius: [9, 0, 0, 9]
            }
          }, {
            name: "离线",
            name: offlineText,
            type: "bar",
            stack: "device",
            barWidth: 18,
@@ -325,7 +530,7 @@
            left: "center",
            top: "55%",
            style: {
              text: "可用路由",
              text: this.i18n("dashboard.chartCenter.availableRoutes", "可用路由"),
              fill: "#7c8fa4",
              fontSize: 12
            }
@@ -370,7 +575,7 @@
            left: "center",
            top: "54%",
            style: {
              text: "需关注设备",
              text: this.i18n("dashboard.chartCenter.attentionDevices", "需关注设备"),
              fill: "#7c8fa4",
              fontSize: 12
            }
@@ -397,7 +602,7 @@
        if (!isFinite(num)) {
          return "0";
        }
        return num.toLocaleString("zh-CN");
        return num.toLocaleString(this.getCurrentLocale());
      },
      formatLatency: function (value) {
        var num;
@@ -408,22 +613,43 @@
        if (!isFinite(num)) {
          return "--";
        }
        return num.toLocaleString("zh-CN", { maximumFractionDigits: 2 }) + " ms";
        return num.toLocaleString(this.getCurrentLocale(), { maximumFractionDigits: 2 }) + " ms";
      },
      formatPercentValue: function (value) {
        var num = Number(value);
        if (!isFinite(num)) {
          return "--";
        }
        return num.toLocaleString(this.getCurrentLocale(), { maximumFractionDigits: 2 }) + "%";
      },
      formatPacketSize: function (value) {
        var num = Number(value);
        if (!isFinite(num) || num < 0) {
          return "系统默认";
          return this.i18n("dashboard.systemDefaultPacketSize", "系统默认");
        }
        return num + " B";
        return num.toLocaleString(this.getCurrentLocale()) + " B";
      },
      displayText: function (value, fallback) {
        return value == null || value === "" ? (fallback || "") : value;
      },
      showMessage: function (message, type) {
        if (this.$message && typeof this.$message === "function") {
          this.$message({
            message: message,
            type: type || "info"
          });
          return;
        }
        console[type === "error" ? "error" : "log"](message);
      },
      networkSamplingText: function () {
        var config = this.network && this.network.samplingConfig ? this.network.samplingConfig : {};
        return "采样 " + this.displayText(config.intervalMs, 0) + " ms / 超时 " + this.displayText(config.timeoutMs, 0) +
          " ms / 每样本 " + this.displayText(config.probeCount, 0) + " 次 / 包大小 " + this.formatPacketSize(config.packetSize);
        return this.i18n("dashboard.networkSampling", "采样 {0} ms / 超时 {1} ms / 每样本 {2} 次 / 包大小 {3}", [
          this.displayText(config.intervalMs, 0),
          this.displayText(config.timeoutMs, 0),
          this.displayText(config.probeCount, 0),
          this.formatPacketSize(config.packetSize)
        ]);
      },
      startAutoRefresh: function () {
        var self = this;
@@ -549,10 +775,142 @@
        window.open(targetMenu && targetMenu.url ? targetMenu.url : this.resolveAbsoluteViewPath(targetPath), "_blank");
      },
      openMonitor: function () {
        this.openParentMenuView("/views/watch/console.html", "监控画面", "监控画面", "监控系统");
        this.openParentMenuView(
          "/views/watch/console.html",
          this.i18n("dashboard.monitorView", "监控画面"),
          this.translateLegacyText("监控画面"),
          this.translateLegacyText("监控系统")
        );
      },
      syncParentSystemRunning: function (status) {
        try {
          if (window.parent && window.parent !== window) {
            window.parent.systemRunning = !!status;
          }
        } catch (e) {
        }
      },
      requestSystemSwitch: function (operatorType, password) {
        var self = this;
        this.switchingSystem = true;
        $.ajax({
          url: baseUrl + "/console/system/switch",
          headers: {
            token: localStorage.getItem("token")
          },
          data: {
            operatorType: operatorType,
            password: password || ""
          },
          method: "POST",
          success: function (res) {
            var status;
            if (res && res.code === 200) {
              status = !!(res.data && res.data.status);
              self.overview = Object.assign({}, self.overview, {
                systemRunning: status
              });
              self.syncParentSystemRunning(status);
              self.showMessage(
                status
                  ? self.i18n("dashboard.systemStarted", "系统已启动")
                  : self.i18n("dashboard.systemStopped", "系统已停止"),
                "success"
              );
              self.loadDashboard(false);
              return;
            }
            if (res && res.code === 403) {
              window.location.href = baseUrl + "/login";
              return;
            }
            self.showMessage(
              (res && res.msg) || self.i18n("dashboard.systemSwitchFailed", "系统状态切换失败"),
              "error"
            );
          },
          error: function () {
            self.showMessage(
              self.i18n("dashboard.systemSwitchFailedDetail", "系统状态切换失败,请检查接口状态"),
              "error"
            );
          },
          complete: function () {
            self.switchingSystem = false;
          }
        });
      },
      startSystem: function () {
        if (this.overview.systemRunning || this.switchingSystem) {
          return;
        }
        this.requestSystemSwitch(1);
      },
      maskStopSystemPromptInput: function () {
        setTimeout(function () {
          var input = document.querySelector(".el-message-box__wrapper .el-message-box__input input");
          if (!input) {
            return;
          }
          input.setAttribute("type", "text");
          input.setAttribute("name", "dashboard-stop-code");
          input.setAttribute("autocomplete", "new-password");
          input.setAttribute("autocapitalize", "off");
          input.setAttribute("autocorrect", "off");
          input.setAttribute("spellcheck", "false");
          input.setAttribute("data-form-type", "other");
          input.style.webkitTextSecurity = "disc";
        }, 30);
      },
      stopSystem: function () {
        var self = this;
        var proceed = function (password) {
          var cleanPassword = String(password == null ? "" : password).trim();
          if (!cleanPassword) {
            self.showMessage(self.i18n("dashboard.stopSystemPasswordRequired", "请输入停止系统口令"), "warning");
            return;
          }
          self.requestSystemSwitch(0, cleanPassword);
        };
        if (!this.overview.systemRunning || this.switchingSystem) {
          return;
        }
        if (typeof this.$prompt === "function") {
          this.$prompt(
            this.i18n("dashboard.stopSystemPrompt", "请输入口令,并停止 WCS 系统"),
            this.i18n("dashboard.stopSystemTitle", "停止系统"),
            {
              confirmButtonText: this.i18n("common.confirm", "确定"),
              cancelButtonText: this.i18n("common.cancel", "取消"),
              inputType: "text",
              inputPattern: /\S+/,
              inputErrorMessage: this.i18n("dashboard.stopSystemPasswordRequired", "请输入停止系统口令")
            }
          ).then(function (result) {
            proceed(result && result.value);
          }).catch(function () {
          });
          this.maskStopSystemPromptInput();
          return;
        }
        proceed(window.prompt(this.i18n("dashboard.stopSystemPrompt", "请输入口令,并停止 WCS 系统"), ""));
      },
      toggleSystem: function () {
        if (this.overview.systemRunning) {
          this.stopSystem();
          return;
        }
        this.startSystem();
      },
      openDevicePingAnalysis: function () {
        this.openParentMenuView("/views/devicePingLog/devicePingLog.html", "设备网络分析", "设备网络分析");
        this.openParentMenuView(
          "/views/devicePingLog/devicePingLog.html",
          this.i18n("devicePingLog.title", "设备网络分析"),
          this.translateLegacyText("设备网络分析")
        );
      }
    }
  });