From 061f66dcfc6ae5aa0a4106b2323b40fc785fb22d Mon Sep 17 00:00:00 2001 From: Nixevol Date: Mon, 18 May 2026 16:38:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E5=8D=A0=E7=94=A8=E8=AE=A1=E7=AE=97=E5=92=8C?= =?UTF-8?q?=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/project_context.md | 7 +++ frontend/src/components/HistoryPanel.vue | 61 ++++++++++++++++++------ frontend/src/styles.css | 50 +++++++++++++++++++ 3 files changed, 104 insertions(+), 14 deletions(-) diff --git a/docs/project_context.md b/docs/project_context.md index efca973..dfa5202 100644 --- a/docs/project_context.md +++ b/docs/project_context.md @@ -1,5 +1,12 @@ # 项目上下文记录 +## 2026-05-18:优化历史详情弹窗信息布局 + +- `frontend/src/components/HistoryPanel.vue` 打开历史详情后会自动调用 `/api/history/size` 计算占用,不再需要用户点击“计算占用”按钮。 +- 历史详情基础信息从 Naive UI `n-descriptions` 表格改为自定义键值列表,统一为左侧标题、右侧值,长路径和值会自动换行。 +- 占用计算期间显示“计算中...”,失败时显示“计算失败”并保留错误 toast。 +- 已执行 `npm run build`,构建通过;未启动浏览器或 headless Chrome。 + ## 2026-05-18:数据管理页切换时刷新表列表 - `frontend/src/components/DatabasePanel.vue` 在数据管理页激活时会重新执行 `loadTables()`,确保从其他页面切回时左侧表列表拉取最新状态。 diff --git a/frontend/src/components/HistoryPanel.vue b/frontend/src/components/HistoryPanel.vue index 484ca10..2ca06b0 100644 --- a/frontend/src/components/HistoryPanel.vue +++ b/frontend/src/components/HistoryPanel.vue @@ -27,19 +27,40 @@ - - {{ detail.id }} - {{ statusText(detail.status) }} - {{ detail.file_count }} - {{ formatElapsed(detail.elapsed_time) }} - {{ formatDate(detail.timestamp) }} - - 计算占用 - {{ recordSize }} - - {{ detail.work_dir }} - {{ detail.error }} - +
+
+ 任务 ID + {{ detail.id }} +
+
+ 状态 + {{ statusText(detail.status) }} +
+
+ 文件数 + {{ detail.file_count }} +
+
+ 耗时 + {{ formatElapsed(detail.elapsed_time) }} +
+
+ 创建时间 + {{ formatDate(detail.timestamp) }} +
+
+ 占用 + {{ recordSize }} +
+
+ 工作目录 + {{ detail.work_dir }} +
+
+ 错误 + {{ detail.error }} +
+
@@ -66,7 +87,9 @@ const detail = ref(null); const detailVisible = ref(false); const cacheSize = ref(null); const recordSize = ref('-'); +const recordSizeLoading = ref(false); const loading = ref(false); +let recordSizeToken = 0; const totalSizeText = computed(() => `总占用: ${cacheSize.value?.size_formatted || '计算中...'}`); const hasRecords = computed(() => records.value.length > 0); @@ -113,21 +136,31 @@ async function loadHistory() { async function openDetail(recordId: string) { try { detail.value = await apiPost('/api/history/detail', { record_id: recordId }); - recordSize.value = '-'; detailVisible.value = true; + void loadRecordSize(recordId); } catch (error) { message.error(error instanceof Error ? error.message : '加载任务详情失败'); } } async function loadRecordSize(recordId: string) { + const currentToken = ++recordSizeToken; + recordSize.value = '计算中...'; + recordSizeLoading.value = true; try { const result = await apiPost<{ success: boolean; size_formatted: string }>('/api/history/size', { record_id: recordId }); + if (currentToken !== recordSizeToken) return; recordSize.value = result.size_formatted; } catch (error) { + if (currentToken !== recordSizeToken) return; + recordSize.value = '计算失败'; message.error(error instanceof Error ? error.message : '计算目录占用失败'); + } finally { + if (currentToken === recordSizeToken) { + recordSizeLoading.value = false; + } } } diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 9c241a7..b39935d 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -967,6 +967,56 @@ select { width: min(900px, calc(100vw - 48px)); } +.detail-info-list { + overflow: hidden; + border: 1px solid var(--td-border-color-light); + border-radius: var(--td-radius-default); +} + +.detail-info-row { + display: grid; + grid-template-columns: 132px minmax(0, 1fr); + min-height: 44px; + border-bottom: 1px solid var(--td-border-color-light); +} + +.detail-info-row:last-child { + border-bottom: 0; +} + +.detail-info-label, +.detail-info-value { + display: flex; + align-items: center; + min-width: 0; + padding: 10px 14px; +} + +.detail-info-label { + color: var(--td-text-color-secondary); + font-weight: 500; + background: var(--td-bg-color-secondarycontainer); + border-right: 1px solid var(--td-border-color-light); +} + +.detail-info-value { + color: var(--td-text-color-primary); + word-break: break-word; +} + +.detail-info-value.monospace, +.detail-info-value.path-value { + font-family: var(--td-font-family-mono); +} + +.detail-info-value.muted { + color: var(--td-text-color-placeholder); +} + +.detail-info-row.error-row .detail-info-value { + color: var(--td-error-color); +} + .log-panel, .script-log { min-height: 320px;