refactor(web): 前端目录重构 — consoles/pages → layouts/features + shared

- consoles/admin/ → layouts/admin-layout/
- consoles/workbench/ → layouts/workbench-layout/ + features/chat/
- pages/ → features/ (dashboard, models, projects, not-found)
- components/ → shared/components/
- hooks/ → shared/hooks/
- utils/ → shared/utils/
- 更新所有 import 路径 (src/web/ + tests/web/)
- 更新开发文档 (README.md, frontend.md, architecture.md)
This commit is contained in:
2026-06-02 23:17:28 +08:00
parent 1f05f259d0
commit b1dec691e9
76 changed files with 249 additions and 111 deletions

View File

@@ -0,0 +1,75 @@
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { XProvider } from "@ant-design/x";
import zhCN_X from "@ant-design/x/locale/zh_CN";
import { App as AntApp, Layout, Segmented, theme } from "antd";
import zhCN from "antd/locale/zh_CN";
import type { ConsoleShellProps } from "./types";
import { APP } from "../../../../shared/app";
import { useMeta } from "../../hooks/use-meta";
import { useSidebarCollapsed } from "../../hooks/use-sidebar-collapsed";
import { useThemePreference } from "../../hooks/use-theme-preference";
import { Sidebar } from "../Sidebar";
import { ConsoleOutlet } from "./ConsoleOutlet";
const { Content, Header, Sider } = Layout;
const THEME_OPTIONS = [
{ label: "系统", value: "system" },
{ label: "明亮", value: "light" },
{ label: "黑暗", value: "dark" },
] as const;
export function ConsoleShell({ headerExtra, menuItems, title }: ConsoleShellProps) {
const { effectiveTheme, preference: themePreference, setPreference: setThemePreference } = useThemePreference();
const { collapsed, setCollapsed } = useSidebarCollapsed();
const { data: meta } = useMeta();
const versionDisplay = meta?.version ? `v${meta.version}` : null;
const themeAlgorithm = effectiveTheme === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm;
return (
<XProvider locale={{ ...zhCN, ...zhCN_X }} theme={{ algorithm: themeAlgorithm }}>
<AntApp>
<Layout className="app-layout">
<Header className="app-header">
<div className="app-header-left">
<span className="app-brand-group">
<span className="app-brand">{APP.title}</span>
{versionDisplay && <span className="app-version">{versionDisplay}</span>}
<span className="app-console-title">{title}</span>
</span>
</div>
<div className="app-header-right">
{headerExtra}
<Segmented
onChange={(value) => setThemePreference(value)}
options={THEME_OPTIONS.map((option) => ({ label: option.label, value: option.value }))}
value={themePreference}
/>
</div>
</Header>
<Layout>
<Sider
collapsed={collapsed}
collapsedWidth={64}
collapsible
onCollapse={(c) => setCollapsed(c)}
theme="light"
trigger={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
width={232}
>
<Sidebar menuItems={menuItems} />
</Sider>
<Layout>
<Content className="app-content">
<ConsoleOutlet />
</Content>
</Layout>
</Layout>
</Layout>
</AntApp>
</XProvider>
);
}