Files
hms/wiki/frontend.md
iven 3d787adceb
Some checks failed
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
docs(wiki): 更新 frontend.md Phase 3 列表页迁移记录
2026-04-28 08:18:26 +08:00

266 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.
---
title: Web 前端
updated: 2026-04-28
status: stable
tags: [frontend, react, antd, vite, spa]
---
# Web 前端
> 从 [[index]] 导航。关联: [[erp-server]] [[infrastructure]] [[erp-health]]
## 1. 设计决策
- **组件库优先** — Ant Design 6不自造轮子
- **状态集中** — Zustand 管理全局状态4 个 store
- **API 层分离** — HTTP 调用封装到 `src/api/`28 个文件),组件不直接 fetch
- **代理开发** — Vite 代理 `/api` 到后端 3000 端口
- **HashRouter** — 不需要服务端 fallback 配置,部署更稳健
- **懒加载** — 除 Login 外所有页面使用 `lazy()` 按需加载
### 版本(以实际 package.json 为准)
React 19.2.4 / Ant Design 6.3.5 / React Router 7.14.0 / Zustand 5.0.12 / Vite 8.0.4 / TypeScript 6.0.2
## 2. UI 规范
### SaaS 后台布局
经典 SaaS 后台管理布局(响应式,支持移动端):
```text
┌─────────────────────────────────────────────┐
│ LOGO 搜索... 🔔 5 👤 Admin ▾ │ ← 顶部导航栏
├─────────┬───────────────────────────────────┤
│ 📊 首页 │ │
│ 👥 用户 │ 主内容区域 │
│ 🔐 权限 │ (多标签页切换) │
│ 📋 流程 │ │
│ 💬 消息 │ │
│ ⚙️ 设置 │ │
│─────────│ │
│ 📦 进销存│ │
│ 🏭 生产 │ │
│ 💰 财务 │ │
│─────────│ │
│ ▸ 更多 │ │
└─────────┴───────────────────────────────────┘
```
### UI 规则
- 使用 Ant Design 组件库,不自造轮子
- 中文优先,所有文案通过 i18n key 引用
- 支持 4 套主题切换:信任蓝 / 温润东方 / 深邃夜色 / 翡翠清雅
- 侧边栏按模块分组:基础模块 / 行业模块
- 表单验证使用 Ant Design Form 的 validateRules
### 2.1 多主题系统4 套内置主题)
> 自 2026-04-28 起采用多主题架构。用户可在顶栏主题切换器中选择偏好主题,选择持久化到 localStorage。
#### 4 套主题视觉人格
| 主题 | 主色 | 背景 | 圆角 | 性格 |
|------|------|------|------|------|
| **信任蓝** (blue) | `#2563EB` | `#F8FAFC` 冷灰 | 10/12/6px | 专业·企业 |
| **温润东方** (warm) | `#C4623A` | `#F5F0EB` 暖米 | 12/16/8px | 温润·人文 |
| **深邃夜色** (dark) | `#60A5FA` | `#0F172A` 深蓝黑 | 10/12/6px | 护眼·专注 |
| **翡翠清雅** (emerald) | `#5B7A5E` | `#F4F7F4` 浅绿灰 | 10/14/8px | 清新·健康 |
#### 技术架构
- **CSS 变量层** — `:root` 默认为 blue`[data-theme='xxx']` 覆盖全部视觉 token`apps/web/src/index.css`
- **Ant Design 动态主题** — `ConfigProvider``theme` prop 按 ThemeName 选择不同配置(`apps/web/src/App.tsx`
- **Zustand 持久化** — `useAppStore().theme` + `localStorage('hms-theme')``apps/web/src/stores/app.ts`
- **暗色检测** — `useThemeMode()` hook 从 store 读取,不再比对色值(`apps/web/src/hooks/useThemeMode.ts`
#### 温润东方风详细 Token与小程序端共享
> 小程序端源文件:`apps/miniprogram/src/styles/variables.scss` + `mixins.scss`
| 角色 | CSS 变量 | 色值 |
|------|----------|------|
| 主色 | `--erp-primary` | `#C4623A` |
| 背景 | `--erp-bg-page` | `#F5F0EB` |
| 容器 | `--erp-bg-container` | `#FFFFFF` |
| 主文字 | `--erp-text-primary` | `#2D2A26` |
| 次文字 | `--erp-text-secondary` | `#7A756E` |
| 边框 | `--erp-border` | `#E8E2DC` |
| 成功 | `--erp-success` | `#5B7A5E` |
| 警告 | `--erp-warning` | `#C4873A` |
| 错误 | `--erp-error` | `#B54A4A` |
#### 禁止事项
- 禁止紫色渐变、禁止 emoji 作图标
- 禁止左侧彩色边框卡片标示状态(改用 tag 标签)
- 禁止无意义的渐变背景
- 禁止装饰性 icon 遍地配
## 3. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `apps/web/src/main.tsx` | React 入口 |
| `apps/web/src/App.tsx` | 路由定义 + Ant Design 动态主题4 套) |
| `apps/web/src/layouts/MainLayout.tsx` | SaaS 后台管理布局 + ThemeSwitcher 集成 |
| `apps/web/src/stores/` | 4 个 Zustand store |
| `apps/web/src/components/ThemeSwitcher.tsx` | 主题选择下拉面板 |
| `apps/web/src/hooks/useThemeMode.ts` | 暗色模式检测(从 store 读取) |
| `apps/web/src/api/` | 28 个 API 服务文件(含 7 个健康模块 API |
| `apps/web/vite.config.ts` | Vite 配置 + API 代理 |
> 微信小程序(患者端)是独立前端项目,详见 [[miniprogram]]
### 路由结构
**公开**: `/login`
**受保护MainLayout 包裹)**:
| 路径 | 页面 |
|------|------|
| `/` | 首页 |
| `/users`, `/roles`, `/organizations` | 用户/角色/组织管理 |
| `/workflow` | 工作流 |
| `/messages` | 消息中心 |
| `/settings` | 系统设置 |
| `/plugins/admin`, `/plugins/market` | 插件管理/市场 |
| `/plugins/:pluginId/:entityName` | 插件 CRUD动态生成 |
| `/plugins/:pluginId/tabs|tree|graph|dashboard|kanban/:name` | 插件多视图页面 |
**健康管理路由22 条)**:
| 路径 | 页面 |
|------|------|
| `/health/patients` | 患者列表 |
| `/health/patients/:id` | 患者详情5 个标签页:基本信息/体征/化验/健康档案/随访) |
| `/health/patient-tags` | 患者标签管理 |
| `/health/doctors` | 医护管理 |
| `/health/schedules` | 排班管理(含日历视图) |
| `/health/appointments` | 预约管理(含状态流转) |
| `/health/follow-up-tasks` | 随访任务列表 |
| `/health/follow-up-records` | 随访记录 |
| `/health/consultations` | 咨询会话列表 |
| `/health/consultations/:id` | 咨询详情(含消息 + 导出) |
| `/health/articles` | 文章管理列表 |
| `/health/article-editor` | 文章编辑器(富文本) |
| `/health/article-categories` | 文章分类管理 |
| `/health/article-tags` | 文章标签管理 |
| `/health/points-rules` | 积分规则管理 |
| `/health/points-products` | 积分商品管理 |
| `/health/points-orders` | 积分订单列表 |
| `/health/statistics` | 统计概览(透析/化验/预约/体征上报率) |
| `/health/offline-events` | 线下活动管理 |
| `/health/ai-analysis` | AI 分析历史 |
| `/health/ai-prompts` | AI Prompt 管理 |
| `/health/ai-usage` | AI 用量统计 |
### 健康模块共享组件11 个)
| 组件 | 用途 |
|------|------|
| `StatusTag` | 预约/随访/咨询状态标签(含单元测试) |
| `PatientSelect` | 患者搜索选择器(远程搜索) |
| `DoctorSelect` | 医护搜索选择器(远程搜索) |
| `CalendarView` | 排班日历视图 |
| `ExportButton` | 咨询记录导出按钮 |
| `VitalSignsChart` | 多指标趋势图:概览卡片条(5 指标 sparkline) + 点击展开详情折线图 |
| `VitalSignsTab` | 患者详情-体征标签页 |
| `LabReportsTab` | 患者详情-化验报告标签页 |
| `HealthRecordsTab` | 患者详情-健康档案标签页 |
| `FollowUpTab` | 患者详情-随访标签页 |
| `ImagePreview` | 图片预览组件 |
### 集成契约
| 方向 | 模块 | 接口 | 触发时机 |
|------|------|------|---------|
| 调用 → | [[erp-server]] | `/api/v1/*` REST | 所有数据操作 |
| 调用 → | [[erp-server]] | `ws://localhost:3000/ws/*` | WebSocket |
| 消费 ← | 插件系统 | `plugin.toml` schema | 动态生成插件页面 |
| 调用 → | [[erp-health]] | `/api/v1/health/*` | 健康模块所有数据操作 |
## 4. 代码逻辑
### 状态管理4 个 Zustand Store
| Store | 状态 |
|-------|------|
| `app.ts` | theme(blue/warm/dark/emerald), sidebarCollapsed, localStorage 持久化 |
| `auth.ts` | user, isAuthenticated, localStorage 持久化 |
| `message.ts` | unreadCount, recentMessages, 请求去重 |
| `plugin.ts` | plugins 列表, 动态菜单, schema 缓存, 请求去重 |
### 健康模块 API 文件7 个)
| 文件 | 覆盖端点 |
|------|---------|
| `patients.ts` | 患者 CRUD + 标签 + 健康摘要 + 家庭成员 |
| `doctors.ts` | 医护档案 CRUD |
| `appointments.ts` | 预约 CRUD + 状态流转 |
| `healthData.ts` | 体征/化验/健康档案/趋势 |
| `followUp.ts` | 随访任务 + 记录 |
| `consultations.ts` | 咨询会话 + 消息 + 导出 |
| `articles.ts` | 健康文章 |
### 前端单元测试3 个)
| 文件 | 测试内容 |
|------|---------|
| `constants/health.test.ts` | 健康常量定义验证 |
| `hooks/useThemeMode.test.ts` | 暗色模式 hook |
| `pages/health/components/StatusTag.test.tsx` | 状态标签渲染 |
### 插件页面系统
插件通过 `plugin.toml` schema 声明页面,前端根据 schema 动态生成:
- `PluginCRUDPage` — 标准列表+表单
- `PluginTabsPage` — 标签页切换
- `PluginTreePage` — 树形展示
- `PluginGraphPage` — 关系图谱
- `PluginKanbanPage` — 看板视图
- `PluginDashboardPage` — 仪表盘
**不变量**: 插件菜单由 `plugin.ts` store 从 API 动态获取,不硬编码
**不变量**: API client 在请求前 30s 检查 token 过期,提前刷新避免 401
**不变量**: DatePicker 返回 dayjs 对象,提交前必须 `.format('YYYY-MM-DD')` 转字符串
### 代理配置
```
http://localhost:5174/api/* → http://localhost:3000/* (API)
ws://localhost:5174/ws/* → ws://localhost:3000/* (WebSocket)
```
## 5. 活跃问题 + 陷阱
⚠️ Ant Design 6 废弃 `destroyOnClose`,应使用 `destroyOnHidden`
⚠️ Ant Design 6 废弃 API 警告(`valueStyle`/`Spin tip`/`trailColor`)已在历史版本中修复
⚠️ `antd.setScaleParam` 强制回流 64ms — antd 内部问题,无法直接修复
### 历史教训
- DatePicker 提交 dayjs 对象而非字符串 → 后端 422 `birth_date trailing input` — 必须调用 `.format('YYYY-MM-DD')`
- 预约表单医护字段标为可选但后端必填 → 400 `doctor_id is required` — 医护为必填CAS 排班需要)
- 趋势图后端 DTO `Vec<(NaiveDate, f64)>` 序列化为 JSON 数组 `[[date, value]]` 而非对象 `[{date, value}]` → 改用 `Vec<DataPoint>` 修复;前端 `extractData` 需同时处理 `ApiResponse` 包装和裸数组两种响应格式
- `IndicatorTimeseriesResp` 返回 `{ indicator, data: [...] }` 包装对象,不是裸数组 — `Array.isArray(res)` 为 false必须从 `res.data` 取值
## 6. 变更记录
| 日期 | 变更 |
|------|------|
| 2026-04-28 | UI/UX 重构 Phase 310 个列表页统一迁移至 PageContainer + usePaginatedData + EntityName + 共享格式化工具,移除手动 isDark 处理 |
| 2026-04-28 | UI/UX 重构 Phase 2仪表盘角色自适应useDashboardRole + DoctorDashboard/NurseDashboard/AdminDashboard/OperatorDashboard删除快捷入口/积分排行/最近活动旧区块 |
| 2026-04-28 | UI/UX 重构 Phase 1提取 6 个共享组件PageContainer/EntityName/FilterBar/DrawerForm/FilterBar + dayjs/format 工具12 个文件 dayjs 导入统一 |
| 2026-04-28 | 多主题系统4 套主题blue/warm/dark/emerald+ CSS 变量 + Ant Design 动态主题 + ThemeSwitcher + useThemeMode 修复 |
| 2026-04-26 | 全面更新22 条健康路由(+12 内容/积分/统计/活动/AI、11 个共享组件、77 个 TSX 文件 |
| 2026-04-26 | 从 CLAUDE.md 迁移UI 布局规范§8 |
| 2026-04-26 | VitalSignsChart 重设计:概览卡片条 + 点击展开详情图5 指标独立 Y 轴 |
| 2026-04-25 | 全面更新10 条健康路由、12 个共享组件、7 个健康 API 文件、3 个单元测试 |
| 2026-04-24 | 添加小程序交叉引用 |
| 2026-04-23 | 重构为 5 节结构,更新为当前完整前端状态 |