Files
hms/docs/superpowers/specs/2026-05-01-action-inbox-design.md
iven c208dcc6f5 docs(specs): 7 份设计规格 — 工作台/适老化/硬编码清理/项目分析
新增: 适老化小程序/Action Inbox/统一工作台/医生操作台/
硬编码清理/健康管理台/全项目深度分析报告
2026-05-03 19:32:25 +08:00

15 KiB
Raw Blame History

行动收件箱与上下文线程设计规格

日期: 2026-05-01 | 状态: Draft | 关联: erp-health, erp-ai, Web 前端, 小程序

1. 背景与问题

1.1 问题陈述

HMS 平台功能完善328 路由、25 事件类型、97.5% 测试通过率),但用户体验存在系统性流程断裂

  • 告警 → 行动断裂:医生看到告警后,无直接路径跳到查看患者→安排随访→记录处置
  • 数据录入 → 反馈断裂:患者录入体征后无即时趋势对比和行动建议
  • AI 建议 → 执行追踪断裂:审批通过后,后续执行/追踪/结果反馈在 UI 上不可见

根因:前端交互模型是"功能陈列式"的——每个功能是死胡同,没有出口指向下一步。

1.2 设计目标

建立统一的行动收件箱 + 上下文线程机制,让每个"终点"变成"起点"

  1. 用户登录后第一眼看到待处理事项(按优先级排列)
  2. 每个待办有清晰的时间线展示完整生命周期
  3. 时间线每一步都可直接跳转到对应功能页
  4. 操作按钮根据当前状态动态变化
  5. 架构可扩展——新增行动类型(告警/随访/异常)只需注册聚合器

1.3 范围

Phase 1本次AI 建议闭环 — 后端已完整实现10 次提交),补齐前端体验 Future:告警处理闭环、体征反馈闭环、随访到期提醒


2. 设计概览

事件源 → 行动收件箱服务 → 前端展示
                                    ├── Web: 顶栏铃铛 → 列表页 → Drawer
                                    └── 小程序: "待办" Tab → 列表 → 半屏弹窗

核心抽象ActionItem — 统一的待办数据结构,不同类型共用相同接口 核心交互Context Thread — Drawer/半屏弹窗中的时间线,展示完整处理进度


3. 数据模型

3.1 ActionItem聚合视图不建新表

interface ActionItem {
  id: string;                              // 格式: "{type}:{source_id}"
  type: "ai_suggestion" | "alert" | "followup" | "data_anomaly";
  priority: "urgent" | "high" | "medium" | "low";
  status: "pending" | "in_progress" | "completed" | "dismissed";
  title: string;
  summary: string;
  patient_id: string;
  patient_name: string;
  source_ref: string;                      // 指向原始实体 ID
  created_at: string;
  updated_at: string;
}

3.2 ThreadEvent上下文线程事件

interface ThreadEvent {
  step: string;              // "ai_analysis" | "doctor_approval" | "followup_scheduled" | "followup_completed" | "reanalysis"
  label: string;             // 展示文本
  status: "completed" | "in_progress" | "pending";
  detail?: string;           // 补充说明
  timestamp?: string;        // 完成时间
  operator?: string;         // 操作人
  link_to?: string;          // 跳转路径
}

3.3 ActionDefinition可用操作

interface ActionDefinition {
  key: string;               // "approve" | "reject" | "complete_early" | "acknowledge"
  label: string;             // 按钮文本
  variant: "primary" | "danger" | "default";
  confirm_message?: string;  // 确认弹窗文案
  api_endpoint: string;      // 调用的 API
}

4. 后端 API 设计

4.1 GET /api/v1/action-inbox

获取当前用户的行动收件箱列表。

Query Params:

  • status: pending | in_progress | completed | dismissed(可选,默认全部)
  • type: ai_suggestion | alert | followup | data_anomaly(可选,默认全部)
  • page / page_size: 分页(默认 1/20

Response: PaginatedResponse<ActionItem>

实现策略聚合查询不建新表。Phase 1 只查 ai_suggestion 表:

-- 注意patient_id 在 ai_analysis 表上,不在 ai_suggestion 上,需三表 JOIN
SELECT s.id, s.suggestion_type, s.risk_level, s.status, s.params,
       s.created_at, s.updated_at,
       p.name as patient_name, a.patient_id,
       a.result_content, a.analysis_type
FROM ai_suggestion s
JOIN ai_analysis a ON s.analysis_id = a.id
JOIN patient p ON a.patient_id = p.id
WHERE s.tenant_id = $1
  AND s.deleted_at IS NULL
ORDER BY
  CASE s.risk_level WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END,
  s.created_at DESC

4.2 GET /api/v1/action-inbox/:source_ref/thread

获取某个行动项的上下文线程。

Response:

interface ThreadResponse {
  action_item: ActionItem;
  thread: ThreadEvent[];
  available_actions: ActionDefinition[];
}

线程拼装逻辑(以 AI 建议为例):

步骤 数据来源 状态判断
AI 分析完成 ai_analysis.status = 'completed' 始终 completed
医生审批 ai_suggestion.status Approved→completed, Pending→in_progress
执行安排 ai_suggestion.workflow_instance_id IS NOT NULL 有值→completed
等待随访 follow_up 关联查询 根据随访状态判断
再分析对比 ai_suggestion.reanalysis_id IS NOT NULL 有值→completed

操作按钮动态生成

建议状态 可用操作
Pending 批准(→ POST /ai/suggestions/:id/approve)、拒绝
Approved/执行中 提前完成随访、标记已知悉
Executed 查看前后对比报告
Expired/Rejected/ParseFailed 无操作(只读展示)
Executed 查看前后对比报告
Expired 无操作

4.3 代码归属与权限码

代码位置

  • ActionInboxServicecrates/erp-health/src/service/action_inbox_service.rserp-health crate
  • ActionInboxHandlercrates/erp-health/src/handler/action_inbox_handler.rs
  • 路由注册:在 erp-health 模块的 protected_routes() 中新增
  • 跨 crate 查询:通过 raw SQL 直接查 ai_suggestion + ai_analysis 表(与现有 ai_suggestion_loader.rs 模式一致erp-health 已有跨 crate 读 ai 表的先例)

权限码:新增独立权限码,注册在 erp-health 模块的 permissions() 中:

  • health.action_inbox.list — 查看行动收件箱
  • health.action_inbox.manage — 执行操作(审批/拒绝/标记已知悉)

理由:action-inbox 是聚合端点,未来包含告警/随访/异常等多种类型,不应绑定到 ai.suggestion.* 权限。用 health. 前缀与 erp-health crate 归属一致。

用户范围

  • Phase 1AI 建议):返回当前租户下所有有权限查看的待办(ai_suggestionassigned_to 字段)
  • Future告警/随访):告警有 assigned_to 关联的负责医生,随访有 assigned_to 字段,届时 API 增加 scope 参数(all | mine

5. Web 前端设计

5.1 入口改造NotificationPanel 扩展

现有apps/web/src/components/NotificationPanel.tsx(铃铛 + PopoverSSE 推送消息/告警)

改造

  • Popover 中增加"待办"区域,显示最近 3 条 ActionItem
  • 底部增加"查看全部待办"链接,跳转到 /action-inbox 页面
  • 角标数字改为:未读消息数 + 待处理 ActionItem 数

5.2 新增页面ActionInboxPage

路由/action-inbox

组件apps/web/src/pages/ActionInboxPage.tsx

布局

  • 顶部:筛选栏(状态 Tab + 类型下拉)
  • 主体Ant Design List 组件,每项显示:
    • 类型标签(颜色区分)
    • 标题 + 患者姓名
    • 优先级标记
    • 创建时间
    • 点击 → 打开 Drawer

5.3 新增组件ActionThreadDrawer

组件apps/web/src/components/ActionThreadDrawer.tsx

实现Ant Design Drawer + Ant Design Steps/Timeline

结构

Drawer (width 480px)
├── 头部:标题 + 患者摘要卡(年龄/最近体征/关键指标)
├── 时间线Ant Design Timeline 组件
│   ├── 每个节点:状态图标 + 文本 + 时间 + 跳转链接
│   └── 当前步骤高亮,未来步骤灰色
├── 关联信息:可点击跳转的快捷链接
└── 操作区:动态按钮组

状态设计

  • 加载中Ant Design Skeleton3 行卡片骨架屏)
  • 数据获取失败Ant Design Result + 重试按钮
  • 空列表:插图 + "暂无待办事项"文案
  • 操作按钮请求中:按钮 loading 状态 + 禁用

5.4 实时更新策略

Phase 1轮询用户手动刷新或切换页面时重新拉取列表。Drawer 打开时,操作按钮点击后主动调用 GET /action-inbox/:id/thread 刷新时间线。

Phase 2SSE 优化):复用 apps/web/src/stores/message.ts 中的 SSE 连接。后端在建议状态变更时,通过事件总线发布 → 消息服务推送到 SSE 流。前端监听 suggestion.status_changed 事件,触发列表/Drawer 刷新。

Phase 1 选择轮询的理由:现有 SSE 只推送 messagealert 两种类型,新增 suggestion 事件需要后端消息服务改造,且 Phase 1 的使用场景(医生不频繁审批)对实时性要求不高。


6. 小程序设计

6.1 TabBar 改造

当前:首页 | 健康 | 消息 | 我的4 Tab :首页 | 健康 | 待办 | 消息 | 我的5 Tab

  • 在"健康"和"消息"之间插入"待办"Tab
  • Tab 图标:todo-listcheck-circle
  • 角标显示待处理数量(调用 GET /action-inbox?status=pending 获取计数)
  • 修改文件:apps/miniprogram/src/app.config.ts

6.2 新增页面:待办列表

路径apps/miniprogram/src/pages/action-inbox/index.tsx

布局

  • 顶部:状态筛选 Tab全部 | 待处理 | 进行中 | 已完成)
  • 列表:按优先级排序的待办卡片
  • 每张卡片:类型标签 + 标题 + 患者名 + 时间 + 箭头
  • 点击卡片 → 弹出半屏弹窗

6.3 新增组件ActionHalfScreenDialog

使用 Taro half-screen-dialog 组件或自定义半屏弹窗:

半屏弹窗
├── 头部:拖拽条 + 类型标签 + 标题
├── 摘要:关键信息(患者/风险等级/时间)
├── 时间线:简化版(只显示已完成和当前步骤)
├── 操作按钮
└── 底部:跳转详情链接

6.4 Service 层

文件apps/miniprogram/src/services/action-inbox.ts

// 复用现有 listPendingSuggestions()
// 新增:
listActionItems(params: { status?: string; type?: string; page: number })
   GET /api/v1/action-inbox

getActionThread(sourceRef: string)
   GET /api/v1/action-inbox/:source_ref/thread

7. 数据映射详细规则

7.1 AI 建议 → ActionItem 映射

ActionItem 字段 映射来源 规则
id "ai_suggestion:" + ai_suggestion.id 类型前缀 + 原 ID
type 固定 "ai_suggestion"
priority ai_suggestion.risk_level High→urgent, Medium→high, Low→medium
status ai_suggestion.status Pending→pending, Approved→in_progress, Executed→completed, Expired/Rejected/ParseFailed→dismissed
title suggestion_type + risk_level 拼接模板 suggestion_type=Followup → "建议安排随访"suggestion_type=Alert → "建议关注指标异常";从 params JSON 提取 reason 字段作为补充(若存在)
summary ai_analysis.result_content 截取前 100 字符
patient_id ai_analysis.patient_id(通过 analysis_id JOIN 三表 JOIN
patient_name patient.name JOIN 查询
source_ref ai_suggestion.id 原始 ID

7.2 线程步骤映射

ThreadEvent.step 触发条件 数据来源
ai_analysis 始终存在 ai_analysis
doctor_approval suggestion.status ∈ {Approved, Rejected} suggestion.updated_at 作为近似审批时间(无专用 approved_at 字段)
followup_scheduled workflow_instance_id IS NOT NULL workflow_instance 表。注意:action_dispatched 步骤已合并到此处——ai_action_dispatcher 是事件消费者,不回写时间戳到 ai_suggestion,其效果体现为 workflow_instance_id 被设置
followup_completed follow_up.status = completed follow_up
reanalysis reanalysis_id IS NOT NULL ai_analysis (reanalysis) 表

8. 实施分阶段

Phase 1A后端 API2-3 天)

  • 创建 ActionInboxServicecrates/erp-health/src/service/action_inbox_service.rs
  • 创建 ActionInboxHandlercrates/erp-health/src/handler/action_inbox_handler.rs
  • 在 erp-health protected_routes() 中注册 2 个新路由
  • 实现三表 JOIN 聚合查询(ai_suggestion + ai_analysis + patient
  • 实现线程拼装逻辑(合并 action_dispatchedfollowup_scheduled 步骤)
  • 实现操作按钮动态生成
  • 在 erp-health permissions() 中注册 health.action_inbox.list / health.action_inbox.manage

Phase 1BWeb 前端2-3 天)

  • 扩展 NotificationPanel,增加待办区域
  • 创建 ActionInboxPage 路由页面
  • 创建 ActionThreadDrawer 组件
  • SSE 实时更新集成
  • 路由注册 + 菜单入口

Phase 1C小程序2-3 天)

  • TabBar 改造4 Tab → 5 Tab在"健康"和"消息"间插入"待办"
  • 创建待办列表页面
  • 创建半屏弹窗组件
  • Service 层对接

Phase 1D验证与收尾1 天)

  • 三端联调测试
  • 更新 wiki 文档
  • 提交并推送

9. 验证方案

9.1 后端验证

# 1. 启动后端
cd crates/erp-server && cargo run

# 2. 创建 AI 分析 → 产生建议
# 3. 调用 API 验证
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/v1/action-inbox

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/v1/action-inbox/ai_suggestion:{id}/thread

9.2 Web 验证

  1. 登录 → 顶栏铃铛应显示待办数量
  2. 点击铃铛 → Popover 显示最近待办
  3. "查看全部" → 进入 ActionInboxPage
  4. 点击待办项 → Drawer 打开,时间线正确
  5. 点击"批准" → 状态变更,时间线更新
  6. SSE 推送 → Drawer 实时更新

9.3 小程序验证

  1. 底部 TabBar 显示"待办"Tab + 角标
  2. 进入待办页 → 列表正确
  3. 点击卡片 → 半屏弹窗弹出
  4. 操作后 → 状态更新,列表刷新

10. 未来扩展

新增行动类型只需:

  1. ActionInboxService 中注册新的聚合查询器
  2. 定义 type → ActionItem 的映射规则
  3. 定义线程步骤模板
  4. 前端自动渲染(共用相同组件)

规划中的扩展类型

  • alert — 告警处理闭环(告警→评估→处置→追踪)
  • followup — 随访到期提醒(到期→执行→记录→再分析)
  • data_anomaly — 体征异常反馈(异常→趋势对比→建议→操作)