From 7a0470e331a978ee206cd8fcf3dfd5642f14eb83 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 17 三月 2026 09:23:44 +0800
Subject: [PATCH] #

---
 src/main/webapp/static/js/dashboard/dashboard.js |  264 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 244 insertions(+), 20 deletions(-)

diff --git a/src/main/webapp/static/js/dashboard/dashboard.js b/src/main/webapp/static/js/dashboard/dashboard.js
index db6676a..42e63df 100644
--- a/src/main/webapp/static/js/dashboard/dashboard.js
+++ b/src/main/webapp/static/js/dashboard/dashboard.js
@@ -11,6 +11,7 @@
     el: "#app",
     data: function () {
       return {
+        rawPayload: null,
         loading: true,
         refreshing: false,
         countdown: REFRESH_SECONDS,
@@ -95,6 +96,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 +115,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 +173,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("浠〃鐩樻暟鎹姞杞藉け璐ワ紝璇锋鏌ユ帴鍙g姸鎬�");
+              self.$message.error(self.i18n("dashboard.loadFailedDetail", "浠〃鐩樻暟鎹姞杞藉け璐ワ紝璇锋鏌ユ帴鍙g姸鎬�"));
             }
           },
           complete: function () {
@@ -138,12 +187,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 === "姝e父") {
+            result.name = self.i18n("dashboard.networkOkLabel", "姝e父");
+          } 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", "姝e父");
+          } 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 +449,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 +459,7 @@
             itemWidth: 10,
             itemHeight: 10,
             textStyle: { color: "#60778d", fontSize: 12 },
-            data: ["鍦ㄧ嚎", "绂荤嚎"]
+            data: [onlineText, offlineText]
           },
           grid: {
             left: 76,
@@ -282,7 +486,7 @@
             axisLabel: { color: "#60778d", fontSize: 12 }
           },
           series: [{
-            name: "鍦ㄧ嚎",
+            name: onlineText,
             type: "bar",
             stack: "device",
             barWidth: 18,
@@ -291,7 +495,7 @@
               borderRadius: [9, 0, 0, 9]
             }
           }, {
-            name: "绂荤嚎",
+            name: offlineText,
             type: "bar",
             stack: "device",
             barWidth: 18,
@@ -325,7 +529,7 @@
             left: "center",
             top: "55%",
             style: {
-              text: "鍙敤璺敱",
+              text: this.i18n("dashboard.chartCenter.availableRoutes", "鍙敤璺敱"),
               fill: "#7c8fa4",
               fontSize: 12
             }
@@ -370,7 +574,7 @@
             left: "center",
             top: "54%",
             style: {
-              text: "闇�鍏虫敞璁惧",
+              text: this.i18n("dashboard.chartCenter.attentionDevices", "闇�鍏虫敞璁惧"),
               fill: "#7c8fa4",
               fontSize: 12
             }
@@ -397,7 +601,7 @@
         if (!isFinite(num)) {
           return "0";
         }
-        return num.toLocaleString("zh-CN");
+        return num.toLocaleString(this.getCurrentLocale());
       },
       formatLatency: function (value) {
         var num;
@@ -408,22 +612,33 @@
         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;
       },
       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 +764,19 @@
         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("鐩戞帶绯荤粺")
+        );
       },
       openDevicePingAnalysis: function () {
-        this.openParentMenuView("/views/devicePingLog/devicePingLog.html", "璁惧缃戠粶鍒嗘瀽", "璁惧缃戠粶鍒嗘瀽");
+        this.openParentMenuView(
+          "/views/devicePingLog/devicePingLog.html",
+          this.i18n("devicePingLog.title", "璁惧缃戠粶鍒嗘瀽"),
+          this.translateLegacyText("璁惧缃戠粶鍒嗘瀽")
+        );
       }
     }
   });

--
Gitblit v1.9.1