elder-yudao-pro/docs/健康业务模块与身份模型.md

13 KiB
Raw Permalink Blame History

健康业务模块与身份模型

更新日期:2026-10-05。实施仓库:elder-yudao-pro,分支:axr。

1. 本次业务决定

以下规则来自用户本次确认,后续开发应沿用:

  • 老人、志愿者、家属使用 手机号+密码 登录,短信验证后续接入。
  • 每个账号只有一种业务身份,不能同时是老人、志愿者和家属。后台管理员属于另一套账号体系。
  • 志愿者需要管理员审核,通过且启用后才能参与志愿服务。
  • 第一版由管理员创建账号与身份档案,后续再开放本人注册。
  • 一位老人可关联多位家属,一位家属可关联多位老人。
  • 家属关联需老人本人确认;管理员也可以核实后确认,必须填写核实理由。
  • 家属只在关联已确认且双方身份有效时,才能读取关联老人的健康信息。
  • 暂不删除已有源码、模块和目录;身份使用停用,关联使用解除,保留历史。

管理员核实方式、注册时的手机号验证流程,后续实现对应入口时再细化。目前没有公共密码注册接口。

2. 账号与身份的边界

flowchart LR
  System[system_users 后台管理员] --> Admin[管理端权限和审核]
  Member[member_user 手机号账号] --> Identity[health_identity 单一业务身份]
  Identity --> Elder[老人 health_elderly_profile]
  Identity --> Volunteer[志愿者 health_volunteer_profile]
  Identity --> Family[家属身份]
  Family --> Relation[health_family_relation 待确认或已确认]
  Relation --> Elder

system 的角色、菜单权限与 health 的业务身份用途不同。前台选择“老人”或“志愿者”不能获得该身份;后端按登录的 memberId 查询可信身份。

框架区分 /admin-api 的后台 Token 与 /app-api 的会员 Token。健康 APP Controller 额外使用 @PreAuthorize("isAuthenticated()"),因为本版本芋道的 APP 路径默认允许匿名进入。

名称 含义 使用位置
adminUserId system_users.id 审核管理员、管理端权限
memberId member_user.id 手机号登录账号
identityId health_identity.id 老人、志愿者或家属的业务身份
elderlyProfileId health_elderly_profile.id 老人健康档案,后续评估与预约的主体
volunteerProfileId health_volunteer_profile.id 志愿者服务资料,后续派单关联
relationId health_family_relation.id 单条家属与老人关联

不同表的 ID 可以恰好相同,不能靠数值相同推导关联。创建账号、身份和对应档案在一个数据库事务内完成;账号密码使用芋道 BCrypt,响应不包含密码。

3. 模块与表

根 Maven 和 yudao-server 已启用 member、health。健康业务只有一个模块,按芋道惯例分为 api/biz,不引入新的微服务或通用工作流。

yudao-module-health/
  yudao-module-health-api/       模块间接口、DTO、身份枚举、错误码
  yudao-module-health-biz/       Controller、Service、DO、Mapper、测试
yudao-ui-admin-vue3/src/
  api/health/                   健康管理请求封装
  views/health/identity/        身份、基础档案与志愿者审核
  views/health/family-relation/ 家属关联确认与解除
mysql_script/health/            独立增量 SQL

所有健康表继承 TenantBaseDO,含租户、创建/更新和逻辑删除字段;使用框架租户拦截器,关联查询与建档校验均在当前租户内完成。

表 当前字段与约束
member_user 手机号、BCrypt 密码、账号状态;新建表添加 (tenant_id,mobile) 唯一索引
health_identity 账号、单一身份、姓名、性别、生日、联系方式、地址、启用状态、审核结果;(tenant_id,member_id) 唯一
health_elderly_profile 紧急联系人、健康摘要、病史、用药、特殊需求;每个老人身份一份基础档案
health_volunteer_profile 技能、服务区域、可服务时间说明、服务经验;每个志愿者身份一份服务档案
health_family_relation 家属身份、老人档案、亲属关系、确认/解除状态、处理账号类型与编号、时间、理由;同一配对唯一

当前不采集身份证号。生日存储为 date,年龄后续按生日计算。性别沿用芋道:1=男、2=女、3=未知;旧系统 0=男、1=女 必须显式转换。

手机号用于登录;contactPhone 是档案联系方式,不会因编辑档案而更改登录手机号。已有会员账号通过 memberId 显式绑定,建档不会重置其密码。身份类型和绑定账号创建后不可变更,避免后续服务记录主体发生变化。

账号停用和身份停用均会使业务身份校验失败。模板会员模块仍保留积分、等级等源码与空表,本次管理页面只展示健康相关功能。

4. 审核与关联状态

业务身份:10=老人、20=志愿者、30=家属。

启用状态:0=启用、1=停用。审核状态:0=待审核、1=通过、2=驳回。两者独立,启用一个待审志愿者不能使其获得服务权限。

  • 管理员创建老人和家属身份时直接通过;创建志愿者时进入待审。
  • 只有待审志愿者能审核;驳回必须填写理由。
  • 驳回后可修改资料并重新提审;重复审核由条件更新拦截。
  • 编辑档案不会修改启用或审核状态。

家属关联:0=待确认、1=已确认、2=已拒绝、3=已解除。

  • 新增关联仅创建申请,不能自动获得读取权限。
  • 本人端申请的家属身份取自登录账号,忽略请求中伪造的 familyIdentityId。
  • 老人只能处理自己的关联;管理员核实确认或拒绝时必须填写理由。
  • 老人、家属可解除本人的待确认/已确认关联;管理员也可解除,均需填写理由。
  • 管理员可将已拒绝/已解除关联重新申请,此时必须重新确认才恢复授权。
  • 处理字段保留最近一次审核/解除痕迹,尚不是完整的每次变更事件流水。
  • 当前确认代表该家属可读取关联老人的基础健康档案;第一阶段不提供家属代预约。

5. 接口与权限

管理端前缀 /admin-api:

路径 功能 权限
POST /health/identity/create 创建账号与身份档案,或绑定已有会员账号 health:identity:create
PUT /health/identity/update 编辑基本资料及对应档案 health:identity:update
GET /health/identity/get、/page 详情与分页筛选 health:identity:query
PUT /health/identity/audit、/resubmit 志愿者审核与重新提审 health:identity:audit
PUT /health/identity/update-status 身份启用与停用 health:identity:update-status
GET /health/family-relation/page 查看关联列表 health:family-relation:query
POST /health/family-relation/create 提交关联申请 health:family-relation:create
PUT /health/family-relation/review、/reopen 核实处理与重新申请 health:family-relation:review
PUT /health/family-relation/revoke 解除关联 health:family-relation:revoke

新增关联页面按姓名搜索老人和家属,同时需要 health:identity:query。普通后台角色应通过系统角色管理授予所需菜单与按钮权限;超级管理员默认拥有全部菜单。

会员端前缀 /app-api:

路径 当前行为
POST /member/auth/login 复用芋道的手机号与密码登录、Token 颁发
GET /health/identity/me 读取当前会员的单一身份与对应档案;可查看本人志愿者待审结果
GET /health/identity/family-relations 本人相关关联列表
POST /health/identity/family-relation/request 家属提交关联申请
PUT /health/identity/family-relation/review 老人本人确认或拒绝
PUT /health/identity/family-relation/revoke 老人或家属解除本人关联
GET /health/identity/family-elderly-profile 已确认家属按老人档案编号读取健康档案

本次提供 APP 后端接口,没有改造旧移动端。请求需正确的 Token 和 tenant-id;家属和老人账号类型同为 MEMBER,具体业务权限仍须健康服务校验。

其他模块调用 HealthIdentityApi:

  • getIdentityByMemberId 仅查询身份,不表示身份有效。
  • requireActiveIdentity(memberId, identityType) 检查账号存在/启用、业务身份类型、启用状态与审核结果。后续预约与接单使用此方法。
  • requireConfirmedFamilyRelation(familyMemberId, elderlyProfileId) 检查双方有效及已确认关联。后续家属访问评估、运动与告警记录使用此方法。
  • 本次没有提供志愿者读取任意老人健康档案的入口;后续必须结合已分配工单校验访问范围。

6. 数据库与 IDEA 运行

按顺序执行:

  1. V000__member_schema.sql:从模板提取的 11 张会员表的纯 DDL,去掉 DROP、示例账号、演示数据及自增起点。
  2. V001__health_identity.sql:新增 4 张健康业务表与唯一索引。
  3. V002__health_menu.sql:新增“健康服务 → 身份与档案、家属关联”及按钮权限。

均使用存在性判断,不清空数据。CREATE TABLE IF NOT EXISTS 不会升级已有旧表结构;若已有 member_user 缺少约定唯一索引,初始化脚本会停止并提示核实,不能直接覆盖已有表。

在项目根目录执行:

powershell -ExecutionPolicy Bypass -File .\deploy\local\initialize-health.ps1

脚本读取已有的私有 secrets.psd1,仅允许操作 elder_yudao_* 本地独立数据库。不会导入旧老年系统数据,不会初始化摄像头、短信或外部呼叫服务。

IDEA 点击 Maven 的 Reload All Maven Projects,再重新运行已有的后端和前端启动配置。前端 .env 已增加 health;模板会员商城页面未加入产品菜单。

管理端重新登录后进入“健康服务”,可以新建老人、志愿者和家属档案,审批志愿者、申请和核实家属关联。

7. 旧系统迁移注意事项与下一步

旧数据库 sys_user.user_id 是登录编号,elderly_info.elderly_id 是档案编号;一些旧家属代码把 elderly_id 当作登录编号。不能直接沿用旧字段名解释。正式导入时需要 legacy ID 映射,明确旧登录 ID → 新 memberId、旧档案 ID → 新 elderlyProfileId、旧采集记录 ID → 新 assessmentId。

旧健康采集和评估允许多次记录。当前 health_elderly_profile 是基础档案,不能把所有历史评估覆盖到这一行。下一阶段应建立独立评估记录、保存时间及原始指标,再逐项迁移已核实的评分逻辑。

后续既定顺序:健康采集与评估 → 轻量运动/场地/设备 → 自由预约与活动报名 → 志愿者匹配/派单/按月拒单理由 → 提醒;LLM/智能体和固定场地摄像头另行接入。摄像头跌倒检测、最近 72 小时视频保存、自动呼叫 120 都尚未实现,老人无回应的判定仍待讨论。

新增能力继续放在 health 的独立包与表中,预约使用老人档案编号,派单使用志愿者身份/服务档案编号,健康历史数据单独保存。不要将手机号、密码或管理员角色塞进健康评估表。

参考:迁移上下文、扩展需求草案、项目目录说明。扩展草案是历史需求记录,具体已实现内容以本文和代码为准。

8. 验证记录

  • Maven 后端打包通过,HealthIdentityServiceTest 的 9 项测试全部通过:加密账号/档案创建、事务回滚、单身份约束、重复手机号不重置密码、志愿者审核与停用、家属确认与解除、伪造身份拦截及多对多、租户隔离、匿名 APP 调用拦截。
  • Vue 管理端 desktop 生产构建通过,新增文件 ESLint 检查通过。
  • 前端原始全量 vue-tsc 因既有类型声明路径配置报 TS2688;使用临时检查配置补充核实后,新增 health 页面/API 没有类型错误,但模板其他页面/组件仍有既有错误,不能宣称全仓库类型检查通过。
  • 本地 elder_yudao_local 增量初始化完成,共 76 张表(原 61+member 11+health 4);脚本重复执行验证通过,健康账号与关联表保持空数据。
  • 临时后端在 48081、Redis DB 14 验证后已关闭;已有 48080 后端和 5173 前端进程未重启。新代码需要由用户在 IDEA 重新运行。
  • 实际 HTTP 验证通过:管理员登录、身份与关联分页、新增两个健康菜单、匿名 APP 拒绝(业务码 403)、后台 Token 调用 APP 拒绝(403)、错误手机号拒绝(400)、匿名后台接口拒绝(401)。未创建演示会员账号。

未迁移旧数据,未改造移动端页面,未实现历次健康评估、预约派单或设备/智能体接入;这些仍是后续阶段。