feat(frontend): M9 模态 UI(mode 系统+共享 store+WS 客户端 + chat(思维链/工具回显/情绪徽标)/code/Agent 监控/后台思考页 + Miuix 设计 token + PWA);tsc+vite build 通过

This commit is contained in:
Aska committed 2026-09-06 07:44:40 +08:00
1 parent b3ffd51736
commit 4c48e94659
40 files changed
+5321

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
import { useState } from "react";
import { useAppStore } from "../store/useAppStore";
import { useModeStore } from "../store/useModeStore";
import { applyTheme, readTheme, type ThemeMode } from "../lib/theme";
import type { WsStatus } from "../lib/types";
import { Tag } from "./primitives";
const wsMeta: Record<WsStatus, { label: string; tone: "ok" | "warn" | "neutral" | "err" }> = {
idle: { label: "未连接", tone: "neutral" },
connecting: { label: "连接中", tone: "warn" },
connected: { label: "实时", tone: "ok" },
reconnecting: { label: "重连中", tone: "warn" },
disconnected: { label: "已断开", tone: "err" },
};
export function TopBar(): React.ReactNode {
const wsStatus = useAppStore((s) => s.wsStatus);
const mood = useAppStore((s) => s.mood);
const mode = useModeStore((s) => s.mode);
const [theme, setTheme] = useState<ThemeMode>(readTheme);
const toggleTheme = () => {
const next: ThemeMode = theme === "dark" ? "light" : "dark";
applyTheme(next);
setTheme(next);
};
const meta = wsMeta[wsStatus];
return (
<header className="glass sticky top-0 z-30 flex h-[var(--mu-topbar-h)] items-center gap-3 border-b border-[var(--mu-glass-border)] px-4">
<div className="flex items-center gap-2">
<img src="/icon.svg" alt="Cyrene" className="h-7 w-7" />
<div className="leading-tight">
<div className="text-sm font-semibold">Cyrene · 昔涟</div>
<div className="text-[11px] text-[var(--mu-text-lo)]">{mode} 模式</div>
</div>
</div>
<div className="flex-1" />
{mood ? <Tag tone="accent">心情 · {mood}</Tag> : null}
<Tag tone={meta.tone}>
<span className={`inline-block h-1.5 w-1.5 rounded-full ${wsStatus === "connected" ? "bg-[var(--mu-ok)]" : "mu-blink"}`} />
{meta.label}
</Tag>
<button
onClick={toggleTheme}
aria-label="切换主题"
className="inline-flex h-8 w-8 items-center justify-center rounded-[var(--mu-radius)] bg-[var(--mu-surface-4)] text-sm transition-all duration-200 ease-[var(--mu-spring)] hover:bg-[var(--mu-surface-5)] active:scale-95"
>
{theme === "dark" ? "☀" : "☾"}
</button>
</header>
);
}