feat: 多智能体会商草稿分享(import 复制 / view 公开结果页)
支持会商草稿生成分享码、导入副本与公开只读结果页,并在侧边栏展示最近会商记录。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
cca3d8eb41
commit
0fd314632a
20 files changed
+1584
No files matched your search
@@ -0,0 +1,83 @@
|
||||
"use client";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { getPublicDraftShareSnapshot } from "@/core/roundtable-draft-shares/api";
|
||||
|
||||
/**
|
||||
* Public, read-only roundtable-result viewer.
|
||||
*
|
||||
* Reachable at `#/roundtable-share/<code>` with NO authentication — anyone with
|
||||
* the link can open it. It renders the Step 3「结果绘制」report (a self-contained
|
||||
* HTML document) inside a sandboxed iframe with no `allow-scripts`, mirroring the
|
||||
* scheduled-task HTML-page preview, so a shared report can never execute code in
|
||||
* the app origin.
|
||||
*/
|
||||
export default function PublicRoundtableSharePage() {
|
||||
const { shareCode } = useParams<{ shareCode: string }>();
|
||||
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ["public-roundtable-share", shareCode],
|
||||
queryFn: () => getPublicDraftShareSnapshot(shareCode!),
|
||||
enabled: !!shareCode,
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="bg-background text-muted-foreground flex h-screen items-center justify-center gap-2 text-sm">
|
||||
<Loader2 className="size-4 animate-spin" />
|
||||
正在加载分享内容…
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return (
|
||||
<div className="bg-background flex h-screen flex-col items-center justify-center gap-2 px-6 text-center">
|
||||
<p className="text-lg font-medium">分享不可用</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
该分享链接不存在、已被撤销,或不是只读分享。
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-background flex h-screen flex-col">
|
||||
<header className="flex shrink-0 flex-col gap-1 border-b px-6 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<h1 className="truncate text-base font-semibold">
|
||||
{data.title || "未命名会商"}
|
||||
</h1>
|
||||
<span className="bg-muted text-muted-foreground shrink-0 rounded-full px-2 py-0.5 text-xs">
|
||||
只读分享
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
这是一份多智能体会商的结果报告快照(只读),你可以查看全部内容,但无法继续研讨。
|
||||
</p>
|
||||
</header>
|
||||
<main className="min-h-0 flex-1">
|
||||
{data.has_report ? (
|
||||
<iframe
|
||||
// No `allow-scripts` — the report is self-contained (inline CSS + inline
|
||||
// SVG charts) and must never run as a script in the app origin.
|
||||
sandbox=""
|
||||
title={data.title || "会商结果报告"}
|
||||
srcDoc={data.html}
|
||||
className="size-full border-0 bg-white"
|
||||
/>
|
||||
) : (
|
||||
<div className="text-muted-foreground flex h-full flex-col items-center justify-center gap-2 px-6 text-center text-sm">
|
||||
<p className="text-base font-medium text-foreground">暂无结果报告</p>
|
||||
<p>这次会商还没有生成第三步「结果绘制」的方案报告。</p>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user