122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import Icon from "./Icon";
|
|
import type { AuthUser, AuthWorkspace } from "../../context/AuthContext";
|
|
|
|
type TopbarProps = {
|
|
activePage: string;
|
|
apiOnline: boolean;
|
|
user: AuthUser | null;
|
|
currentWorkspace: AuthWorkspace;
|
|
workspaces: AuthWorkspace[];
|
|
workspaceMenuOpen: boolean;
|
|
onSetWorkspaceMenuOpen: (open: boolean) => void;
|
|
onSetCurrentWorkspace: (workspaceId: string) => void;
|
|
onLogout: () => void;
|
|
};
|
|
|
|
export function Topbar({
|
|
activePage,
|
|
apiOnline,
|
|
user,
|
|
currentWorkspace,
|
|
workspaces,
|
|
workspaceMenuOpen,
|
|
onSetWorkspaceMenuOpen,
|
|
onSetCurrentWorkspace,
|
|
onLogout,
|
|
}: TopbarProps) {
|
|
const pageTitles: Record<string, string> = {
|
|
home: "工作台",
|
|
scripts: "构建脚本",
|
|
schedules: "调度配置",
|
|
system: "系统管理",
|
|
};
|
|
|
|
return (
|
|
<header className="topbar">
|
|
<div className="page-title">
|
|
<button className="icon-button icon-button--back" type="button">
|
|
<Icon name="chevron" size={19} />
|
|
</button>
|
|
<div>
|
|
<span className="page-title__eyebrow">开发工作区</span>
|
|
<h1>{pageTitles[activePage] || "工作台"}</h1>
|
|
</div>
|
|
</div>
|
|
<div className="topbar__actions">
|
|
<div className="api-state">
|
|
<span className={`api-state__dot${apiOnline ? " is-online" : ""}`} />
|
|
{apiOnline ? "服务已连接" : "服务未连接"}
|
|
</div>
|
|
<div className="topbar-menu-wrap">
|
|
<button
|
|
className="workspace-switcher"
|
|
type="button"
|
|
onClick={() => onSetWorkspaceMenuOpen(!workspaceMenuOpen)}
|
|
>
|
|
<span className="workspace-switcher__icon">
|
|
<Icon name="workspace" size={18} />
|
|
</span>
|
|
<span>
|
|
<small>当前 Workspace</small>
|
|
<strong>{currentWorkspace.workspace_name}</strong>
|
|
</span>
|
|
<Icon name="chevron" size={15} />
|
|
</button>
|
|
{workspaceMenuOpen && (
|
|
<div className="topbar-dropdown">
|
|
{workspaces.map((workspace) => (
|
|
<button
|
|
className={
|
|
workspace.workspace_id === currentWorkspace.workspace_id
|
|
? "is-selected"
|
|
: ""
|
|
}
|
|
type="button"
|
|
key={workspace.workspace_id}
|
|
onClick={() => {
|
|
onSetCurrentWorkspace(workspace.workspace_id);
|
|
onSetWorkspaceMenuOpen(false);
|
|
}}
|
|
>
|
|
<Icon name="workspace" size={15} />
|
|
<span>
|
|
<strong>{workspace.workspace_name}</strong>
|
|
<small>
|
|
{workspace.workspace_id === currentWorkspace.workspace_id
|
|
? "当前使用"
|
|
: "点击切换"}
|
|
</small>
|
|
</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="topbar-menu-wrap">
|
|
<button className="user-menu" type="button">
|
|
<span className="avatar">
|
|
{user?.display_name?.slice(0, 1) ?? "?"}
|
|
</span>
|
|
<span className="user-menu__copy">
|
|
<strong>{user?.display_name ?? "未知用户"}</strong>
|
|
<small>
|
|
{user?.role_code === "admin" ? "管理员" : "开发人员"}
|
|
</small>
|
|
</span>
|
|
</button>
|
|
<button
|
|
className="text-button"
|
|
type="button"
|
|
onClick={() => {
|
|
onLogout();
|
|
window.location.assign("/login");
|
|
}}
|
|
>
|
|
登出
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|