#
Junjie
3 天以前 d8d82ceda75fa17972d6996f83078367a19c1730
src/main/webapp/views/ai/diagnosis.html
@@ -616,7 +616,7 @@
        <footer class="composer-panel">
          <div class="composer-head">
            <div><strong>向 AI 助手提问</strong></div>
            <div>{{ currentChatId ? '会话已绑定' : '临时会话' }}</div>
            <div>{{ currentRunTokenSummary || currentChatTokenSummary || (currentChatId ? '会话已绑定' : '临时会话') }}</div>
          </div>
          <el-input
            v-model="userInput"
@@ -679,6 +679,7 @@
          lastRenderTs: 0,
          renderIntervalMs: 120,
          stepChars: 6,
          runTokenUsage: null,
          userInput: '',
          autoScrollThreshold: 80,
          chats: [],
@@ -731,7 +732,15 @@
          var current = this.findChat(this.currentChatId);
          if (!current && this.resetting) return '新建会话,等待首条消息';
          if (!current) return '会话 ' + this.currentChatId;
          return this.chatLabel(current);
          var tokenText = this.tokenSummaryText(current);
          return tokenText ? (this.chatLabel(current) + ' · ' + tokenText) : this.chatLabel(current);
        },
        currentChatTokenSummary: function() {
          var current = this.findChat(this.currentChatId);
          return current ? this.tokenSummaryText(current) : '';
        },
        currentRunTokenSummary: function() {
          return this.runTokenUsage ? this.tokenSummaryText(this.runTokenUsage, '本次') : '';
        },
        inlinePrompts: function() {
          return this.promptPresets.slice(1);
@@ -801,7 +810,22 @@
        },
        chatOptionLabel: function(chat) {
          if (!chat) return '未命名会话';
          return this.chatLabel(chat) + ' · ' + (chat.size || 0) + ' 条 · ' + this.chatUpdatedAt(chat);
          var suffix = this.tokenSummaryText(chat);
          return this.chatLabel(chat) + ' · ' + (chat.size || 0) + ' 条 · ' + this.chatUpdatedAt(chat) + (suffix ? (' · ' + suffix) : '');
        },
        numericValue: function(value) {
          if (value === null || value === undefined || value === '') return 0;
          var num = Number(value);
          return isNaN(num) ? 0 : num;
        },
        tokenSummaryText: function(source, prefix) {
          if (!source) return '';
          var total = this.numericValue(source.totalTokens != null ? source.totalTokens : source.lastTotalTokens);
          if (!total) return '';
          var prompt = this.numericValue(source.promptTokens != null ? source.promptTokens : source.lastPromptTokens);
          var completion = this.numericValue(source.completionTokens != null ? source.completionTokens : source.lastCompletionTokens);
          var label = prefix || '上次';
          return label + ' tokens ' + total + '(输' + prompt + ' / 出' + completion + ')';
        },
        chatUpdatedAt: function(chat) {
          if (!chat || !chat.updatedAt) return '刚刚创建';
@@ -825,6 +849,7 @@
        openChat: function(chatId) {
          if (!chatId || this.streaming) return;
          this.currentChatId = chatId;
          this.runTokenUsage = null;
          this.switchChat();
        },
        switchChat: function() {
@@ -869,6 +894,7 @@
          if (this.streaming) return;
          this.currentChatId = Date.now() + '_' + Math.random().toString(36).substr(2, 8);
          this.resetting = true;
          this.runTokenUsage = null;
          this.clear();
        },
        deleteChat: function() {
@@ -932,6 +958,7 @@
          if (!message) return;
          this.loading = true;
          this.streaming = true;
          this.runTokenUsage = null;
          this.messages.push({ role: 'user', text: message, ts: this.nowStr() });
          this.appendAssistantPlaceholder();
          this.scrollToBottom(true);
@@ -945,6 +972,12 @@
          this.source.onopen = function() {
            self.loading = false;
          };
          this.source.addEventListener('token_usage', function(e) {
            if (!e || !e.data) return;
            try {
              self.runTokenUsage = JSON.parse(e.data);
            } catch (ignore) {}
          });
          this.source.onmessage = function(e) {
            if (!e || !e.data) return;
            var chunk = (e.data || '').replace(/\\n/g, '\n');
@@ -966,6 +999,7 @@
          this.clear();
          this.loading = true;
          this.streaming = true;
          this.runTokenUsage = null;
          this.appendAssistantPlaceholder();
          this.scrollToBottom(true);
@@ -974,6 +1008,12 @@
          this.source.onopen = function() {
            self.loading = false;
          };
          this.source.addEventListener('token_usage', function(e) {
            if (!e || !e.data) return;
            try {
              self.runTokenUsage = JSON.parse(e.data);
            } catch (ignore) {}
          });
          this.source.onmessage = function(e) {
            if (!e || !e.data) return;
            var chunk = (e.data || '').replace(/\\n/g, '\n');