新增: - AlertList 告警列表页: 状态筛选/确认/忽略操作 - AlertRuleList 告警规则页: 创建/编辑/启停管理 - alerts + deviceReadings 前端 API 层 - App.tsx 路由注册 + MainLayout 标题 fallback - wiki/frontend.md 更新页面清单 修复: - ArticleEditor: 修复 unused variable 构建错误 - FollowUpTaskList: 修复 filter(Boolean) 类型窄化问题
217 lines
9.1 KiB
Markdown
217 lines
9.1 KiB
Markdown
---
|
||
title: Web 前端
|
||
updated: 2026-04-26
|
||
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 引用
|
||
- 支持暗色/亮色主题切换
|
||
- 侧边栏按模块分组:基础模块 / 行业模块
|
||
- 表单验证使用 Ant Design Form 的 validateRules
|
||
|
||
## 3. 关键文件 + 数据流
|
||
|
||
### 核心文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `apps/web/src/main.tsx` | React 入口 |
|
||
| `apps/web/src/App.tsx` | 路由定义(公开 + 受保护) |
|
||
| `apps/web/src/layouts/MainLayout.tsx` | SaaS 后台管理布局 |
|
||
| `apps/web/src/stores/` | 4 个 Zustand 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(light/dark), sidebarCollapsed |
|
||
| `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-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 节结构,更新为当前完整前端状态 |
|