/** * 最左活动栏:主导航 + 底部账号。 * 本地/团队工作区只在底部登录/头像菜单切换(设计师线框 B);不再显示顶部「本」字标。 */ import { useState } from "react"; import { useWorkspace } from "../workspaceStore"; import { ContextMenu, cx, type MenuItem } from "./common"; import { Icon, type IconName } from "./icons"; export function ActivityRail() { const view = useWorkspace((s) => s.view); const setView = useWorkspace((s) => s.setView); const setSidebarSide = useWorkspace((s) => s.setSidebarSide); const account = useWorkspace((s) => s.account); const switchSpace = useWorkspace((s) => s.switchSpace); const authLogout = useWorkspace((s) => s.authLogout); const syncNow = useWorkspace((s) => s.syncNow); const setDialog = useWorkspace((s) => s.setDialog); const [accountMenu, setAccountMenu] = useState<{ x: number; y: number } | null>(null); const activeSpace = account.spaces.find((sp) => sp.id === account.activeSpaceId) ?? null; const isTeam = activeSpace?.teamId != null; const spaceName = activeSpace ? `${isTeam ? "团队 · " : ""}${activeSpace.name}` : "本地工作区"; const siteItem: MenuItem = { label: ( 官网与价格 ), icon: , onClick: () => window.open("/home", "_blank", "noopener,noreferrer"), }; const workspaceItems: MenuItem[] = [ { label: ( 本地工作区 {account.activeSpaceId === null && ( ● 当前 )} ), onClick: () => void switchSpace(null), }, ...account.spaces.map((sp) => { const team = sp.teamId != null; return { label: ( {team ? `团队 · ${sp.name}` : sp.name} {sp.id === account.activeSpaceId ? ( ● 当前 ) : ( {new Date(sp.updatedAt * 1000).toLocaleDateString("zh-CN")} )} ), onClick: () => void switchSpace(sp.id), }; }), ]; const accountItems: MenuItem[] = account.user ? [ ...workspaceItems, { type: "sep" as const }, { label: "环境变量", icon: , onClick: () => setDialog({ type: "environments" }), }, { label: "账号设置", icon: , onClick: () => setDialog({ type: "settings" }), }, ...(account.activeSpaceId !== null ? [ { label: account.syncing ? "同步中…" : account.lastSyncAt ? `已同步 ${new Date(account.lastSyncAt).toLocaleTimeString("zh-CN")}` : "立即同步到云端", icon: , onClick: () => void syncNow(), }, ] : []), { label: "团队管理…", icon: , onClick: () => setDialog({ type: "team" }), }, { type: "sep" as const }, siteItem, { label: "退出", icon: , onClick: () => void authLogout(), }, ] : [ { label: "登录 / 注册", icon: , onClick: () => setDialog({ type: "auth" }), }, { type: "sep" as const }, { label: "本地工作区", icon: , onClick: () => void switchSpace(null), }, { label: "环境变量", icon: , onClick: () => setDialog({ type: "environments" }), }, { type: "sep" as const }, siteItem, ]; const navs: { id: string; icon: IconName; label: string; active: boolean; onClick: () => void; soon?: boolean }[] = [ { id: "api", icon: "globe", label: "接口", active: view === "api", onClick: () => { setView("api"); setSidebarSide("api"); }, }, { id: "testing", icon: "list-checks", label: "测试", active: view === "testing", onClick: () => setView("testing"), soon: true, }, ]; const syncTitle = !account.user ? "登录后可切换团队工作区;未登录也可继续用本地" : `${account.user.name}(${account.user.email})\n当前:${spaceName}${ account.syncing ? "\n同步中…" : account.syncError ? `\n同步失败:${account.syncError}` : account.lastSyncAt && account.activeSpaceId !== null ? `\n已同步 ${new Date(account.lastSyncAt).toLocaleTimeString("zh-CN")}` : "" }`; return ( ); }