diff --git a/frontend/src/app/workspace/layout.tsx b/frontend/src/app/workspace/layout.tsx index 81604687..211272a2 100644 --- a/frontend/src/app/workspace/layout.tsx +++ b/frontend/src/app/workspace/layout.tsx @@ -14,12 +14,25 @@ import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; import { Toaster } from "@/components/ui/sonner"; import { CommandPalette } from "@/components/workspace/command-palette"; import { WorkspaceSidebar } from "@/components/workspace/workspace-sidebar"; +import { BrandProvider, useBrand } from "@/core/brand/provider"; +import { BrandSessionInitializer } from "@/core/brand/provider-client"; import { getLocalSettings, useLocalSettings } from "@/core/settings"; +import { cn } from "@/lib/utils"; const queryClient = new QueryClient(); export default function WorkspaceLayout({ children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + {children} + + ); +} + +function WorkspaceBrandShell({ + children, }: Readonly<{ children: React.ReactNode }>) { const [settings, setSettings] = useLocalSettings(); const [open, setOpen] = useState(false); // SSR default: open (matches server render) @@ -27,6 +40,7 @@ export default function WorkspaceLayout({ const pressedKeysRef = useRef>(new Set()); const comboTriggeredRef = useRef(false); const searchParams = useSearchParams(); + const { rootClassName } = useBrand(); // iframe 技能模式(mode=skill)时隐藏侧边栏 const isSkillMode = searchParams.get("mode") === "skill"; @@ -110,8 +124,9 @@ export default function WorkspaceLayout({ ); return ( + diff --git a/frontend/src/components/workspace/welcome.tsx b/frontend/src/components/workspace/welcome.tsx index 2cf5beb8..32c92482 100644 --- a/frontend/src/components/workspace/welcome.tsx +++ b/frontend/src/components/workspace/welcome.tsx @@ -1,8 +1,10 @@ "use client"; +import Image from "next/image"; import { useSearchParams } from "next/navigation"; import { useMemo } from "react"; +import { useBrand } from "@/core/brand/provider"; import { useI18n } from "@/core/i18n/hooks"; import { cn } from "@/lib/utils"; @@ -16,6 +18,7 @@ export function Welcome({ mode?: "ultra" | "pro" | "thinking" | "flash"; }) { const { t } = useI18n(); + const { copy } = useBrand(); const searchParams = useSearchParams(); const isUltra = useMemo(() => mode === "ultra", [mode]); const colors = useMemo(() => { @@ -39,12 +42,37 @@ export function Welcome({ className="flex items-center gap-2" style={{ fontFamily: '"Microsoft YaHei"' }} > - - {t.welcome.greeting} - + {copy.productLabel} + */} + + {copy.productLabel} + + + + · + + {copy.appLogoSrc ? ( + + ) : ( + + {copy.appName} + + )} )} @@ -59,7 +87,8 @@ export function Welcome({ )} ) : ( - + // + <>> )} ); diff --git a/frontend/src/components/workspace/workspace-header.tsx b/frontend/src/components/workspace/workspace-header.tsx index 420c7439..63e4655c 100644 --- a/frontend/src/components/workspace/workspace-header.tsx +++ b/frontend/src/components/workspace/workspace-header.tsx @@ -1,6 +1,7 @@ "use client"; import { MessageSquarePlus } from "lucide-react"; +import Image from "next/image"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { toast } from "sonner"; @@ -13,6 +14,7 @@ import { useSidebar, } from "@/components/ui/sidebar"; import { useThreadChat } from "@/components/workspace/chats"; +import { useBrand } from "@/core/brand/provider"; import { useI18n } from "@/core/i18n/hooks"; import { POST_MESSAGE_TYPES, sendToParent } from "@/core/iframe-messages"; import { env } from "@/env"; @@ -21,10 +23,14 @@ import { copyToClipboard } from "@/lib/utils"; export function WorkspaceHeader({ className }: { className?: string }) { const { t } = useI18n(); + const { copy } = useBrand(); const { state } = useSidebar(); const pathname = usePathname(); const { threadId } = useThreadChat(); const threadUrl = threadId ? `/workspace/chats/${threadId}` : ""; + const compactAppName = copy.appName.startsWith("cox") + ? `C${copy.appName.charAt(3).toUpperCase()}` + : copy.appName.slice(0, 2).toUpperCase(); const handleCopyThreadId = async () => { if (!threadId) return; @@ -51,7 +57,7 @@ export function WorkspaceHeader({ className }: { className?: string }) { {state === "collapsed" ? ( - XC + {compactAppName} @@ -62,9 +68,19 @@ export function WorkspaceHeader({ className }: { className?: string }) { {t.workspaceHeader.sidebarTitle} ) : ( - - {/* TODO: 测试标识 */} - XClaw{" "} + + {copy.appLogoSrc ? ( + + ) : ( + copy.appName + )} v3.3.0 {" "} id:{threadId ? threadId.slice(0, 5) : "-"} - {" "} {threadId && (