From 60fa266af6d5085702bb9a48db2ea67c7c41845c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=85=AC=E6=98=8E?=
<83812544+Ed1s0nZ@users.noreply.github.com>
Date: Tue, 31 Mar 2026 22:10:39 +0800
Subject: [PATCH] Add files via upload
---
web/static/js/chat.js | 26 ++++++++++++++++++++++++--
web/static/js/monitor.js | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/web/static/js/chat.js b/web/static/js/chat.js
index bf296ece..9e6e8505 100644
--- a/web/static/js/chat.js
+++ b/web/static/js/chat.js
@@ -1695,6 +1695,20 @@ function renderProcessDetails(messageId, processDetails) {
detailsContainer.appendChild(contentDiv);
}
+ // processDetails === null 表示“尚未加载(懒加载)”
+ const isLazyNotLoaded = (processDetails === null);
+ if (isLazyNotLoaded) {
+ detailsContainer.dataset.lazyNotLoaded = '1';
+ detailsContainer.dataset.loaded = '0';
+ timeline.innerHTML = '
' +
+ (typeof window.t === 'function' ? window.t('chat.expandDetail') : '展开详情') +
+ '(点击后加载)
';
+ // 默认折叠
+ timeline.classList.remove('expanded');
+ return;
+ }
+ detailsContainer.dataset.lazyNotLoaded = '0';
+ detailsContainer.dataset.loaded = '1';
// 如果没有processDetails或为空,显示空状态
if (!processDetails || processDetails.length === 0) {
// 显示空状态提示
@@ -2327,7 +2341,8 @@ function getConversationGroup(dateObj, todayStart, startOfWeek, yesterdayStart)
// 加载对话
async function loadConversation(conversationId) {
try {
- const response = await apiFetch(`/api/conversations/${conversationId}`);
+ // 轻量加载:不带 processDetails,避免历史会话切换卡顿;展开详情时再按需拉取
+ const response = await apiFetch(`/api/conversations/${conversationId}?include_process_details=0`);
const conversation = await response.json();
if (!response.ok) {
@@ -2426,11 +2441,18 @@ async function loadConversation(conversationId) {
// 传递消息的创建时间
const messageId = addMessage(msg.role, displayContent, msg.mcpExecutionIds || [], null, msg.createdAt);
+ // 绑定后端 messageId,供按需加载过程详情使用
+ const messageEl = document.getElementById(messageId);
+ if (messageEl && msg && msg.id) {
+ messageEl.dataset.backendMessageId = String(msg.id);
+ }
// 对于助手消息,总是渲染过程详情(即使没有processDetails也要显示展开详情按钮)
if (msg.role === 'assistant') {
// 延迟一下,确保消息已经渲染
setTimeout(() => {
- renderProcessDetails(messageId, msg.processDetails || []);
+ // 如果后端未返回 processDetails 字段,传 null 表示“尚未加载,点击展开时再请求”
+ const hasField = msg && Object.prototype.hasOwnProperty.call(msg, 'processDetails');
+ renderProcessDetails(messageId, hasField ? (msg.processDetails || []) : null);
// 如果有过程详情,检查是否有错误或取消事件,如果有,确保详情默认折叠
if (msg.processDetails && msg.processDetails.length > 0) {
const hasErrorOrCancelled = msg.processDetails.some(d =>
diff --git a/web/static/js/monitor.js b/web/static/js/monitor.js
index ce8020d1..d496114a 100644
--- a/web/static/js/monitor.js
+++ b/web/static/js/monitor.js
@@ -506,6 +506,46 @@ function toggleProcessDetails(progressId, assistantMessageId) {
const detailsId = 'process-details-' + assistantMessageId;
const detailsContainer = document.getElementById(detailsId);
if (!detailsContainer) return;
+
+ // 懒加载:首次展开时才从后端拉取该条消息的过程详情
+ const maybeLazy = detailsContainer.dataset && detailsContainer.dataset.lazyNotLoaded === '1' && detailsContainer.dataset.loaded !== '1';
+ if (maybeLazy) {
+ const messageEl = document.getElementById(assistantMessageId);
+ const backendMessageId = messageEl && messageEl.dataset ? messageEl.dataset.backendMessageId : '';
+ if (backendMessageId && typeof apiFetch === 'function' && typeof renderProcessDetails === 'function') {
+ if (detailsContainer.dataset.loading === '1') {
+ // 正在加载中,避免重复请求
+ } else {
+ detailsContainer.dataset.loading = '1';
+ // 先展开容器,显示加载态
+ const timeline = detailsContainer.querySelector('.progress-timeline');
+ if (timeline) {
+ timeline.innerHTML = '' + ((typeof window.t === 'function') ? window.t('common.loading') : '加载中…') + '
';
+ }
+ apiFetch(`/api/messages/${encodeURIComponent(String(backendMessageId))}/process-details`)
+ .then(async (res) => {
+ const j = await res.json().catch(() => ({}));
+ if (!res.ok) throw new Error((j && j.error) ? j.error : res.status);
+ const details = (j && Array.isArray(j.processDetails)) ? j.processDetails : [];
+ // 重新渲染详情(renderProcessDetails 会清掉 lazy 标记并写入 loaded)
+ renderProcessDetails(assistantMessageId, details);
+ })
+ .catch((e) => {
+ console.error('加载过程详情失败:', e);
+ const tl = detailsContainer.querySelector('.progress-timeline');
+ if (tl) {
+ tl.innerHTML = '' + ((typeof window.t === 'function') ? window.t('chat.noProcessDetail') : '暂无过程详情(加载失败)') + '
';
+ }
+ // 失败时保留 lazy 状态,允许用户重试
+ detailsContainer.dataset.lazyNotLoaded = '1';
+ detailsContainer.dataset.loaded = '0';
+ })
+ .finally(() => {
+ detailsContainer.dataset.loading = '0';
+ });
+ }
+ }
+ }
const content = detailsContainer.querySelector('.process-details-content');
const timeline = detailsContainer.querySelector('.progress-timeline');