+
{children}
{pagination ?
{pagination}
: null}
diff --git a/web/components/palette-toggle.tsx b/web/components/palette-toggle.tsx
new file mode 100644
index 0000000..5f897a6
--- /dev/null
+++ b/web/components/palette-toggle.tsx
@@ -0,0 +1,96 @@
+"use client"
+
+import { useEffect, useState } from "react"
+import { DropletsIcon, PaletteIcon } from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+type PaletteMode = "blue" | "green" | "gray"
+
+const PALETTE_STORAGE_KEY = "dashboard_palette"
+const DEFAULT_PALETTE: PaletteMode = "green"
+
+const paletteOptions: Array<{
+ value: PaletteMode
+ label: string
+ swatch: string
+}> = [
+ {
+ value: "green",
+ label: "温润服务绿",
+ swatch: "bg-teal-700",
+ },
+ {
+ value: "gray",
+ label: "中性精密灰",
+ swatch: "bg-slate-500",
+ },
+ {
+ value: "blue",
+ label: "清透科技蓝",
+ swatch: "bg-blue-600",
+ },
+]
+
+function readPalette(): PaletteMode {
+ if (typeof window === "undefined") {
+ return DEFAULT_PALETTE
+ }
+
+ const stored = window.localStorage.getItem(PALETTE_STORAGE_KEY)
+ return stored === "blue" || stored === "green" || stored === "gray"
+ ? stored
+ : DEFAULT_PALETTE
+}
+
+function applyPalette(value: PaletteMode) {
+ document.documentElement.dataset.palette = value
+ window.localStorage.setItem(PALETTE_STORAGE_KEY, value)
+}
+
+export function PaletteToggle() {
+ const [palette, setPalette] = useState
(DEFAULT_PALETTE)
+
+ useEffect(() => {
+ const storedPalette = readPalette()
+ setPalette(storedPalette)
+ applyPalette(storedPalette)
+ }, [])
+
+ function handleChange(value: string) {
+ const nextPalette: PaletteMode =
+ value === "blue" || value === "gray" ? value : "green"
+ setPalette(nextPalette)
+ applyPalette(nextPalette)
+ }
+
+ const ActiveIcon = palette === "green" ? DropletsIcon : PaletteIcon
+
+ return (
+
+ }
+ aria-label="切换主题色"
+ >
+
+
+
+
+ {paletteOptions.map((option) => (
+
+
+ {option.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/web/components/site-header.tsx b/web/components/site-header.tsx
index 02ed92d..c3f18be 100644
--- a/web/components/site-header.tsx
+++ b/web/components/site-header.tsx
@@ -6,6 +6,7 @@ import { usePathname } from "next/navigation"
import { RealtimeConnectionStatus } from "@/components/realtime-connection-status"
import { getPageTitle } from "@/lib/navigation"
import { useAgentConversationsStore } from "@/lib/stores/agent-conversations"
+import { PaletteToggle } from "@/components/palette-toggle"
import { ThemeToggle } from "@/components/theme-toggle"
import {
Breadcrumb,
@@ -50,7 +51,7 @@ export function SiteHeader() {
}, [isMobile, open])
return (
-