Files
Alfred/docs/development/frontend.md
lanyuanxiaoyao 6cb378d7cb feat: Admin/Workbench 双入口架构
- 抽取 ConsoleShell 共享外壳(Layout/Header/Sider/主题切换/侧边栏折叠)
- Sidebar 纯化为接受 menuItems prop 的展示组件
- Admin 管理台:/ 总览 + /projects 项目管理
- Workbench 工作台:/workbench/:projectId 项目作用域
- WorkbenchProjectGate 入口守卫(loading/error/archived/不存在拦截)
- ProjectContext 提供当前项目上下文
- 项目管理表格 active 行增加'进入工作台'按钮
- 项目名称 trim 后最多 10 字符(前后端一致)
- Workbench 总览页展示项目 Descriptions
- Header 区分:管理台显示副标题,工作台显示项目名 + 返回管理台按钮
- 28/28 前端测试通过
- 文档更新:frontend.md ConsoleShell 规范、usage.md 双入口说明
2026-05-28 22:33:03 +08:00

164 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端开发
本文档说明 alfred 前端的 React、Ant Design、TanStack Query、组件、样式和前端测试约定。
适用场景:修改 src/web/、前端共享类型使用方式、组件结构、样式规则或前端测试。
## 技术栈
| 层面 | 技术 | 用途 |
| ------ | --------------------------------------------------- | ------------------------ |
| 框架 | React 19 | UI 组件开发 |
| 构建 | Vite开发+ Bun compile生产 | 开发服务 HMR 与生产构建 |
| 语言 | TypeScript | 类型安全 |
| UI 库 | Ant Design (antd) + @ant-design/icons | UI 组件与图标 |
| 数据层 | TanStack Query (React Query) + React Query Devtools | 服务端状态管理与自动刷新 |
| 路由 | React Router v7 (Declarative mode) | SPA 路由与页面导航 |
不引入额外状态管理库。TanStack Query 承担服务端状态,组件内状态使用 useState。
## 组件开发规范
- 每个 React 组件一个 .tsx 文件,文件名使用 PascalCase
- 组件 props 定义为 interface XxxProps紧邻组件函数声明
- 类型从 src/shared/api.ts 导入,使用 import type
- 展示组件放在 components/,通过 props 接收数据,通过回调返回事件;页面专属展示组件可就近放在 pages/\*/components/
- 容器逻辑放在 hooks 中,组件只做数据消费;全局共享查询可提取为独立 hook如 use-meta
- 工具函数放在 utils/,保持纯函数无副作用
页面组件保持编排职责,组合 hooks 和展示组件;当页面同时承担查询、筛选、分页、表格列、弹窗表单和 mutation 时,应按工具栏、表格、表单弹窗等功能边界拆分。拆分以降低职责复杂度为目标,避免为了拆分而拆分。
## Ant Design 使用规范
- 优先使用 antd 组件默认状态和官方交互模式;没有明确产品定制需求时,不额外改写组件视觉。
- 优先通过组件 props 配置行为和外观,例如 `collapsible``theme``scroll``locale``status``variant``color`
- 全局使用 `ConfigProvider` 配置 antd 中文 locale`antd/locale/zh_CN` 导入 `zhCN`
- 需要 message、modal、notification 等 antd 应用级能力时,在 `ConfigProvider` 内包裹 `App`(代码中可别名为 `AntApp`),组件内通过 `App.useApp()` 获取。
- 状态页、异常页、空结果优先使用 `Result``Empty``Alert``Spin` 等 antd 组件。
- 信息展示优先使用 `Typography``Card``Descriptions``Table` 等 antd 组件,避免用原生标签加自定义 CSS 复刻。
- 搜索输入优先使用 `Input.Search`,保持回车搜索、按钮搜索和清空行为一致。
- 表格在窄屏有挤压风险时必须提供明确的 `scroll` 或响应式列策略。
## 样式开发规范
前端基于 Ant Design 构建 UI。样式管理目标是让 antd 继续承担主视觉系统,项目 CSS 只补足页面外壳、局部布局和自有组件视觉,不另起一套与 antd 竞争的样式体系。
样式开发优先级:
1. antd 组件默认能力,例如 `Button``Card``Table``Form``Result``Empty`
2. antd 组件 props例如 `size``type``variant``color``status``layout``scroll``gutter`
3. antd 布局组件,例如 `Layout``Flex``Space``Row``Col`,避免为普通排列关系新增 CSS。
4. `ConfigProvider` theme token 和 antd 组件 token处理主题级或组件级统一调整。
5. antd CSS 变量(`--ant-*`),用于项目自有 CSS 中引用颜色、间距、字体、圆角和阴影等设计值。
6. 全局 CSS仅承载应用外壳、全局基础样式和少量明确复用的工具类。
7. CSS Modules用于页面专属布局或项目自有组件视觉仅在局部样式增长到需要就近维护时使用。
8. 自行开发视觉组件,仅在 antd 组件和组合方式无法表达明确产品需求时使用。
红线:
- 严禁在组件中使用 `style` 属性内联调整样式。
- 严禁通过 CSS 覆盖 antd 组件内部类名,例如 `.ant-*`
- 严禁使用 `!important`
- 颜色统一使用 antd Design Token / CSS 变量,不使用硬编码色值。
- 默认不引入 Tailwind、UnoCSS、Sass、Less、CSS-in-JS 或额外 PostCSS 插件;确需引入时必须先说明现有 antd + CSS Modules 无法满足的具体问题、影响范围和迁移成本。
默认状态原则:如果 antd 组件默认样式已经满足当前需求,不为其增加额外 CSS 类;不要通过外层 CSS 修改 Sider、Menu、Table、Modal 等组件内部结构样式。
全局 CSS 归属:
- 当前入口保留 `src/web/styles.css`;当文件继续增长时,优先拆分为 `src/web/styles/global.css``src/web/styles/app-shell.css``src/web/styles/utilities.css` 等按职责命名的文件,再由入口样式文件集中导入。
- `global.css` 仅放 `html``body``:root`、字体渲染、全局背景等应用级基础样式。
- `app-shell.css` 仅放应用外壳样式,例如 `app-layout``app-header``app-content`、Header 内容分布和主内容间距。
- `utilities.css` 只放至少两处复用、语义稳定、不会与 antd props 重叠的工具类;只有一处使用时优先改为 antd 布局组件或局部 CSS Modules。
- 全局类名必须带有明确前缀,应用外壳使用 `app-*`,工具类使用 `u-*`;禁止新增 `.container``.title``.content` 等容易跨页面冲突的泛名类。
CSS Modules 归属:
- 页面专属样式与页面就近放置,例如 `src/web/pages/projects/projects.module.css`
- 自有组件样式与组件就近放置,例如 `src/web/components/FooCard/foo-card.module.css`
- CSS Modules 中类名使用职责语义,例如 `.root``.toolbar``.summaryCard``.emptyState`;通过导入对象绑定到组件,避免字符串拼写散落。
- 同一类样式只服务当前页面或组件;一旦被多处复用,应先判断能否用 antd 组件或 props 表达,再考虑提取共享组件,而不是直接提升为全局 CSS。
- 首次实际使用 `*.module.css` 时,同步补全 TypeScript 声明和必要测试,确保类型检查与构建链路稳定。
antd 定制边界:
- 优先使用官方 props、theme token 和组件 token不要因为视觉微调直接写 CSS。
- antd v6 组件暴露 `classNames` 语义插槽时,可以把项目自有类绑定到官方稳定插槽;仍然不得选择 `.ant-*` 内部 DOM 类名。
- 避免使用 antd `styles` 语义插槽写内联样式;如果必须使用,应先评估是否可以通过 token、CSS 变量或 CSS Modules 表达。
- 弹窗、下拉、表格、菜单等复杂组件不依赖内部 DOM 结构做布局修补;发现必须修补时,优先调整组件组合或交互设计。
token 和 CSS 变量规则:
- 颜色使用 `var(--ant-color-*)`,例如文本、边框、背景和状态色。
- 间距、字号、圆角和阴影优先使用 `var(--ant-padding-*)``var(--ant-margin-*)``var(--ant-font-size-*)``var(--ant-border-radius*)``var(--ant-box-shadow*)` 等 antd 变量。
- 项目自定义 CSS 变量只能定义在 `:root` 或清晰的主题容器上,并且必须基于 antd token 派生;不要创建与 antd 平行的颜色、间距、字号体系。
- 主题切换统一通过 `ConfigProvider` theme algorithm 和 token 控制,不在 CSS 中硬编码亮色或暗色分支。
响应式规则:
- 页面必须在桌面和移动端正常加载和可读。
- 优先使用 antd `Flex``Grid``Table scroll`、响应式列配置处理布局收缩。
- 媒体查询只处理页面或自有组件的布局断点;不要用媒体查询覆盖 antd 内部结构。
- 移动端适配优先保证内容可访问、操作可点击和横向溢出可控,不追求与桌面完全一致的排版。
新增样式前检查:
1. 这个需求是否可以由 antd 组件或 props 完成?
2. 这个样式是否属于主题级统一调整,应该放到 `ConfigProvider` theme token
3. 这个样式是否只服务页面外壳,应该留在全局 CSS
4. 这个样式是否只服务单个页面或自有组件,应该使用 CSS Modules
5. 这个样式是否在覆盖 antd 内部结构?如果是,应重新设计组件组合。
6. 这个样式是否引入了硬编码色值、`style``.ant-*``!important`?如果是,不应合入。
## 表单与交互规范
- Modal + Form 提交使用 `Form onFinish` 处理业务提交,`Modal onOk` 只触发 `form.submit()`
- 不在 `Modal onOk` 中直接执行异步 `validateFields` 和提交逻辑,也不通过 lint disable 绕过该问题。
- 文本必填字段同时配置 `required: true``whitespace: true`,保持前端校验与后端 trim 后校验一致。
- 提交中状态传给 antd 组件的 loading/confirmLoading 等 props避免自行实现重复状态样式。
- 操作确认优先使用 `Popconfirm`,成功/失败反馈优先使用 antd message。
## 运行时外壳规范
前端提供两个入口外壳,共享通用 Console Shell 组件:
- **Admin管理台**`src/web/consoles/admin/AdminConsoleLayout.tsx`,菜单配置在 `menu.tsx`,路由 `/``/projects`
- **Workbench工作台**`src/web/consoles/workbench/WorkbenchProjectGate.tsx``WorkbenchConsoleLayout.tsx`,菜单配置和路由构造在 `routes.ts`,路由 `/workbench/:projectId`
通用 Console Shell`src/web/components/ConsoleShell/ConsoleShell.tsx`)包含 Layout、Header、Sider、Content、主题切换、版本展示和侧边栏折叠状态由 Admin 和 Workbench 复用。Header 显示品牌名、版本号和控制台标题Admin 显示"管理台"Workbench 显示"工作台 · 项目名")。
Sidebar`src/web/components/Sidebar/index.tsx`)是纯展示/导航组件,通过 `menuItems` props 接收菜单配置由调用方决定菜单内容和路径。Admin 传入静态路径 `/``/projects`Workbench 通过 route builder`buildWorkbenchPath`)将相对菜单路径拼成 `/workbench/:projectId` 的子路径。
Workbench 项目上下文通过 `ProjectContext` 提供,在 `WorkbenchProjectGate` 中从 URL path param 读取 `projectId`,通过 `useProject(projectId)` 加载项目,仅 active 项目渲染工作台布局,不存在或 archived 项目显示"项目不存在或不可访问"。
- 生产入口必须启用 `ErrorBoundary`,运行时渲染异常使用 antd `Result status="500"` 或等价组件展示。
- `ReactQueryDevtools` 仅在 `import.meta.env.DEV` 条件下渲染,不进入生产渲染路径。
- 主题切换统一通过 `ConfigProvider` 的 antd theme algorithm 控制,不使用硬编码主题色。
## TanStack Query 规范
- Query key 使用 structured array使用 as const 保持字面量类型
- 全局面板级查询可持续刷新,详情级查询必须按状态条件启用
- 多处页面使用同一后端资源时,应提取共享 hook避免重复定义 fetch 函数。
## fetch 封装
统一使用 fetch不引入 axios。错误抛异常由 TanStack Query 的 error 状态承接。
前后端共享的请求和响应类型定义在 src/shared/api.ts。前端 fetch 函数的返回类型必须匹配后端真实 JSON 形状;如果后端返回包装对象,例如 `{ project: Project }`,应声明对应响应类型并在 hook 内提取业务对象。
## 前端测试
- 测试目录为 tests/web/,结构对应 src/web/
- 单元测试重点覆盖 utils/ 和 hooks 中的纯逻辑
- 组件测试使用 jsdom 和 @testing-library/react
- 测试用户行为而非实现细节
- 只 mock 系统边界,使用真实的 QueryClientProvider 包裹组件
- 组件测试环境由 tests/setup.ts 和 bunfig.toml preload 提供
- 断言优先基于用户可见文本、role、按钮和交互结果不依赖 `.ant-*` 内部类名。
- 对 antd 组件只断言本项目传入的可观察行为或配置结果,避免把 antd 内部 DOM 结构当作稳定契约。
## 更新触发条件
修改前端技术栈、组件边界、数据流、样式规则、测试环境或前端验证方式时,必须更新本文档。