Files
hms/docs/superpowers/specs/2026-04-23-hms-miniprogram-design.md
iven 9ef65b9a9f
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
feat(health+miniprogram): 预约/报告/随访/资讯/家庭管理 — Chunk 4-6
后端:
- 添加 articles 表迁移 + Entity + Service + Handler
- 健康数据趋势 API (get_mini_trend) 注册路由
- article CRUD (list/get) + DTO

前端 (11个新页面 + 5个服务):
- 预约挂号: 列表/创建向导/详情页
- 报告管理: 列表/详情页
- 随访管理: 任务列表/记录详情页
- 资讯文章: 文章详情页
- 个人中心: 就诊人管理/新增/我的报告/我的随访/用药提醒/设置
- 更新 app.config.ts 注册全部路由
- 更新 profile/article 页面为真实功能
2026-04-24 00:58:40 +08:00

19 KiB
Raw Permalink Blame History

HMS 患者小程序设计规格

版本: v1.0 日期: 2026-04-23 状态: 草案 关联: 健康模块设计规格 2026-04-23-health-management-module-design.md


1. 概述

1.1 产品定位

HMS 患者小程序是综合健康管理入口,面向体检中心/医疗机构的患者。覆盖体检预约、报告查询、健康数据长期监测、随访管理、家庭健康管理等场景。

医护端以 PC 管理后台(apps/web/)为主力,小程序聚焦患者体验。医护端小程序可在后续按需补一个轻量版(随访提醒、排班查看),不在本规格范围内。

1.2 核心决策

维度 决策 原因
技术选型 Taro 4 + React 19 与 Web 端 React 技能复用,支持多端编译
架构方案 直连后端 MVP 阶段最务实,复用 erp-server API
登录方式 微信授权 + 手机号补充 降低门槛 + 确保身份可靠
代码位置 apps/miniprogram/Monorepo 方便接口同步,共享类型定义
目标平台 微信小程序优先 覆盖最广泛用户,后续可扩展
数据录入 手动 + 蓝牙预留接口 MVP 快速交付,后续对接设备
视觉风格 医疗清新(青色主调) 专业可靠,沿用现有 HTML 原型风格

1.3 MVP 功能范围

MVP 包含7 个功能模块):

  1. 登录 + 个人中心
  2. 健康数据录入 + 趋势图
  3. 预约挂号
  4. 报告查询
  5. 随访管理
  6. 家庭健康管理(就诊人切换)
  7. 健康资讯 + 用药提醒

后续版本:

  • 在线咨询即时通讯WebSocket 长连接)

2. 项目结构

apps/miniprogram/
├── config/                    # Taro 编译配置
│   ├── index.ts               # 通用配置
│   ├── dev.ts                 # 开发环境
│   └── prod.ts                # 生产环境
├── project.config.json        # 微信小程序项目配置
├── src/
│   ├── app.config.ts          # Taro 全局配置TabBar、页面路由
│   ├── app.tsx                # 入口组件
│   ├── app.scss               # 全局样式(医疗清新主题变量)
│   ├── components/            # 通用组件
│   │   ├── HealthCard/        # 健康指标卡片(血压/血糖/体重)
│   │   ├── AppointmentCard/   # 预约卡片
│   │   ├── ReportItem/        # 报告列表项
│   │   ├── FamilyPicker/      # 就诊人切换器
│   │   ├── EmptyState/        # 空状态占位
│   │   └── TrendChart/        # 趋势图echarts-taro3-react
│   ├── pages/
│   │   ├── index/             # 首页(今日健康+快捷入口+待办)
│   │   ├── health/            # 健康数据(录入+趋势图)
│   │   ├── appointment/       # 预约(列表+新建预约)
│   │   ├── report/            # 报告(体检报告+化验单)
│   │   ├── followup/          # 随访(任务+问卷填写)
│   │   ├── article/           # 健康资讯(文章列表+详情)
│   │   ├── profile/           # 我的(个人信息+就诊人管理+设置)
│   │   └── login/             # 登录(微信授权+手机号)
│   ├── services/              # API 调用层
│   │   ├── request.ts         # 封装 Taro.requestJWT 注入、错误处理)
│   │   ├── auth.ts            # 登录/刷新 token
│   │   ├── health.ts          # 健康数据 CRUD
│   │   ├── appointment.ts     # 预约 CRUD
│   │   ├── report.ts          # 报告查询
│   │   ├── followup.ts        # 随访任务/记录
│   │   └── article.ts         # 资讯/科普
│   ├── stores/                # Zustand 状态管理
│   │   ├── auth.ts            # 登录态、用户信息、就诊人列表
│   │   └── health.ts          # 健康数据缓存
│   ├── utils/
│   │   ├── bluetooth.ts       # 蓝牙接口预留MVP 不实现)
│   │   ├── format.ts          # 日期/数值格式化
│   │   └── constants.ts       # 常量定义
│   └── styles/
│       ├── variables.scss     # 主题变量(青色主调)
│       └── mixins.scss        # 常用样式混入
├── package.json
└── tsconfig.json

设计原则:

  • services 层与 Web 端 apps/web/src/api/ 职责对齐,用 Taro.request 替代 fetch
  • stores 复用 Zustand 模式,与 Web 端保持一致的状态管理风格
  • 组件命名 PascalCase 目录,与 Web 端风格统一
  • MVP 阶段不强抽取 packages/shared/,等两端跑起来后根据重复度决定

3. 认证流程

3.1 整体流程

用户打开小程序
    ↓
检查本地 storage 有无有效 JWT
    ├── 有且未过期 → 直接进入首页
    └── 无或已过期 ↓

Step 1: 微信静默登录
    wx.login() → code
    → POST /api/v1/auth/wechat/login { code }
    → 后端用 code 换 openid查找绑定用户
        ├── 已绑定 → 签发 JWT { token, user }
        └── 未绑定 → 返回 { need_bind: true, openid }

Step 2: 手机号绑定(仅新用户)
    wx.getPhoneNumber 按钮组件 → encryptedData + iv
    → POST /api/v1/auth/wechat/bind-phone { openid, encryptedData, iv }
    → 后端解密手机号,创建/关联 user + patient 档案
    → 签发 JWT { token, user, patient }

Step 3: 补充档案(首次绑定后)
    → 引导填写姓名、性别、出生日期、身份证号(可选)
    → PUT /api/v1/health/patients/me { name, gender, birthday }

3.2 后端新增内容

erp-auth 新增:

新增 说明
wechat_users id, openid, union_id, user_id, phone, created_at, updated_at
POST /api/v1/auth/wechat/login code → openid 查询,返回绑定状态
POST /api/v1/auth/wechat/bind-phone 绑定手机号,创建 user + patient
GET /api/v1/auth/wechat/qrcode 生成带参数小程序码PC 端扫码登录场景)

wechat_users 表必须包含 tenant_id(多租户隔离)和标准审计字段(created_at, updated_at, deleted_at)。

3.3 Token 策略

Token 有效期 存储
Access Token (JWT) 15 分钟 内存 + Taro.setStorage
Refresh Token 7 天 Taro.setStorage

自动刷新机制:services/request.ts 拦截 401 → 调用 POST /auth/refresh → 重试原请求。刷新失败则跳转登录页。

3.4 多就诊人

  • 一个微信账号可管理多个 patient本人 + 家人)
  • 切换就诊人时请求 header 带 X-Patient-Id
  • 后端校验该 patient 属于当前 user

4. 页面结构与导航

4.1 Tab Bar

底部导航栏 5 个入口:

Tab 图标 页面路径
首页 🏠 /pages/index/index
健康 📊 /pages/health/index
预约 📅 /pages/appointment/index
资讯 📰 /pages/article/index
我的 👤 /pages/profile/index

4.2 页面层级

Tab: 首页 /pages/index
├── /pages/notifications/index          # 通知列表
└── /pages/followup/detail/index        # 随访任务详情

Tab: 健康 /pages/health
├── /pages/health/input/index           # 录入数据
├── /pages/health/trend/index           # 指标趋势
└── /pages/health/history/index         # 历史记录

Tab: 预约 /pages/appointment
├── /pages/appointment/create/index     # 新建预约
└── /pages/appointment/detail/index     # 预约详情

Tab: 资讯 /pages/article
└── /pages/article/detail/index         # 文章详情

Tab: 我的 /pages/profile
├── /pages/profile/family/index         # 就诊人管理
├── /pages/profile/family-add/index     # 添加就诊人
├── /pages/profile/reports/index        # 我的报告
├── /pages/profile/followups/index      # 我的随访
├── /pages/profile/medication/index     # 用药提醒
└── /pages/profile/settings/index       # 设置

独立页面(不在 Tab 内):
├── /pages/login/index                  # 登录
└── /pages/login/profile/index          # 档案补全

4.3 首页布局

┌─────────────────────────────┐
│  问候栏(渐变青色背景)       │  用户名 + 日期 + 通知铃铛
├─────────────────────────────┤
│  今日健康卡片(上浮 -20px   │  血压/心率/血糖/体重 2×2 网格
├─────────────────────────────┤
│  快捷服务4 宫格)           │  录数据/预约/报告/随访
├─────────────────────────────┤
│  即将到来                    │  最近 1 条预约卡片
├─────────────────────────────┤
│  待办随访                    │  最多 2 条待办 + 查看全部
├─────────────────────────────┤
│  [ 首页 ] [ 健康 ] [ 预约 ] [ 资讯 ] [ 我的 ]  │
└─────────────────────────────┘

5. 核心功能数据流

5.1 健康数据录入

选择指标类型 → 输入数值 + 测量时间 → 添加备注(可选)→ POST /vital-signs
                                                            ↓
                                                   成功 → 更新首页卡片 + 趋势缓存
                                                   失败 → Toast + 本地暂存

MVP 支持的指标类型:

指标 单位 输入控件
收缩压 / 舒张压 mmHg 两个数字输入框
心率 bpm 数字输入框
空腹血糖 mmol/L 数字输入框
餐后血糖 mmol/L 数字输入框
体重 kg 数字输入框1 位小数)
体温 数字输入框1 位小数)

每次可同时填多项或只填一项。录入时间默认当前,可手动调整为当天任意时间。

5.2 预约挂号

选择科室 → 选择医生 → 选择日期(排班日历)→ 选择时段 → 确认预约
                                                            ↓
                                                  POST /appointments
                                                            ↓
                                              成功 → 订阅消息通知 + 日历同步
                                              满员 → 提示"该时段已满"

关键交互:

  • 排班日历用周视图,有排班的日期标绿点
  • 点击日期后展示该日可用时段
  • 时段显示"剩余 X 位"
  • 预约成功后支持微信订阅消息提醒

5.3 报告查询

报告列表(分页,时间倒序)
    ↓ 点击某份报告
报告详情 → 基本信息卡 + 指标列表 + PDF/图片附件预览

指标状态标记:

  • 异常偏高:红色 + ↑ 箭头
  • 异常偏低:红色 + ↓ 箭头
  • 正常范围:灰色

5.4 随访管理

待办列表(按截止日期排序)
    ↓ 支持"待完成/已完成/已过期"筛选
点击任务 → 动态表单(后端定义字段)→ 提交 → 标记完成

问卷由 PC 端医护创建follow_up_task小程序负责展示和填写。提交后创建 follow_up_record。

5.5 家庭健康管理

就诊人列表(本人 + 已添加家属)
    ↓ 点击头像或下拉切换
切换就诊人 → 全局 X-Patient-Id 更新 → 所有页面数据刷新
    ↓ 添加家属
填写信息 → 姓名 + 关系 + 身份证号(可选)→ POST /patients

切换就诊人通过全局 store 更新,所有 service 请求自动携带新 X-Patient-Id

5.6 健康资讯 + 用药提醒

资讯:

  • GET /articles → 分页列表(缩略图 + 标题 + 摘要 + 时间)
  • 文章详情使用 Taro RichText 组件渲染富文本

用药提醒MVP

  • 小程序本地 storage 存储提醒规则(药品名 + 频率 + 时间)
  • 每日触发检查
  • 通过微信订阅消息推送提醒
  • 不依赖后端新表

6. API 集成与状态管理

6.1 请求层封装

services/request.ts 职责:

拦截点 行为
请求拦截 自动注入 Authorization: Bearer {token}
请求拦截 自动注入 X-Patient-Id(当前选中就诊人)
请求拦截 自动注入 X-Tenant-Id(从登录信息获取)
响应拦截 401 → 静默刷新 token → 重试原请求
响应拦截 刷新失败 → 跳转登录页
错误处理 网络错误 / 业务错误 / 超时统一处理

多租户处理:患者只属于一个租户。登录时后端返回 tenant_id,前端每次请求带上。不走 tenant_id 中间件自动注入。

6.2 Zustand Stores

auth store

interface AuthState {
  token: string | null
  refreshToken: string | null
  user: { id: string; name: string; phone: string; avatar: string } | null
  currentPatient: Patient | null
  patients: Patient[]
  setCurrentPatient: (id: string) => void
  login: (code: string) => Promise<void>
  bindPhone: (data: BindPhoneData) => Promise<void>
  logout: () => void
}

health store

interface HealthState {
  todaySummary: VitalSigns | null
  trendData: Record<string, TrendPoint[]>
  refreshToday: () => Promise<void>
  getTrend: (type: string, range: '7d' | '30d' | '90d') => Promise<TrendPoint[]>
}

6.3 API 端点对应表

小程序 service 后端端点 方法
auth.login(code) /api/v1/auth/wechat/login POST
auth.bindPhone(data) /api/v1/auth/wechat/bind-phone POST
auth.refresh() /api/v1/auth/refresh POST
health.getToday() /api/v1/health/vital-signs?date=today GET
health.input(data) /api/v1/health/vital-signs POST
health.getTrend(type, range) /api/v1/health/vital-signs/trend GET
appointment.list() /api/v1/health/appointments GET
appointment.create(data) /api/v1/health/appointments POST
appointment.cancel(id) /api/v1/health/appointments/:id/cancel PUT
schedule.getByDoctor(id) /api/v1/health/doctor-schedules GET
report.list() /api/v1/health/lab-reports GET
report.detail(id) /api/v1/health/lab-reports/:id GET
followup.list() /api/v1/health/follow-up-tasks GET
followup.submit(id, data) /api/v1/health/follow-up-records POST
patient.list() /api/v1/health/patients GET
patient.create(data) /api/v1/health/patients POST
patient.update(id, data) /api/v1/health/patients/:id PUT

后端需新增的端点(尚未实现):

端点 说明
POST /auth/wechat/login 微信登录
POST /auth/wechat/bind-phone 手机号绑定
GET /vital-signs/trend 趋势聚合查询
GET /doctor-schedules 按科室/医生查询排班
GET /articles 健康资讯列表
GET /articles/:id 资讯详情

7. 视觉设计

7.1 主题色

沿用现有 HTML 原型的医疗清新风格:

用途 色值 说明
主色 #0891B2 青色,按钮、导航、强调
主色浅 #E0F7FA 背景、卡片高亮
主色深 #065A73 渐变、按压态
辅助色 #059669 绿色,成功、正常指标
危险色 #DC2626 红色,异常指标、删除
警告色 #D97706 琥珀,待办、提醒
背景色 #F0FDFA 页面底色
卡片色 #FFFFFF 卡片背景
主文字 #134E4A 标题、正文
副文字 #6B7280 说明、标签
轻文字 #94A3B8 时间戳、占位符

7.2 圆角规范

元素 圆角
卡片 12px
按钮 8px
输入框 8px
头像 50%
快捷图标 14px

7.3 阴影规范

层级
轻阴影 0 1px 3px rgba(0,0,0,.04)
标准阴影 0 2px 8px rgba(0,0,0,.06)
中阴影 0 4px 16px rgba(0,0,0,.08)
重阴影 0 8px 32px rgba(0,0,0,.12)

8. 开发工作流

8.1 开发环境

# 安装依赖
cd apps/miniprogram && pnpm install

# 开发模式(需配合微信开发者工具)
pnpm dev:weapp         # Taro 编译 + watch → dist/
# 用微信开发者工具打开 dist/ 目录预览

# 生产构建
pnpm build:weapp       # 压缩 + tree-shaking

# 后端联调
# 需同时运行 erp-server (port 3000)
# 小程序开发设置中关闭域名校验(开发阶段)

8.2 与 Web 端的代码复用

复用内容 方式 说明
TypeScript 类型 按需引用 Web 端 DTO 类型 API 请求/响应结构一致
主题变量值 Web CSS 变量 → SCSS 变量 青色主调色值保持一致
Zustand 模式 相同 store 设计模式 各自独立实现
API 接口定义 service 层函数签名对齐 Web 用 fetch小程序用 Taro.request

8.3 后端需同步开发的内容

优先级 内容 涉及 crate
P0 wechat_users 表 + 微信登录/绑定 API erp-auth
P0 vital_signs 趋势查询 API erp-health
P0 doctor_schedules 按科室/医生查询 API erp-health
P1 lab_reports 指标异常标注字段 erp-health
P1 follow_up_tasks 动态问卷字段扩展 erp-health
P2 articles 表 + CRUD erp-health
P2 微信订阅消息模板注册 erp-server

9. 分期交付计划

阶段 内容 目标
Phase 1 项目骨架 + 登录流程 + 首页(静态数据) 基础搭建
Phase 2 健康数据录入 + 趋势图 核心功能
Phase 3 预约挂号 + 排班日历 核心功能
Phase 4 报告查询 + 家庭管理 扩展功能
Phase 5 随访 + 资讯 + 用药提醒 扩展功能
Phase 6 打磨 + 真机测试 + 提审 上线准备

每个 Phase 内部遵循:先对接后端 API → 再实现 UI → 真机验证 → 提交。


10. 约束与风险

约束/风险 应对策略
小程序包体积限制2MB 主包) 按功能分包加载,图表库按需引入
微信审核周期3-7 天) Phase 6 预留充足审核时间
后端 API 部分未实现 小程序开发与后端同步推进,优先实现 P0 端点
微信订阅消息需用户主动触发 在预约成功、随访提交等场景引导用户订阅
蓝牙设备适配复杂 MVP 预留接口不实现,后续按设备型号逐一对接
多就诊人数据隔离 后端严格校验 user-patient 归属关系