/**
* 最左活动栏:主导航 + 底部账号。
* 本地/团队工作区只在底部登录/头像菜单切换(设计师线框 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 (
);
}