# 服务机构端 · C0 基础骨架 · 设计文档 > 日期:2026-10-14 > 范围:服务机构端 P0 的「地基」——机构=租户映射、账号/人员/角色、数据模型基线、审计、错误码。 > 依据:`docs/requirements/P0 PRD(交付开发·V1)`、`docs/refs/` 数据字典、脚手架 sysmgr(ec-nest/ec-admin)。 > 后续:C1 待遇档案、C2 派单工单、C3 履约留痕、C4 质控闸门(各自另出 spec)。 ## 1. 背景与目标 在 sysmgr 脚手架(ec-nest + ec-admin)之上实现服务机构端 P0。C0 只做地基,定死全局规则,供 C1–C4 复用,避免各块各自为政。 **已定决策**(用户 2026-10-14 拍板): - 每个服务机构 = 脚手架一个独立租户(tenant)。 - 业务角色(nurse/leader/qc/admin/director)用脚手架角色,按业务角色配置权限。 - 保留脚手架菜单 + 新增服务机构端业务菜单。 - 本期只做机构管理后台 + 后端接口;护理员 APP(Flutter)、家属端(UniAPP)后续另开 change。 - 照片存储用腾讯云 COS,本期占位。 - 完整审计。 ## 2. 机构↔租户映射 - 机构 = 租户。用脚手架 `tenant_code` 作为**机构唯一标识**(承载 PRD 的 `org_id` 语义)。 - `org` 独立业务表:主键 = 机构 code(与 `tenant_code` 同值),存机构业务字段;**不扩展 `sys_tenant`**(守 fork「框架只读」铁律)。 - 业务表统一带 `tenant_code`,继承脚手架 PrismaService 的自动多租户过滤 + 软删过滤。 - 备选(弃用):机构字段塞进 `sys_tenant` —— 污染脚手架,升级上游时易冲突。 `org` 关键字段:机构 code(主键)、org_name、org_type(medical_care/nursing_home/home_care/home_individual)、credit_code、loc_code、loc_name、svc_source(national/local)、license_no、address、contact_name/contact_phone、bed_count、sign_date。 ## 3. 账号 / 人员 / 角色 分工(用户确认): - **登录/鉴权/RBAC → `user`**:复用脚手架 `sys_user` + user-role + resource,**不加任何列**。 - **人员/HR/资质 → `staff`**:业务新表,是被派单、被质控、挂资质的对象,**不参与鉴权**。 - **关联**:`staff.user_id → user.id`,1:1,**外键放 staff 侧、可空**——不动 `sys_user`(守「框架只读」铁律)。院长/质控/管理员无 staff 记录;护理员/组长的 staff 记录 `user_id` 指向其账号。 > PRD 的 `user.staff_id` 落地为 `staff.user_id`(语义等价、方向镜像),字段字典以 `shared/data-model` 为准。 `staff` 关键字段:staff_id、tenant_code、name、id_card_no(加密)、person_code(预留)、phone、job_type(nurse/nurse_medical/manager)、work_type、entry_date/leave_date、employ_status、cert_type/cert_no/cert_level/cert_expire/cert_status、cert_verify_url(预留)、group_leader_id。 「多角色」落地:PRD 的「`user.role` 逗号分隔」**不照搬**,用脚手架 user↔role 多对多实现(权限并集天然支持)。「本组」在业务 service 层按 `staff.group_leader_id` 计算,不走脚手架 org 树。 ## 4. 角色与权限码 5 个脚手架角色:nurse / leader / qc / admin / director。权限码走脚手架 Permissions + tenant-template 资源注册机制。 权限码清单(domain:action,最终清单随 `data-model`/`api-contract` 收口): | 域 | 权限码 | |---|---| | elder | list / detail / create / update / status-change / import / svc-save | | plan | create / change / detail / confirm | | order | generate / assign / reassign / cancel / detail / today | | record | checkin / checkout / item-save / photo-upload / detail | | abnormal | report / list / handle | | qc | pending-list / detail / pass / return / exception-link | | svc-org | list / config / new-national | | staff | list / create / update / group-assign | | export | export | 角色→权限(并集;业务 service 层补「本组 / 自审自放行」校验): - **nurse**:order.today、record.*、abnormal.report - **leader**:nurse 全部 + 本组 order.assign/reassign/cancel、本组 qc.pass/return - **qc**:elder.*、plan.*、order.*(全部)、record.detail、abnormal.handle、qc.*(全部)、svc-org.config、export - **admin**:staff.*、svc-org.config、系统设置;不碰业务数据 - **director**:只读查看;**仅持 director 时写接口 403** ## 5. 数据模型基线(C0 建表) C0 建 9 张业务表:`org`、`staff`、`svc_national`、`svc_local`、`svc_mapping`、`svc_org`、`dict_abnormal_type`、`dict_photo_tier`、`loc_config`。`user` 复用 `sys_user`(**不加任何列**);`staff.user_id` 关联 `user.id`。 - svc_national(L1):nat_id、nat_code(varchar20)、nat_name、nat_category、nat_sub_category、recommend_staff、recommend_duration、is_medical、version - svc_local(L2):loc_id、loc_code、local_item_name、local_category、svc_time、min_freq、staff_qual、is_medical、source_doc、map_status - svc_mapping(L3,机构不可见):map_id、loc_id、nat_id(可空)、map_type、map_note、status - svc_org(L4):org_svc_id、tenant_code、src_type、src_id、is_enabled、price(预留)、price_effective(预留)、is_new_national - dict_abnormal_type:9 宫格异常分类;dict_photo_tier:必拍/免拍/可拍配置 - loc_config:loc_code、loc_name、目录来源(national/local)、项数规则(预留) > 字段字典唯一锚点:`shared/data-model`(实现时先行,本 spec 不重复完整字段定义)。 **与脚手架约定对齐点**(data-model 里定死): 1. 主键:脚手架 UUID v7(varchar36)vs PRD varchar(32) → 倾向跟随脚手架 UUID v7;业务码(机构编码/项目代码)作唯一索引。 2. 软删:脚手架 `deleted_at`(时间戳)vs PRD `is_deleted`(布尔)→ 跟脚手架 `deleted_at`。 3. 通用字段:`created_at/by`、`updated_at/by` 沿用脚手架。 ## 6. 审计清单(完整审计) 复用脚手架 audit-log,以下业务动作全量落审计(谁 / 何时 / 动作 / 对象 / 前后值): 建档、改待遇状态、改等级、制定/变更计划、派单/调单/取消、签到/签退、上传照片、异常上报、质控放行/退回、异常处理/联动改计划、Excel 导入、导出文书、明文查看身份证、结转垫付。 ## 7. 业务错误码 PRD 错误码映射到脚手架 error-codes.ts(业务码 5 位 [域2][序3]),统一响应补 `hint` 字段(脚手架现为 {code,message,data}): 1001 无有效待遇(L1) / 1002 无有效计划(L2) / 1003 无有效工单(L3) / 1004 留痕不完整(L4) / 1005 未质控(L5) / 1006 资质不匹配(提示级) / 2001 时间冲突(硬拒) / 2002 项数不满足(提示) / 3001 必拍未拍(硬拒) / 3002 定位失败(非错误) / 3003 扑空登记 / 3004 垫付不计费 / 4001 越权或自审自放行。 ## 8. 横切产品缺口约定(C3/C4 引用) - **推送**:P0 只做后台站内待办实时刷新(WebSocket/短轮询);APP push、公众号模板消息后置。 - **离线并发**:client_md5 幂等 + 留痕「补正链」;补传撞已退回 → 标「待重新质控」。 - **照片 COS**:record_photo.file_path 结构 + 上传接口占位(不接 COS SDK),COS 配置留 .env 占位。 - **身份核验(P-9)**:本期兜底 = 拍照留痕 + 护理员实名账号 + 家属可选确认;record 预留核验方式字段;扫脸/人证后置。 ## 9. 非目标(本期不做) 护理员 APP、家属端、二期三块(结算/资质/看板)、评估机构端、医保接口对接、真实 COS 上传、身份扫脸核验。 ## 10. 验收 - 一机构一租户隔离:跨机构数据不可见(4001)。 - 5 角色权限并集 + 仅持 director 时写接口 403。 - 业务菜单出现、脚手架菜单保留。 - 审计动作全量落日志。 - C0 建表经 `prisma migrate` 生成,`shared/data-model` 字段字典先行。