套用wujie修改
This commit is contained in:
1 parent
c48317672c
commit
31525e79a8
5 files changed
+97
-36
No files matched your search
@@ -4,12 +4,22 @@ import * as React from "react";
|
|||||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
import { XIcon } from "lucide-react";
|
import { XIcon } from "lucide-react";
|
||||||
|
|
||||||
|
import { isWujieEnv } from "@/core/embed/wujie";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
function Dialog({
|
function Dialog({
|
||||||
|
modal,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
// 无界嵌入时 Radix modal 会给 body 注入异常 margin-right,导致右侧空白。
|
||||||
|
// 默认降为 non-modal;显式传 modal={true} 仍可强制 modal。
|
||||||
|
return (
|
||||||
|
<DialogPrimitive.Root
|
||||||
|
data-slot="dialog"
|
||||||
|
modal={modal ?? !isWujieEnv()}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DialogTrigger = React.forwardRef<
|
const DialogTrigger = React.forwardRef<
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useSearchParams } from "next/navigation";
|
|||||||
import { useTheme } from "@/contexts/ThemeContext";
|
import { useTheme } from "@/contexts/ThemeContext";
|
||||||
import { loginByUsername } from "@/core/auth/api";
|
import { loginByUsername } from "@/core/auth/api";
|
||||||
import { setStoredAuth } from "@/core/auth";
|
import { setStoredAuth } from "@/core/auth";
|
||||||
import { readWujieProps } from "@/core/embed/wujie";
|
import { readWujieProps, isWujieEnv } from "@/core/embed/wujie";
|
||||||
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
|
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
|
||||||
import { ChatRuntime } from "./WorkspaceRoutes";
|
import { ChatRuntime } from "./WorkspaceRoutes";
|
||||||
import "@/roundtable-planning/styles/roundtable-planning.css";
|
import "@/roundtable-planning/styles/roundtable-planning.css";
|
||||||
@@ -66,6 +66,12 @@ export default function EmbedRoundtablePage() {
|
|||||||
setTheme(resolveEmbedRoundtableTheme(themeParam));
|
setTheme(resolveEmbedRoundtableTheme(themeParam));
|
||||||
}, [themeParam, setTheme]);
|
}, [themeParam, setTheme]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isWujieEnv()) return;
|
||||||
|
document.documentElement.classList.add("wujie-embed");
|
||||||
|
return () => document.documentElement.classList.remove("wujie-embed");
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
async function runLogin() {
|
async function runLogin() {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { isWujieEnv } from "@/core/embed/wujie";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
import { listChains, setChainPublic, type ChainScope } from "../api/chains";
|
import { listChains, setChainPublic, type ChainScope } from "../api/chains";
|
||||||
@@ -188,15 +187,8 @@ export function BusinessChainListDialog({
|
|||||||
onOpenChange,
|
onOpenChange,
|
||||||
onConfigure,
|
onConfigure,
|
||||||
}: BusinessChainListDialogProps) {
|
}: BusinessChainListDialogProps) {
|
||||||
const inWujie = isWujieEnv();
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
open={open}
|
|
||||||
onOpenChange={onOpenChange}
|
|
||||||
// Wujie 内部容器场景下,Radix modal 的 body-scroll-lock 可能计算出异常
|
|
||||||
// margin-right,导致右侧出现大片空白。这里降为 non-modal 规避布局抖动。
|
|
||||||
modal={!inWujie}
|
|
||||||
>
|
|
||||||
<DialogContent className="flex max-h-[85vh] flex-col gap-0 sm:max-w-2xl">
|
<DialogContent className="flex max-h-[85vh] flex-col gap-0 sm:max-w-2xl">
|
||||||
<DialogHeader className="shrink-0">
|
<DialogHeader className="shrink-0">
|
||||||
<DialogTitle className="flex items-center gap-2">
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ export default function RoundtablePlanningPage() {
|
|||||||
const isDark = theme === "dark";
|
const isDark = theme === "dark";
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
/** 无界(wujie)嵌入抽屉:隐藏业务链条入口,设置按钮改作手动回传交付。 */
|
||||||
|
const inWujieEmbed = isWujieEnv();
|
||||||
|
|
||||||
// ─── 会商自动化串联(模块 C):任务页带进来的预填 ─────────────────
|
// ─── 会商自动化串联(模块 C):任务页带进来的预填 ─────────────────
|
||||||
// 只在首次渲染读一次 navigation state;随后清掉 history state,避免刷新/后退重放。
|
// 只在首次渲染读一次 navigation state;随后清掉 history state,避免刷新/后退重放。
|
||||||
@@ -167,6 +169,12 @@ export default function RoundtablePlanningPage() {
|
|||||||
);
|
);
|
||||||
// 由 prefill.businessCode 解析出的「自动选用业务链」结果;有值时「进入研讨」跳过选链弹窗直接进 Step 2。
|
// 由 prefill.businessCode 解析出的「自动选用业务链」结果;有值时「进入研讨」跳过选链弹窗直接进 Step 2。
|
||||||
const [autoChainResult, setAutoChainResult] = useState<SeatSelectionResult | null>(null);
|
const [autoChainResult, setAutoChainResult] = useState<SeatSelectionResult | null>(null);
|
||||||
|
/** 无界直传 chainId 时,链条解析完成前禁止弹选链窗(避免 modal 布局抖动)。 */
|
||||||
|
const [autoChainLoading, setAutoChainLoading] = useState(
|
||||||
|
() =>
|
||||||
|
inWujieEmbed &&
|
||||||
|
!!(prefillRef.current?.chainId || prefillRef.current?.businessCode),
|
||||||
|
);
|
||||||
const autoStartedRef = useRef(false);
|
const autoStartedRef = useRef(false);
|
||||||
const prefillClearedRef = useRef(false);
|
const prefillClearedRef = useRef(false);
|
||||||
// 共识达成后只向父页面(无界)回传一次交付结果。
|
// 共识达成后只向父页面(无界)回传一次交付结果。
|
||||||
@@ -774,6 +782,7 @@ export default function RoundtablePlanningPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prefill = prefillRef.current;
|
const prefill = prefillRef.current;
|
||||||
if (!prefill?.chainId && !prefill?.businessCode) return;
|
if (!prefill?.chainId && !prefill?.businessCode) return;
|
||||||
|
setAutoChainLoading(true);
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
void (async () => {
|
void (async () => {
|
||||||
try {
|
try {
|
||||||
@@ -794,6 +803,8 @@ export default function RoundtablePlanningPage() {
|
|||||||
if (!cancelled && result) setAutoChainResult(result);
|
if (!cancelled && result) setAutoChainResult(result);
|
||||||
} catch {
|
} catch {
|
||||||
/* 解析失败 → 保持 null,回退弹窗手选 */
|
/* 解析失败 → 保持 null,回退弹窗手选 */
|
||||||
|
} finally {
|
||||||
|
if (!cancelled) setAutoChainLoading(false);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
return () => {
|
return () => {
|
||||||
@@ -801,13 +812,9 @@ export default function RoundtablePlanningPage() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// C4(无界回传):第二步达成共识后,把总控结论 + 各智能体交付一次性广播给父页面。
|
/** 组装无界回传载荷:总控共识 + 各智能体最终交付(剔除总控席位)。 */
|
||||||
// 用 ref 防重(共识态会多次触发渲染);非无界环境静默跳过。
|
const buildWujieConsensusPayload = useCallback(
|
||||||
useEffect(() => {
|
() => ({
|
||||||
if (!step2.hasConsensus || consensusEmittedRef.current) return;
|
|
||||||
if (!isWujieEnv()) return;
|
|
||||||
consensusEmittedRef.current = true;
|
|
||||||
emitWujieEvent("roundtable:consensus", {
|
|
||||||
taskTitle: prefillRef.current?.taskTitle ?? null,
|
taskTitle: prefillRef.current?.taskTitle ?? null,
|
||||||
chainId: prefillRef.current?.chainId ?? null,
|
chainId: prefillRef.current?.chainId ?? null,
|
||||||
chainTitle: chainMeta?.title ?? null,
|
chainTitle: chainMeta?.title ?? null,
|
||||||
@@ -817,14 +824,43 @@ export default function RoundtablePlanningPage() {
|
|||||||
step2.step2RoundtableDialogues,
|
step2.step2RoundtableDialogues,
|
||||||
step2.coordinatorName,
|
step2.coordinatorName,
|
||||||
),
|
),
|
||||||
});
|
}),
|
||||||
}, [
|
[
|
||||||
step2.hasConsensus,
|
chainMeta,
|
||||||
step2.coordinatorName,
|
step2.coordinatorName,
|
||||||
step2.lastLeaderContent,
|
step2.lastLeaderContent,
|
||||||
step2.step2RoundtableDialogues,
|
step2.step2RoundtableDialogues,
|
||||||
chainMeta,
|
],
|
||||||
]);
|
);
|
||||||
|
|
||||||
|
const emitConsensusToParent = useCallback(() => {
|
||||||
|
if (!inWujieEmbed) return false;
|
||||||
|
return emitWujieEvent("roundtable:consensus", buildWujieConsensusPayload());
|
||||||
|
}, [buildWujieConsensusPayload, inWujieEmbed]);
|
||||||
|
|
||||||
|
const handleSettingsClick = useCallback(() => {
|
||||||
|
if (inWujieEmbed) {
|
||||||
|
const deliverables = buildWujieConsensusPayload().deliverables;
|
||||||
|
if (deliverables.length === 0) {
|
||||||
|
triggerToast("暂无可回传的智能体交付结果");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (emitConsensusToParent()) {
|
||||||
|
triggerToast(`已回传 ${deliverables.length} 个智能体交付结果`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
triggerToast("⚙️ 系统管理面板拉取中(暂不开放外部审计)");
|
||||||
|
}, [buildWujieConsensusPayload, emitConsensusToParent, inWujieEmbed, triggerToast]);
|
||||||
|
|
||||||
|
// C4(无界回传):第二步达成共识后,把总控结论 + 各智能体交付一次性广播给父页面。
|
||||||
|
// 用 ref 防重(共识态会多次触发渲染);非无界环境静默跳过。
|
||||||
|
useEffect(() => {
|
||||||
|
if (!step2.hasConsensus || consensusEmittedRef.current) return;
|
||||||
|
if (!inWujieEmbed) return;
|
||||||
|
consensusEmittedRef.current = true;
|
||||||
|
emitConsensusToParent();
|
||||||
|
}, [step2.hasConsensus, inWujieEmbed, emitConsensusToParent]);
|
||||||
|
|
||||||
// 把页面重置回「第一步全新任务」——新建任务 + 后台挂起后都复用。
|
// 把页面重置回「第一步全新任务」——新建任务 + 后台挂起后都复用。
|
||||||
// 注意:只清前端状态,不删后端已建的草稿 / 已挂起的后台作业(它们继续在后台跑,
|
// 注意:只清前端状态,不删后端已建的草稿 / 已挂起的后台作业(它们继续在后台跑,
|
||||||
@@ -1016,15 +1052,17 @@ export default function RoundtablePlanningPage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
{!inWujieEmbed && (
|
||||||
id="business-chain-btn"
|
<button
|
||||||
onClick={() => setIsChainListOpen(true)}
|
id="business-chain-btn"
|
||||||
title="查看 / 配置可复用的业务链条(有序智能体编排)"
|
onClick={() => setIsChainListOpen(true)}
|
||||||
className="bg-white hover:bg-slate-50 border border-[#e2e8f0] text-[#334155] text-xs font-bold px-3 py-2 rounded-xl flex items-center gap-1.5 transition dark:border-border dark:bg-secondary dark:text-foreground dark:hover:bg-accent"
|
title="查看 / 配置可复用的业务链条(有序智能体编排)"
|
||||||
>
|
className="bg-white hover:bg-slate-50 border border-[#e2e8f0] text-[#334155] text-xs font-bold px-3 py-2 rounded-xl flex items-center gap-1.5 transition dark:border-border dark:bg-secondary dark:text-foreground dark:hover:bg-accent"
|
||||||
<ListOrdered className="w-3.5 h-3.5 text-primary" />
|
>
|
||||||
业务链条
|
<ListOrdered className="w-3.5 h-3.5 text-primary" />
|
||||||
</button>
|
业务链条
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
id="new-task-btn"
|
id="new-task-btn"
|
||||||
@@ -1083,7 +1121,8 @@ export default function RoundtablePlanningPage() {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
id="settings-btn"
|
id="settings-btn"
|
||||||
onClick={() => triggerToast("⚙️ 系统管理面板拉取中(暂不开放外部审计)")}
|
onClick={handleSettingsClick}
|
||||||
|
title={inWujieEmbed ? "回传各智能体交付结果给宿主" : "系统设置"}
|
||||||
className="p-1.5 text-slate-400 hover:text-slate-600 rounded-lg hover:bg-slate-100 transition-colors dark:text-muted-foreground dark:hover:bg-accent dark:hover:text-foreground"
|
className="p-1.5 text-slate-400 hover:text-slate-600 rounded-lg hover:bg-slate-100 transition-colors dark:text-muted-foreground dark:hover:bg-accent dark:hover:text-foreground"
|
||||||
>
|
>
|
||||||
<Settings className="w-4 h-4" />
|
<Settings className="w-4 h-4" />
|
||||||
@@ -1142,6 +1181,14 @@ export default function RoundtablePlanningPage() {
|
|||||||
void drafts.ensureDraft(1).finally(() => handleConfirmAgents(result));
|
void drafts.ensureDraft(1).finally(() => handleConfirmAgents(result));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
inWujieEmbed &&
|
||||||
|
autoChainLoading &&
|
||||||
|
(prefillRef.current?.chainId || prefillRef.current?.businessCode)
|
||||||
|
) {
|
||||||
|
triggerToast("正在加载业务链条,请稍候…");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 先把草稿落地拿到 draft_id,推荐历史才有归属;失败也照常打开弹窗
|
// 先把草稿落地拿到 draft_id,推荐历史才有归属;失败也照常打开弹窗
|
||||||
// (弹窗在无 draftId 时退化为「直接推荐、不存历史」)。
|
// (弹窗在无 draftId 时退化为「直接推荐、不存历史」)。
|
||||||
void drafts.ensureDraft(1).finally(() => setIsRecommendDialogOpen(true));
|
void drafts.ensureDraft(1).finally(() => setIsRecommendDialogOpen(true));
|
||||||
|
|||||||
@@ -337,6 +337,12 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 无界嵌入:Radix scroll-lock 可能误算 margin-right,留下右侧空白条 */
|
||||||
|
html.wujie-embed body {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
[data-sidebar="menu-button"][data-active="true"] {
|
[data-sidebar="menu-button"][data-active="true"] {
|
||||||
box-shadow: inset 3px 0 0 var(--primary);
|
box-shadow: inset 3px 0 0 var(--primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|||||||
Reference in new issue
Block a user