wujie应用联调

This commit is contained in:
董宏凯 committed 2026-06-11 17:11:28 +08:00
1 parent 0784f30e23
commit f3ca996116
35 files changed
+1590 -334

No files matched your search

@@ -0,0 +1,115 @@
"use client";
import { useEffect, useState } from "react";
import { useSearchParams } from "next/navigation";
import { useTheme } from "@/contexts/ThemeContext";
import { loginByUsername } from "@/core/auth/api";
import { setStoredAuth } from "@/core/auth";
import { readWujieProps } from "@/core/embed/wujie";
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
import { ChatRuntime } from "./WorkspaceRoutes";
import "@/roundtable-planning/styles/roundtable-planning.css";
const DEFAULT_USERNAME = "guest";
/**
* 把宿主传入的主题标识映射成 light/dark。**默认深蓝(dark)**:
* 只有明确传 light/红白 才走浅色,其余(dark / dark-blue / 深蓝 / 空)一律深蓝。
* 不复用 `resolveEmbedTheme`(它只认严格的 "dark-blue",传 "dark" 会被判成浅色)。
*/
function resolveEmbedRoundtableTheme(raw: string): "dark" | "light" {
const v = raw.trim().toLowerCase();
if (v === "light" || v === "red" || v === "红白") return "light";
return "dark";
}
/**
* 圆桌规划嵌入页(独立入口,**与现有 wujie ticket 登录无关**)。
*
* 用于宿主(如 parallel-agents-vue 的 RoundtableDrawer)用无界把圆桌**主体页面**塞进抽屉:
* - **登录**:走「用户名免密登录」(`loginByUsername`),username 来自 `window.$wujie.props.username`
* (或 URL `?username=`),不经 LoginPage 的 MaxKey/consumer ticket 流程。
* - **无侧边栏**:本路由挂在顶层(`/embed/roundtable`),在 `AppProviders` 之下、`PageRoutes` 之外,
* 天然不含页面侧边栏 / workspace 导航,只渲染圆桌主体。
* - **任务预填**:taskTitle / taskGoal / chainId 由 `RoundtablePlanningPage` 自身的
* `readWujiePrefill()` 直接从 `window.$wujie.props` 读取(抽屉打开即自动跑第一步、按链条进第二步)。
*/
export default function EmbedRoundtablePage() {
const searchParams = useSearchParams();
const { setTheme } = useTheme();
// username / password / theme:wujie props 优先,URL query 兜底。
const wp = readWujieProps();
const username =
(typeof wp.username === "string" && wp.username.trim()) ||
(typeof wp.userName === "string" && wp.userName.trim()) ||
searchParams.get("username")?.trim() ||
searchParams.get("userName")?.trim() ||
DEFAULT_USERNAME;
// 共享口令(用户名+密码登录模式):仅当后端开启 username_login.require_password 时校验。
// 不 trim —— 口令可能含首尾空格;未传则按「免密」走(后端未开门禁时照常)。
const password =
(typeof wp.password === "string" && wp.password) ||
searchParams.get("password") ||
undefined;
// 主题色:宿主传入优先;默认「深蓝」= dark 主题(其主色为蓝,oklch hue 259)。
const themeParam =
(typeof wp.theme === "string" && wp.theme.trim()) ||
searchParams.get("theme")?.trim() ||
"dark";
const [authReady, setAuthReady] = useState(false);
const [authError, setAuthError] = useState<string | null>(null);
useEffect(() => {
setTheme(resolveEmbedRoundtableTheme(themeParam));
}, [themeParam, setTheme]);
useEffect(() => {
let cancelled = false;
async function runLogin() {
setAuthError(null);
try {
const auth = await loginByUsername(username, password);
if (cancelled) return;
setStoredAuth(auth);
setAuthReady(true);
} catch (error) {
if (cancelled) return;
setAuthError(error instanceof Error ? error.message : "登录失败");
}
}
void runLogin();
return () => {
cancelled = true;
};
}, [username, password]);
if (authError) {
return (
<div className="flex size-full items-center justify-center bg-background p-6 text-sm text-red-600">
登录失败:{authError}
</div>
);
}
if (!authReady) {
return (
<div className="flex size-full items-center justify-center bg-background p-6 text-sm text-muted-foreground">
正在进入圆桌…
</div>
);
}
// RoundtablePlanningPage 依赖 SubtasksProvider / ArtifactsProvider / PromptInputProvider
// (Step 2 沙箱用 useArtifacts)。ChatRuntime 正是这三者的封装;不套 WorkspaceLayout,
// 故无侧边栏,只渲染圆桌主体。
return (
<div className="h-full w-full overflow-hidden">
<ChatRuntime>
<RoundtablePlanningPage />
</ChatRuntime>
</div>
);
}