feat(圆桌): 大屏多页席位多样式+新窗口React页+布局优化+切历史记录刷新

- 新窗口打开改为渲染应用内 React 大屏(独立全屏路由 /roundtable-dashboard,
  经 localStorage 传数据,无侧边栏),替代原自包含 HTML blob
- 总览页布局:上半两列(总控共识+竞争力排行),核心风险分布下移到数据研判中心后
- 席位交付/执行路线网格列数自适应(grid.ts):不足4个卡片撑满整行
- 席位专页主体多样式变体(SeatShowcase):框架矩阵/洞察卡阵/双栏对比/清单核对/
  发布声明,按席位序号轮转分配,总结席位固定发布声明,全部数据驱动
- 修复切换历史记录时大屏/报告不刷新:渲染期复位入口闸门+hydrate依赖草稿id,
  hydrateSaved清残留data;数据切换时大屏自动回总览页

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
董宏凯andClaude Opus 4.8 committed 2026-06-13 16:32:32 +08:00
1 parent 432c12fbac
commit 2fa40c5e96
11 files changed
+496 -61

No files matched your search

@@ -39,6 +39,7 @@ import type { ModelOption } from "@/roundtable-planning/components/Step3ReportMo
import { ScrollToBottomButton } from "@/roundtable-planning/components/ScrollToBottomButton";
import { Step2Message } from "@/roundtable-planning/components/Step2Panel";
import { Step2SandboxLayout } from "@/roundtable-planning/components/Step2SandboxLayout";
import { DASHBOARD_VIEW_STORAGE_PREFIX } from "@/roundtable-planning/pages/DashboardStandalonePage";
import { useAutoScroll } from "@/roundtable-planning/hooks/useAutoScroll";
import { useDialogueSpeedMetrics } from "@/roundtable-planning/hooks/useDialogueSpeedMetrics";
import type { UseStep3DashboardReturn } from "@/roundtable-planning/hooks/useStep3Dashboard";
@@ -113,13 +114,25 @@ export function Step3DashboardMode({
return () => setPreviewEnabled(false);
}, [view, setPreviewEnabled]);
// 新窗口打开:把自包含 HTML 大屏(renderDashboardHtml 产物)在新标签页打开。
// 新窗口打开:把当前大屏数据写进 localStorage,在新标签页打开应用内 React 大屏
// (独立全屏路由 /roundtable-dashboard,无侧边栏)。无真实数据时 standalone 回落 DEMO。
const handleOpenNewWindow = () => {
if (!html || typeof window === "undefined") return;
const blob = new Blob([html], { type: "text/html;charset=utf-8" });
const url = URL.createObjectURL(blob);
if (typeof window === "undefined") return;
const key = `${DASHBOARD_VIEW_STORAGE_PREFIX}${Date.now()}`;
try {
// 先清掉历史键,避免 localStorage 堆积;再写本次数据。
for (let i = window.localStorage.length - 1; i >= 0; i -= 1) {
const k = window.localStorage.key(i);
if (k && k.startsWith(DASHBOARD_VIEW_STORAGE_PREFIX)) window.localStorage.removeItem(k);
}
if (dashboardData) window.localStorage.setItem(key, JSON.stringify(dashboardData));
} catch {
// localStorage 不可用(隐私模式/超额):忽略,新窗口将回落 DEMO 数据。
}
// HashRouter:在当前页基址上拼 hash 路由,带上数据键。
const base = `${window.location.origin}${window.location.pathname}`;
const url = `${base}#/roundtable-dashboard?k=${encodeURIComponent(key)}`;
window.open(url, "_blank", "noopener,noreferrer");
window.setTimeout(() => URL.revokeObjectURL(url), 60_000);
};
const handleRedraw = () => {
@@ -159,9 +172,8 @@ export function Step3DashboardMode({
<button
type="button"
onClick={handleOpenNewWindow}
disabled={!html}
title={html ? "在新标签页打开自包含 HTML 大屏" : "暂无可打开的大屏"}
className="bg-white border border-slate-200 text-slate-700 hover:bg-slate-50 disabled:opacity-50 disabled:cursor-not-allowed text-[10.5px] font-bold px-3 py-1.5 rounded-xl flex items-center gap-1 transition"
title="在新标签页打开 React 大屏页面(全屏,无侧边栏)"
className="bg-white border border-slate-200 text-slate-700 hover:bg-slate-50 text-[10.5px] font-bold px-3 py-1.5 rounded-xl flex items-center gap-1 transition"
>
<ExternalLink className="w-3.5 h-3.5 text-slate-500" />
新窗口打开