From cbb00d4729243e4949b3c921fc2f94cb03ca8aaa Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期五, 27 三月 2026 18:47:43 +0800
Subject: [PATCH] #

---
 src/main/webapp/views/ai/llm_config.html |   71 +++++++++++++++++++++++++++++++++--
 1 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/src/main/webapp/views/ai/llm_config.html b/src/main/webapp/views/ai/llm_config.html
index c80314c..edf9f45 100644
--- a/src/main/webapp/views/ai/llm_config.html
+++ b/src/main/webapp/views/ai/llm_config.html
@@ -309,7 +309,11 @@
       <div class="route-card" :class="routeCardClass(route)" v-for="(route, idx) in routes" :key="route.id ? ('route_' + route.id) : ('new_' + idx)">
         <div class="route-head">
           <div class="route-title">
-            <el-input v-model="route.name" size="mini" placeholder="璺敱鍚嶇О"></el-input>
+            <el-input
+              :value="displayRouteName(route)"
+              size="mini"
+              placeholder="璺敱鍚嶇О"
+              @input="handleRouteNameInput(route, $event)"></el-input>
             <div class="route-id-line">#{{ route.id || 'new' }} 路 浼樺厛绾� {{ route.priority || 0 }}</div>
           </div>
           <div class="route-state">
@@ -393,7 +397,7 @@
     </div>
   </div>
 
-  <el-dialog title="LLM璋冪敤鏃ュ織" :visible.sync="logDialogVisible" width="88%" :close-on-click-modal="false">
+  <el-dialog :title="i18n('llm.logsTitle', 'LLM璋冪敤鏃ュ織')" :visible.sync="logDialogVisible" width="88%" :close-on-click-modal="false">
     <div class="log-toolbar">
       <el-select v-model="logQuery.scene" size="mini" clearable placeholder="鍦烘櫙" style="width:180px;">
         <el-option label="chat" value="chat"></el-option>
@@ -431,6 +435,12 @@
       </el-table-column>
       <el-table-column prop="httpStatus" label="鐘舵�佺爜" width="90"></el-table-column>
       <el-table-column prop="latencyMs" label="鑰楁椂(ms)" width="95"></el-table-column>
+      <el-table-column label="Tokens" width="140">
+        <template slot-scope="scope">
+          <div>{{ logTotalTokens(scope.row) }}</div>
+          <div style="color:#909399;font-size:12px;">杈搟{ logPromptTokens(scope.row) }} / 鍑簕{ logCompletionTokens(scope.row) }}</div>
+        </template>
+      </el-table-column>
       <el-table-column prop="traceId" label="TraceId" width="230"></el-table-column>
       <el-table-column label="閿欒" min-width="220">
         <template slot-scope="scope">
@@ -457,7 +467,7 @@
     </div>
   </el-dialog>
 
-  <el-dialog :title="logDetailTitle || '鏃ュ織璇︽儏'" :visible.sync="logDetailVisible" width="82%" :close-on-click-modal="false" append-to-body>
+  <el-dialog :title="logDetailTitle || i18n('llm.logDetailTitle', '鏃ュ織璇︽儏')" :visible.sync="logDetailVisible" width="82%" :close-on-click-modal="false" append-to-body>
     <div class="log-detail-body">{{ logDetailText || '-' }}</div>
     <span slot="footer" class="dialog-footer">
       <el-button size="mini" @click="copyText(logDetailText)">澶嶅埗鍏ㄦ枃</el-button>
@@ -511,6 +521,31 @@
       }
     },
     methods: {
+      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 fallback || key;
+      },
+      translateLegacyText: function(text) {
+        if (window.WCS_I18N && typeof window.WCS_I18N.tl === 'function') {
+          return window.WCS_I18N.tl(text);
+        }
+        return text;
+      },
+      displayRouteName: function(route) {
+        var value = route && route.name ? String(route.name) : '';
+        return this.translateLegacyText(value);
+      },
+      handleRouteNameInput: function(route, value) {
+        if (!route) {
+          return;
+        }
+        route.name = value;
+      },
       formatDateTime: function(input) {
         if (!input) return '-';
         var d = input instanceof Date ? input : new Date(input);
@@ -797,13 +832,35 @@
           + '妯″瀷: ' + (row.model || '-') + '\n'
           + '鐘舵�佺爜: ' + (row.httpStatus != null ? row.httpStatus : '-') + '\n'
           + '鑰楁椂: ' + (row.latencyMs != null ? row.latencyMs : '-') + ' ms\n'
+          + 'Tokens: ' + this.logTotalTokens(row) + '锛堣緭' + this.logPromptTokens(row) + ' / 鍑�' + this.logCompletionTokens(row) + '锛塡n'
           + '缁撴灉: ' + (row.success === 1 ? '鎴愬姛' : '澶辫触') + '\n'
           + '閿欒: ' + (row.errorMessage || '-') + '\n\n'
           + '璇锋眰:\n' + (row.requestContent || '-') + '\n\n'
           + '鍝嶅簲:\n' + (row.responseContent || '-');
-        this.logDetailTitle = '鏃ュ織璇︽儏 - ' + (row.traceId || row.id || '');
+        this.logDetailTitle = this.i18n('llm.logDetailPrefix', '鏃ュ織璇︽儏 - ') + (row.traceId || row.id || '');
         this.logDetailText = text;
         this.logDetailVisible = true;
+      },
+      parseLogExtra: function(row) {
+        if (!row || !row.extra) return {};
+        if (typeof row.extra === 'object') return row.extra;
+        try {
+          return JSON.parse(row.extra);
+        } catch (e) {
+          return {};
+        }
+      },
+      logPromptTokens: function(row) {
+        var extra = this.parseLogExtra(row);
+        return extra && extra.promptTokens != null ? extra.promptTokens : '-';
+      },
+      logCompletionTokens: function(row) {
+        var extra = this.parseLogExtra(row);
+        return extra && extra.completionTokens != null ? extra.completionTokens : '-';
+      },
+      logTotalTokens: function(row) {
+        var extra = this.parseLogExtra(row);
+        return extra && extra.totalTokens != null ? extra.totalTokens : '-';
       },
       deleteLog: function(row) {
         var self = this;
@@ -1006,6 +1063,12 @@
       }
     },
     mounted: function() {
+      var self = this;
+      if (window.WCS_I18N && typeof window.WCS_I18N.onReady === 'function') {
+        window.WCS_I18N.onReady(function() {
+          self.$forceUpdate();
+        });
+      }
       this.loadRoutes();
     }
   });

--
Gitblit v1.9.1