From d22ad6088a7144eed2da423349b190b0eaecfbf5 Mon Sep 17 00:00:00 2001 From: iven Date: Sat, 25 Apr 2026 20:22:24 +0800 Subject: [PATCH] =?UTF-8?q?docs(wiki+spec):=20=E9=A1=B9=E7=9B=AE=E5=85=A8?= =?UTF-8?q?=E6=99=AF=E5=88=86=E6=9E=90=20+=20=E5=8A=9F=E8=83=BD=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E8=AE=BE=E8=AE=A1=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 wiki/erp-ai.md (AI 模块知识库页面) - 修正 wiki/index.md 数据不一致 (crate 数 16、迁移 55、模块含 ai) - 更新 wiki/erp-server.md (7 模块注册) - 新增功能完善设计规格 (按钮权限 + AI 3 页面 + 小程序报告) --- .../2026-04-25-feature-completion-design.md | 299 ++++++++++++++++++ wiki/erp-ai.md | 143 +++++++++ wiki/erp-server.md | 5 +- wiki/index.md | 21 +- 4 files changed, 457 insertions(+), 11 deletions(-) create mode 100644 docs/superpowers/specs/2026-04-25-feature-completion-design.md create mode 100644 wiki/erp-ai.md diff --git a/docs/superpowers/specs/2026-04-25-feature-completion-design.md b/docs/superpowers/specs/2026-04-25-feature-completion-design.md new file mode 100644 index 0000000..e23d212 --- /dev/null +++ b/docs/superpowers/specs/2026-04-25-feature-completion-design.md @@ -0,0 +1,299 @@ +# HMS 功能完善迭代设计规格 + +> 日期: 2026-04-25 +> 状态: 已确认 +> 关联: `docs/superpowers/specs/2026-04-25-erp-ai-module-design.md` + +## 1. 背景与目标 + +### 1.1 项目现状 + +HMS 健康管理平台已完成核心业务开发(237 次提交、57k 行 Rust + 174 前端文件),但存在以下功能缺口: + +- **按钮级权限控制缺失** — 路由守卫已有,但操作按钮(新增/编辑/删除)未做权限过滤 +- **AI 模块管理端空白** — 后端 6 个 API 端点已实现,但前端无管理页面 +- **小程序端 AI 不可见** — 患者无法查看 AI 分析报告 + +### 1.2 目标 + +通过纵向切片方式逐步交付三个功能域,每个切片从前到后完整打通: + +1. **切片 1:按钮级权限** — 基础设施,后续页面的前置依赖 +2. **切片 2:AI 管理端** — 3 个 PC 管理页面 +3. **切片 3:小程序报告** — 患者端只读查看 + +--- + +## 2. 切片 1:按钮级权限控制 + +### 2.1 架构 + +``` +auth store (permissions: string[]) + ↓ +usePermission(code) → { hasPermission: boolean } + ↓ + ... + ↓ +无权限 → 不渲染(hidden 模式) +有权限 → 正常渲染子元素 +``` + +### 2.2 组件设计 + +**usePermission hook** + +位置: `apps/web/src/hooks/usePermission.ts` + +```typescript +function usePermission(code: string): { hasPermission: boolean } +``` + +- 从 auth store 读取当前用户 permissions 数组 +- 返回 code 是否在权限列表中 + +**AuthButton 组件** + +位置: `packages/ui-components/src/AuthButton.tsx` + +Props: +- `code: string` — 权限码(如 `health.patient.manage`) +- `children: ReactNode` — 受保护的按钮内容 + +行为: 无权限时不渲染 children(hidden 模式)。 + +**AuthGuard 组件** + +位置: `packages/ui-components/src/AuthGuard.tsx` + +Props: +- `code: string` — 权限码 +- `children: ReactNode` — 受保护的内容块 + +行为: 同 AuthButton,用于包裹非按钮内容(如整个 Tab、区块)。 + +### 2.3 改造范围 + +优先改造健康模块 15 个页面中的操作按钮: + +| 页面 | 按钮权限码 | +|------|-----------| +| PatientList | health.patient.manage | +| PatientDetail | health.patient.manage | +| AppointmentList | health.appointment.manage | +| DoctorList | health.doctor.manage | +| DoctorSchedule | health.doctor.manage | +| FollowUpTaskList | health.follow-up.manage | +| FollowUpRecordList | health.follow-up.manage | +| ConsultationList | health.consultation.manage | +| ConsultationDetail | health.consultation.manage | +| OfflineEventList | health.articles.manage | +| PatientTagManage | health.patient.manage | +| StatisticsDashboard | health.health-data.list (只读) | +| PointsProductList | health.articles.manage | +| PointsOrderList | health.articles.list | +| PointsRuleList | health.articles.manage | + +扩展到基础模块页面(Users, Roles, Organizations, Workflow 等)。 + +### 2.4 验证标准 + +- [ ] 无权限用户看不到操作按钮 +- [ ] 有权限用户操作正常 +- [ ] 权限变更后界面实时更新(无需刷新) + +--- + +## 3. 切片 2:AI 管理端 3 页面 + +### 3.1 路由设计 + +``` +/health/ai/prompts → Prompt 管理 +/health/ai/analysis → 分析历史 +/health/ai/usage → 用量统计 +``` + +### 3.2 页面 A — Prompt 管理 + +位置: `apps/web/src/pages/health/AiPromptList.tsx` + +**功能清单:** + +| 功能 | 说明 | +|------|------| +| 列表展示 | 表格:名称/类型(化验单解读、趋势分析、体检方案、报告摘要)/版本号/状态(active/draft)/更新时间 | +| 新建 Prompt | Modal 表单:名称、类型(下拉)、系统提示词、用户提示词模板(支持 `{{variable}}` 占位符) | +| 编辑 Prompt | 同新建,自动递增版本号 | +| 激活/停用 | 切换按钮,激活时停用同类型旧模板 | +| 版本历史 | 展开行显示所有历史版本,支持一键回滚 | + +**API 封装:** + +位置: `apps/web/src/api/ai/prompts.ts` + +```typescript +// 对应后端已有的 ai_prompt 实体 CRUD +getPrompts(params: ListParams): Promise> +createPrompt(data: CreatePromptDto): Promise +updatePrompt(id: string, data: UpdatePromptDto): Promise +activatePrompt(id: string): Promise +rollbackPrompt(id: string): Promise +``` + +**权限码:** `ai.prompt.list`(查看)、`ai.prompt.manage`(编辑/激活/回滚) + +### 3.3 页面 B — 分析历史 + +位置: `apps/web/src/pages/health/AiAnalysisList.tsx` + +**功能清单:** + +| 功能 | 说明 | +|------|------| +| 列表展示 | 表格:分析类型/患者姓名/状态(streaming/completed/failed)/创建时间/token 用量 | +| 详情查看 | 点击行展开/Modal 展示完整分析结果(Markdown 渲染) | +| 筛选 | 按类型(4 种)、时间范围(DateRangePicker)、患者(PatientSelect 组件复用) | +| 重新分析 | 对 failed 记录支持重新发起分析 | + +**API 封装:** + +位置: `apps/web/src/api/ai/analysis.ts` + +```typescript +getAnalysisHistory(params: AnalysisQueryParams): Promise> +getAnalysisDetail(id: string): Promise +``` + +**权限码:** `ai.analysis.list`(查看)、`ai.analysis.manage`(重新分析) + +### 3.4 页面 C — 用量统计 + +位置: `apps/web/src/pages/health/AiUsageDashboard.tsx` + +**功能清单:** + +| 功能 | 说明 | +|------|------| +| 概览卡片 | 4 张 StatCard:总用量/本月/今日/平均 token | +| 趋势图 | Ant Design Charts 折线图,按日/周/月切换 | +| 类型分布 | 饼图展示 4 种分析类型的占比 | +| 用户排行 | 表格展示用户维度用量排名 | + +**API 封装:** + +位置: `apps/web/src/api/ai/usage.ts` + +```typescript +getUsageOverview(): Promise +getUsageTrend(params: TrendParams): Promise +getUsageByType(): Promise +getUsageByUser(params: UserRankingParams): Promise> +``` + +**后端补充:** 需要在 erp-ai handler 中新增用量统计端点(当前仅有 list/get,需增加 aggregation)。 + +**权限码:** `ai.usage.list` + +### 3.5 菜单注册 + +在 `apps/web/src/layouts/MainLayout.tsx` 健康管理菜单组下新增: + +``` +健康管理 +├── 患者管理 +├── 医护管理 +├── 预约管理 +├── 随访管理 +├── 咨询管理 +├── 文章管理 +├── 积分商城 +├── 统计看板 +└── AI 分析 ← 新增 + ├── Prompt 管理 + ├── 分析历史 + └── 用量统计 +``` + +### 3.6 验证标准 + +- [ ] Prompt CRUD 全流程可用(创建/编辑/激活/回滚) +- [ ] 分析历史可筛选、可查看详情(Markdown 正确渲染) +- [ ] 用量统计图表数据正确 +- [ ] 所有操作按钮受 AuthButton 权限控制 +- [ ] 页面响应式布局正常 + +--- + +## 4. 切片 3:小程序 AI 报告查看 + +### 4.1 新增页面 + +**报告列表页** + +位置: `apps/miniprogram/src/pages/report/list.tsx` + +- 调用 `/api/v1/ai/analysis/history?patient_id={currentPatientId}` +- 列表展示分析记录(类型图标 + 时间 + 状态标签) +- 点击进入详情 + +**报告详情页** + +位置: `apps/miniprogram/src/pages/report/detail.tsx` + +- 调用 `/api/v1/ai/analysis/{id}` +- Markdown 渲染分析结果(使用 Taro rich-text 或 taro-markdown 组件) +- 底部展示分析时间和 token 用量信息 + +### 4.2 路由集成 + +在首页(`pages/index/index.tsx`)健康数据区域增加"AI 报告"入口卡片。 + +### 4.3 API 复用 + +后端端点已存在(`list_analysis` + `get_analysis`),无需新增。需确保: +- 患者只能查看自己的分析记录(通过 JWT user_id → patient_id 过滤) +- 响应数据中不含 PII + +### 4.4 验证标准 + +- [ ] 患者可查看自己的 AI 分析历史 +- [ ] 详情页 Markdown 正确渲染 +- [ ] 无法查看其他患者的报告 +- [ ] 无报告时显示空状态提示 + +--- + +## 5. 实施顺序 + +| 阶段 | 内容 | 依赖 | 预计工作量 | +|------|------|------|-----------| +| P1 | usePermission hook + AuthButton/AuthGuard 组件 | 无 | 2 文件 | +| P2 | 健康模块 15 页面按钮权限改造 | P1 | 15 文件 | +| P3 | AI API 前端封装(3 个 service 文件) | 无 | 3 文件 | +| P4 | AI Prompt 管理页面 | P1, P3 | 1 文件 | +| P5 | AI 分析历史页面 | P1, P3 | 1 文件 | +| P6 | AI 用量统计页面 + 后端聚合 API | P1, P3 | 2 文件 | +| P7 | 菜单注册 + 路由配置 | P4-P6 | 2 文件 | +| P8 | 小程序报告列表 + 详情页 | P3 | 2 文件 | +| P9 | 小程序首页入口集成 | P8 | 1 文件 | + +--- + +## 6. 非目标(明确排除) + +- 不涉及 CI/CD 流水线建设(属于安全与稳定性方向) +- 不涉及 erp-plugin unwrap 修复(属于代码质量方向) +- 不涉及 TypeScript strict 模式开启(属于质量方向,单独处理) +- 不涉及新的 AI 提供商接入(仅使用现有 Claude 提供商) +- 不涉及用量配额/计费功能(后续迭代) + +--- + +## 7. 技术约束 + +- 前端组件使用 Ant Design 6 现有组件 +- 图表使用 Ant Design Charts(项目已有依赖) +- 小程序 Markdown 渲染使用社区 taro-markdown 组件或 rich-text +- 后端新增聚合 API 遵循现有 handler/service 模式 +- 所有新页面使用 i18n key,不硬编码中文 diff --git a/wiki/erp-ai.md b/wiki/erp-ai.md new file mode 100644 index 0000000..b09cbb0 --- /dev/null +++ b/wiki/erp-ai.md @@ -0,0 +1,143 @@ +--- +title: erp-ai AI 分析模块 +updated: 2026-04-25 +status: in-development +tags: [ai, llm, sse, health-analysis, claude] +--- + +# erp-ai AI 分析模块 + +> 从 [[index]] 导航。关联: [[erp-health]] [[erp-core]] [[erp-server]] +> +> 设计规格: `docs/superpowers/specs/2026-04-25-erp-ai-module-design.md` + +## 1. 设计决策 + +### 为什么需要 AI 模块? + +健康管理平台需要为医护人员提供智能辅助分析能力:化验单解读、健康趋势分析、体检方案推荐、报告摘要生成。这些能力需要一个独立的模块来管理 AI 提供商、Prompt 模板和用量追踪。 + +### 核心架构选择 + +- **原生 Rust crate** — 与 erp-health 同级,直接调用数据库和事件总线 +- **ErpModule trait 实现** — `AiModule` 在 erp-server 注册,路由挂载到 `/api/v1/ai` +- **SSE 流式响应** — 所有分析端点使用 Server-Sent Events 实时推送 +- **多提供商支持** — AiProvider trait 抽象,当前实现 Claude (Anthropic) +- **数据脱敏** — 发送前自动移除患者 PII(姓名、身份证、手机号) + +## 2. 关键文件 + 数据流 + +### 目录结构 + +``` +crates/erp-ai/ +├── src/ +│ ├── lib.rs ← 模块导出 (AiModule, AiState, AiError) +│ ├── module.rs ← ErpModule trait 实现, 6 权限码, 路由定义 +│ ├── error.rs ← AiError → AppError (59 行) +│ ├── state.rs ← AiState { db, event_bus, provider } +│ ├── dto.rs ← 请求/响应 DTO (102 行) +│ ├── provider/ +│ │ ├── mod.rs ← AiProvider trait 定义 +│ │ └── claude.rs ← Claude SSE 流式实现 (227 行) +│ ├── service/ +│ │ ├── analysis.rs ← AnalysisService 核心编排 (183 行) +│ │ ├── prompt.rs ← PromptService 模板渲染 (67 行) +│ │ └── usage.rs ← UsageService 用量追踪 (45 行) +│ ├── handler/ +│ │ └── mod.rs ← 6 个 SSE + REST 端点 (340 行) +│ ├── prompt/ +│ │ └── mod.rs ← Prompt 模板引擎 (25 行) +│ └── entity/ +│ ├── ai_prompt.rs ← Prompt 模板 Entity +│ ├── ai_analysis.rs ← 分析结果 Entity +│ └── ai_usage.rs ← 用量日志 Entity +``` + +### 实体模型(3 个实体) + +| 实体 | 用途 | +|------|------| +| ai_prompt | Prompt 模板(版本管理、激活/回滚) | +| ai_analysis | 分析结果记录(输入参数、输出摘要、token 用量) | +| ai_usage | 用量追踪(按租户/用户聚合) | + +### 权限码(6 个) + +| 权限码 | 说明 | +|--------|------| +| `ai.analysis.list` / `ai.analysis.manage` | 查看分析历史 / 发起分析 | +| `ai.prompt.list` / `ai.prompt.manage` | 查看 Prompt / 管理 Prompt | +| `ai.usage.list` | 查看用量统计 | +| `ai.provider.manage` | 管理提供商配置 | + +### API 端点: `/api/v1/ai/` + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/ai/analyze/lab-report` | POST | 化验单智能解读(SSE) | +| `/ai/analyze/trends` | POST | 健康趋势分析(SSE) | +| `/ai/analyze/checkup-plan` | POST | 体检方案推荐(SSE) | +| `/ai/analyze/report-summary` | POST | 报告摘要生成(SSE) | +| `/ai/analysis/history` | GET | 分析历史列表 | +| `/ai/analysis/{id}` | GET | 分析结果详情 | + +### 集成契约 + +| 方向 | 模块 | 接口 | 触发时机 | +|------|------|------|---------| +| 依赖 → | [[erp-health]] | 健康数据查询 | 分析时读取患者数据 | +| 依赖 → | [[erp-core]] | EventBus, AppError | 模块注册 | +| 注册 → | [[erp-server]] | `AiModule` | 启动时注册 | + +## 3. 代码逻辑 + +### SSE 流式分析流程 + +``` +客户端 POST → handler::stream_*() + → sanitization: 移除 PII (姓名→患者, 身份证→***) + → PromptService: 加载激活模板 + 渲染变量 + → AnalysisService: 编排分析流程 + → AiProvider::stream(): 调用 LLM API + → 逐 chunk SSE 推送: data: { "content": "..." } + → AnalysisService: 保存结果到 ai_analysis + → UsageService: 记录 token 用量 + → SSE done +``` + +### 数据脱敏 + +发送给 LLM 的数据经过脱敏处理: +- 患者姓名 → "患者" +- 身份证号 → 全掩码 +- 手机号 → `138****1234` 格式 + +### 模块依赖 + +`AiModule` 声明依赖 `["health"]`,确保健康模块先于 AI 模块初始化。 + +⚡ **不变量**: 所有发送到外部 LLM 的数据必须经过 PII 脱敏 +⚡ **不变量**: SSE 连接超时必须设置,避免挂起 +⚡ **不变量**: 用量追踪必须记录,用于计费和审计 + +## 4. 活跃问题 + 陷阱 + +### 当前状态: 🔧 开发中 + +6 个 API 端点已实现,SSE 流式分析可用。当前为 Phase 1 MVP。 + +### 待完善 + +| 问题 | 级别 | 说明 | +|------|------|------| +| 管理端前端页面 | P1 | Prompt 管理、分析历史、用量统计页面 | +| 小程序端集成 | P2 | 患者端查看 AI 分析结果 | +| 更多提供商 | P2 | 接入 OpenAI、本地模型等 | +| 用量配额限制 | P1 | 按租户设置用量上限 | + +## 5. 变更记录 + +| 日期 | 变更 | +|------|------| +| 2026-04-25 | 创建 erp-ai wiki 页面 | diff --git a/wiki/erp-server.md b/wiki/erp-server.md index 4867c21..d9f6532 100644 --- a/wiki/erp-server.md +++ b/wiki/erp-server.md @@ -39,9 +39,9 @@ AppConfig::load() → 安全检查 → init_tracing → db::connect → Migrator → 构建Router → bind + serve → 优雅关闭(CTRL+C/SIGTERM) ``` -### 注册的 6 个模块 +### 注册的 7 个模块 -AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → **HealthModule** +AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → **HealthModule** → **AiModule** ### AppState @@ -69,6 +69,7 @@ AppState { | 组装 → | erp-message | `MessageModule` | 启动时注册 | | 组装 → | erp-plugin | `PluginModule` | 启动时注册 | | 组装 → | [[erp-health]] | `HealthModule` | 启动时注册 | +| 组装 → | [[erp-ai]] | `AiModule` | 启动时注册 | | 依赖 ← | [[erp-core]] | ErpModule trait, EventBus | 所有模块 | | 依赖 ← | [[infrastructure]] | PostgreSQL, Redis | 连接 | diff --git a/wiki/index.md b/wiki/index.md index 9264140..383b233 100644 --- a/wiki/index.md +++ b/wiki/index.md @@ -6,16 +6,18 @@ | 指标 | 值 | |------|-----| -| Rust crate | 15 个(7 核心 + erp-health + 6 插件 + erp-plugin-prototype) | -| 数据库表 | 30 基础表 + 18 健康业务表(已实现) | -| 数据库迁移 | 50 个 | -| 核心模块 | 5 基础 (auth/config/workflow/message/plugin) + 1 业务 (health) | -| Web 前端页面 | 30 路由(含 10 健康管理路由) | -| 健康模块组件 | 11 个共享组件(StatusTag/PatientSelect/DoctorSelect/VitalSignsChart 等) | -| 微信小程序 | Taro 4.2 + React 18,20 个页面 | +| Rust crate | 16 个(erp-core + 6 基础业务 + erp-health + erp-ai + 6 插件 + erp-plugin-prototype) | +| 数据库表 | 30 基础表 + 18 健康业务表 + 3 AI 表(已实现) | +| 数据库迁移 | 55 个 | +| 核心模块 | 5 基础 (auth/config/workflow/message/plugin) + 2 业务 (health + ai) | +| Web 前端页面 | 62 个 TSX 组件(含 15 健康管理页面) | +| 健康模块组件 | 12 个共享组件(StatusTag/PatientSelect/DoctorSelect/VitalSignsChart 等) | +| 微信小程序 | Taro 4.2 + React 18,27 个页面 | | 前端单元测试 | 3 个(vitest)+ 4 E2E spec(playwright) | | 后端测试 | 36 个(workspace)+ 57 validation 纯函数测试 | +| 总代码量 | Rust ~57k 行 + 前端 TSX/TS ~174 文件 | | API 文档 | `http://localhost:3000/api/docs/openapi.json` | +| Git 提交 | 237 次 | ## 症状导航 @@ -51,9 +53,10 @@ ### 核心业务层(HMS 专属) - [[erp-health]] — **患者管理 · 健康数据 · 预约排班 · 随访管理 · 咨询管理**(原生 Rust 模块,已实现) +- [[erp-ai]] — **AI 智能分析 · 化验单解读 · 趋势分析 · 报告摘要**(原生 Rust 模块,开发中) ### 组装层 -- [[erp-server]] — Axum 入口 · AppState · 6 模块注册 · 后台任务 · 优雅关闭 +- [[erp-server]] — Axum 入口 · AppState · 7 模块注册 · 后台任务 · 优雅关闭 ### 患者端 - [[miniprogram]] — **微信小程序** · Taro 4.2 · 微信登录 · 手机绑定 · 健康数据查看 @@ -61,7 +64,7 @@ ### 基础设施 - [[infrastructure]] — 连接信息 · 环境变量 · 一键启动 (**单一真相源**) - [[database]] — SeaORM 迁移 · 多租户表结构 -- [[frontend]] — React 19 SPA · 健康管理页面(13 页面 + 11 组件) +- [[frontend]] — React 19 SPA · 健康管理页面(15 页面 + 12 组件) - [[testing]] — 验证清单 · 测试分布 · 性能基准 ## 核心架构问答