fix(dashboard): 大屏绘制独立页顶栏深色适配 + 修复卡 loading/重绘无数据

- 顶栏(dashboard-agent-topbar)深色下改深蓝(《深蓝色 UI 规范》卡片#122347/
  页面#0C1836/边框#1A2F5A/文字#C5CFE0),不再白底;仅作用于顶栏。
- init effect 始终并行拉输入 JSON 写入 inputRef,恢复历史后「重新绘制」/续问
  才有源数据,否则回退空 prompt 生成不出数据。
- 修复卡在「正在加载任务大屏…」:init effect 改为只依赖 [taskId]、start/
  hydrateTranscript 经 ref 读取、finally 无条件 setLoading(false),避免模型异步
  加载触发 cleanup 把首跑标记 cancelled 后 loading 永不置 false。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
董宏凯andClaude Opus 4.8 committed 2026-06-18 18:01:30 +08:00
1 parent 6a8f118ad0
commit bd5623ebc5
2 files changed
+58 -18

No files matched your search

@@ -122,6 +122,15 @@ export default function DashboardAgentPage() {
}
}, [availableModels, selectedModel]);
// init 只跑一次:start / hydrateTranscript 用 ref 持有,effect 只依赖 [taskId]。
// 否则它们的 identity 会随 selectedModel/themeMode 变化重建(模型挂载后异步加载即触发),
// 让 effect 在 await 期间 cleanup → 二次进入被 didInitRef 挡掉 → 首跑的 finally 因 cancelled
// 跳过 setLoading(false),loading 永远停在 true(白转圈,卡在「正在加载任务大屏…」)。
const startRef = useRef(start);
startRef.current = start;
const hydrateTranscriptRef = useRef(hydrateTranscript);
hydrateTranscriptRef.current = hydrateTranscript;
// ── 挂载:按 taskId 取会话 → 决定直显大屏 / 看生成过程(只跑一次) ──
const didInitRef = useRef(false);
useEffect(() => {
@@ -131,37 +140,38 @@ export default function DashboardAgentPage() {
return;
}
didInitRef.current = true;
let cancelled = false;
void (async () => {
try {
const session = await getDashboardSessionByTask(taskId).catch(() => null);
if (cancelled) return;
// 会话 + 输入 JSON 并行取。输入**始终**备好并写进 inputRef —— 否则恢复历史
// 后用户点「重新绘制」/续问时 buildInitialPrompt 拿不到源数据,会回退到空的
// 圆桌 prompt,智能体没东西可分析 → 生成不出数据(即「模拟数据不生效」)。
const [session, input] = await Promise.all([
getDashboardSessionByTask(taskId).catch(() => null),
fetchDashboardInputJson(taskId).catch(() => null),
]);
inputRef.current = input;
const savedDialogues = (session?.transcript as Step2Dialogue[] | undefined) ?? [];
const validReport = session?.reportJson && parseReportJson(session.reportJson);
if (validReport) {
// 有有效结果 → 恢复并直接展示大屏页面。
hydrateTranscript(savedDialogues, session!.reportJson);
hydrateTranscriptRef.current(savedDialogues, session!.reportJson);
setView("page");
} else if (savedDialogues.length > 0) {
// 有历史聊天但无有效结果 → 进生成过程展示历史,不自动重跑。
hydrateTranscript(savedDialogues, session?.reportJson ?? null);
// 有历史聊天但无有效结果 → 进生成过程展示历史,不自动重跑(点「重新绘制」可重生成)。
hydrateTranscriptRef.current(savedDialogues, session?.reportJson ?? null);
setView("chat");
} else {
// 无任何记录 → 拉输入 JSON 自动开跑,让用户看生成过程(不自动跳)。
const input = await fetchDashboardInputJson(taskId).catch(() => null);
if (cancelled) return;
inputRef.current = input;
// 无任何记录 → 自动开跑,让用户看生成过程(不自动跳)。
setView("chat");
if (input) start();
if (input) startRef.current();
}
} finally {
if (!cancelled) setLoading(false);
setLoading(false);
}
})();
return () => {
cancelled = true;
};
}, [taskId, hydrateTranscript, start]);
// 只依赖 taskId:start/hydrateTranscript 经 ref 读取,避免其 identity 变化重跑本 effect。
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [taskId]);
// ── 防抖回存聊天记录 + 最新 report-json(按 taskId 共享) ──
useEffect(() => {
@@ -245,9 +255,9 @@ export default function DashboardAgentPage() {
}
return (
<div className="flex h-full min-h-0 flex-col text-slate-800">
<div className="flex h-full min-h-0 flex-col text-slate-800 dark:text-slate-200">
{/* 顶栏 */}
<div className="shrink-0 flex flex-wrap items-center justify-between gap-3 border-b border-slate-100 bg-gradient-to-r from-slate-50 to-white px-6 py-3">
<div className="dashboard-agent-topbar shrink-0 flex flex-wrap items-center justify-between gap-3 border-b border-slate-100 bg-gradient-to-r from-slate-50 to-white px-6 py-3">
<div className="flex items-center gap-2.5">
<Sparkles className="h-4.5 w-4.5 text-primary" />
<h3 className="text-sm font-black tracking-tight text-slate-900">大屏绘制智能体</h3>
+30
View File
@@ -626,6 +626,36 @@
background-attachment: fixed, fixed;
}
/* 「大屏绘制智能体」独立页顶栏(DashboardAgentPage,class=dashboard-agent-topbar)深色
* 适配:顶栏只为浅色写死了 slate/white 渐变,深色(.dark)下统一改深蓝(《深蓝色 UI 规范》
* 卡片底 #122347 / 页面底 #0C1836 / 边框 #1A2F5A / 字体 #C5CFE0),仅作用于顶栏内,
* 不影响下方大屏/聊天区。浅色不命中,原样式不变。 */
.dark .dashboard-agent-topbar {
background-image: linear-gradient(to right, #122347, #0c1836) !important;
border-color: #1a2f5a !important;
}
.dark .dashboard-agent-topbar .text-slate-900 {
color: #e8edf5 !important;
}
.dark .dashboard-agent-topbar
:is(.text-slate-700, .hover\:text-slate-700:hover) {
color: #c5cfe0 !important;
}
.dark .dashboard-agent-topbar :is(.text-slate-500, .text-slate-400) {
color: #6e88b0 !important;
}
.dark .dashboard-agent-topbar .bg-white {
background-color: #1a2f5a !important;
}
.dark .dashboard-agent-topbar
:is(.bg-slate-50, .hover\:bg-slate-50:hover) {
background-color: #0c1836 !important;
}
.dark .dashboard-agent-topbar
:is(.border-slate-100, .border-slate-200) {
border-color: #1a2f5a !important;
}
.workspace-panel {
border: 1px solid #f0d7d0;
background: #ffffff;