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:
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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user