套用wujie修改
This commit is contained in:
1 parent
c48317672c
commit
31525e79a8
5 files changed
+171
-110
No files matched your search
@@ -4,28 +4,38 @@ 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<
|
||||||
React.ElementRef<typeof DialogPrimitive.Trigger>,
|
React.ElementRef<typeof DialogPrimitive.Trigger>,
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>
|
||||||
>(({ ...props }, ref) => {
|
>(({ ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<DialogPrimitive.Trigger
|
<DialogPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
data-slot="dialog-trigger"
|
data-slot="dialog-trigger"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
DialogTrigger.displayName = DialogPrimitive.Trigger.displayName;
|
DialogTrigger.displayName = DialogPrimitive.Trigger.displayName;
|
||||||
|
|
||||||
function DialogPortal({
|
function DialogPortal({
|
||||||
...props
|
...props
|
||||||
@@ -33,68 +43,68 @@ function DialogPortal({
|
|||||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DialogClose = React.forwardRef<
|
const DialogClose = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Close>,
|
React.ElementRef<typeof DialogPrimitive.Close>,
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>
|
||||||
>(({ ...props }, ref) => {
|
>(({ ...props }, ref) => {
|
||||||
return <DialogPrimitive.Close ref={ref} data-slot="dialog-close" {...props} />;
|
return <DialogPrimitive.Close ref={ref} data-slot="dialog-close" {...props} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
DialogClose.displayName = DialogPrimitive.Close.displayName;
|
|
||||||
|
|
||||||
const DialogOverlay = React.forwardRef<
|
DialogClose.displayName = DialogPrimitive.Close.displayName;
|
||||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<DialogPrimitive.Overlay
|
|
||||||
ref={ref}
|
|
||||||
data-slot="dialog-overlay"
|
|
||||||
className={cn(
|
|
||||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
||||||
|
|
||||||
const DialogContent = React.forwardRef<
|
const DialogOverlay = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||||
showCloseButton?: boolean;
|
>(({ className, ...props }, ref) => {
|
||||||
}
|
return (
|
||||||
>(({ className, children, showCloseButton = true, ...props }, ref) => {
|
<DialogPrimitive.Overlay
|
||||||
return (
|
ref={ref}
|
||||||
<DialogPortal data-slot="dialog-portal">
|
data-slot="dialog-overlay"
|
||||||
<DialogOverlay />
|
className={cn(
|
||||||
<DialogPrimitive.Content
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||||
ref={ref}
|
className,
|
||||||
data-slot="dialog-content"
|
)}
|
||||||
className={cn(
|
{...props}
|
||||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
|
/>
|
||||||
className,
|
);
|
||||||
)}
|
});
|
||||||
{...props}
|
|
||||||
>
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||||
{children}
|
|
||||||
{showCloseButton && (
|
const DialogContent = React.forwardRef<
|
||||||
<DialogPrimitive.Close
|
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||||
data-slot="dialog-close"
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
||||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
showCloseButton?: boolean;
|
||||||
>
|
}
|
||||||
<XIcon />
|
>(({ className, children, showCloseButton = true, ...props }, ref) => {
|
||||||
<span className="sr-only">Close</span>
|
return (
|
||||||
</DialogPrimitive.Close>
|
<DialogPortal data-slot="dialog-portal">
|
||||||
)}
|
<DialogOverlay />
|
||||||
</DialogPrimitive.Content>
|
<DialogPrimitive.Content
|
||||||
</DialogPortal>
|
ref={ref}
|
||||||
);
|
data-slot="dialog-content"
|
||||||
});
|
className={cn(
|
||||||
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
|
||||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
{showCloseButton && (
|
||||||
|
<DialogPrimitive.Close
|
||||||
|
data-slot="dialog-close"
|
||||||
|
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||||
|
>
|
||||||
|
<XIcon />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
)}
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||||
|
|
||||||
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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