diff --git a/frontend-web/.env.development b/frontend-web/.env.development index 3837c075..b78f859a 100644 --- a/frontend-web/.env.development +++ b/frontend-web/.env.development @@ -8,7 +8,7 @@ VITE_USE_REAL_DATA=true VITE_MOCK_COP_TASK_DETAIL=true # 研判情报报告(大屏绘制智能体深链 selectSqReport)数据源:true 走本地样例假数据(真实接口未就绪时调试用);联调通过后置 false。 -VITE_MOCK_SQ_REPORT=true +VITE_MOCK_SQ_REPORT=false # 深链任务详情(cop-task-detail:任务名称/描述)数据源:true 走本地假数据(真实接口未就绪时调试用);联调通过后置 false。 VITE_MOCK_COP_TASK_DETAIL=true diff --git a/frontend-web/src/components/workspace/appearance-controls.tsx b/frontend-web/src/components/workspace/appearance-controls.tsx new file mode 100644 index 00000000..02efa7c8 --- /dev/null +++ b/frontend-web/src/components/workspace/appearance-controls.tsx @@ -0,0 +1,186 @@ +"use client"; + +import { Check, LayoutIcon, PanelLeftIcon, Shirt } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { useTheme, type ThemeType } from "@/contexts/ThemeContext"; +import { useLayoutMode } from "@/core/system-settings/hooks"; +import { cn } from "@/lib/utils"; + +/** + * 换肤 / 界面模式 顶栏控件。深色顶栏(Header)与简洁模式页面级顶栏(ChatPage 等)共用, + * 通过 `tone` 适配不同底色: + * - "banner-dark" / "banner-light":Header 落在主题 banner 上(白字 / 浅色 hover)。 + * - "content":简洁模式聊天页浅底顶栏,走 foreground / muted-foreground。 + */ +export type AppearanceControlTone = "banner-dark" | "banner-light" | "content"; + +// 换肤色板:红色=红白主题(light),蓝色=浅蓝主题(lightblue),深蓝色=深色主题(dark) +export const THEME_SWATCHES: { id: ThemeType; label: string; color: string }[] = [ + { id: "light", label: "红色", color: "#cf1322" }, + { id: "lightblue", label: "蓝色", color: "#0062d9" }, + { id: "dark", label: "深蓝色", color: "#002466" }, +]; + +const triggerToneClass = (tone: AppearanceControlTone) => + tone === "banner-dark" + ? "text-slate-400 hover:bg-slate-800/50 hover:text-slate-400" + : tone === "banner-light" + ? "text-white hover:bg-[var(--brand-950)] hover:text-white active:bg-[#8a0618]" + : "text-muted-foreground hover:bg-muted hover:text-foreground"; + +export function ThemeSwitcher({ tone }: { tone: AppearanceControlTone }) { + const { theme, setTheme } = useTheme(); + const [open, setOpen] = useState(false); + const closeTimer = useRef | null>(null); + + const cancelClose = () => { + if (closeTimer.current) { + clearTimeout(closeTimer.current); + closeTimer.current = null; + } + }; + const scheduleClose = () => { + cancelClose(); + closeTimer.current = setTimeout(() => setOpen(false), 120); + }; + + useEffect(() => () => cancelClose(), []); + + return ( +
{ + cancelClose(); + setOpen(true); + }} + onMouseLeave={scheduleClose} + > + + {open ? ( +
+
+
+ {THEME_SWATCHES.map((swatch) => { + const active = theme === swatch.id; + return ( +
+
+ ) : null} +
+ ); +} + +const LAYOUT_OPTIONS = [ + { + id: "full" as const, + label: "全量模式", + description: "展示侧边栏与顶栏导航", + icon: PanelLeftIcon, + }, + { + id: "compact" as const, + label: "简洁模式", + description: "隐藏侧边栏与顶栏,获得更大工作区", + icon: LayoutIcon, + }, +]; + +/** + * 界面模式(全量 / 简洁)下拉切换。换肤旁并排,图标 + 下拉: + * - 简洁模式 ChatPage 顶栏(全局顶栏被隐藏)。 + * - 全量模式 Header 右上角。 + * 用户未显式设置过界面模式时(mode === undefined),当前态按调用方所在的实际界面 + * 兜底——`fallback` 指明这一回退值(Header 传 "full",ChatPage 传 "compact")。 + */ +export function LayoutModeSwitcher({ + tone, + fallback = "compact", +}: { + tone: AppearanceControlTone; + fallback?: "full" | "compact"; +}) { + const [mode, setLayoutMode] = useLayoutMode(); + const current = mode ?? fallback; + const TriggerIcon = current === "full" ? PanelLeftIcon : LayoutIcon; + + return ( + + + + + + 界面模式 + + {LAYOUT_OPTIONS.map((option) => { + const Icon = option.icon; + const active = current === option.id; + return ( + setLayoutMode(option.id)} + className="gap-2" + > + +
+ {option.label} + + {option.description} + +
+ {active && } +
+ ); + })} +
+
+ ); +} diff --git a/frontend-web/src/components/workspace/recent-roundtable-list.tsx b/frontend-web/src/components/workspace/recent-roundtable-list.tsx index c1af707f..67482aab 100644 --- a/frontend-web/src/components/workspace/recent-roundtable-list.tsx +++ b/frontend-web/src/components/workspace/recent-roundtable-list.tsx @@ -71,9 +71,10 @@ function StatusBadge({ draft }: { draft: DraftMeta }) { if (draft.status === "error") { return 出错; } + // 非进行中/待澄清/出错时,展示本次会商所用业务链(无链条 → 自由模式)。 return ( - 第 {draft.furthestStep} 步 + {draft.chainTitle || "自由模式"} ); } diff --git a/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx b/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx index aa6a7d60..c89efb9f 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx @@ -192,7 +192,7 @@ export function AIWritingForm({