feat: 邀请函邮件发送 + 首次设密/密码为空 + 姓名单一可信源

邀请发送 (菜单暂隐藏, 待确认参数见 发送邀请-待确认参数.md):
- 后端: BizInvite / BizInviteRecipient + Controller/Service/Mapper/XML
- 邮件: InviteMailSender (spring-boot-starter-mail SMTP) + application*.yml 邮件配置
- 上传进度: UploadProgressRegistry + UploadProgressController
- 前端: InviteList / InviteNew / InviteDetail / InviteView + api/business/invite.js
- 原型: proto/html/components/invite-detail / new-invitation / send-invitation

登录/账号:
- 首次设密: /getInfo 返回 isPasswordEmpty, SysProfileController 密码为空时跳过旧密码校验, ForcePasswordDialog 强制弹窗
- 姓名单一可信源 resolveDisplayName: doctor→biz_expert.name, sponsor/executor→biz_person.name, 其余回退 nick_name
- OA compliance 门禁改为按手机号查 ecology 视图 (不再限定 manager/leader)

其它:
- OSS zip 在线查看 (列清单+取单文件, 公开只读) + SecurityConfig permitAll
- doctor 项目详情 ProjectDetail.vue
- 数据库/测试/设计文档 (md) 入库
This commit is contained in:
郭庆泰
2026-09-10 20:40:49 +08:00
parent 56615f9806
commit 5a0a892574
171 changed files with 11032 additions and 876 deletions
+715
View File
@@ -0,0 +1,715 @@
# 详细设计方案
> 版本:V2.0
> 范围:合规管理平台(业务系统)整体设计
> 读者:甲方 / 业务方
> 配套文档:《数据库设计文档 V2.0》(表结构与字段细节,本文不再重复展开)
---
## 一、概述
### 1.1 项目定位
本平台是一个面向「医疗合规项目」的**全流程协同管理平台**,覆盖从项目申报、立项、分配、公示、执行、材料审核、结算到完结的完整业务闭环。平台连接六类角色,把原本分散在线下、依赖人工催办与纸质签字的环节统一搬到线上,实现流程可追踪、材料可归档、费用可核算、签字可验真。
### 1.2 建设目标
1. **全流程线上化**:投稿、立项、分配、公示、报名、执行、材料审核、结算、完结,全程在线流转。
2. **多角色协同**:医生、执行方、支持方、合规人员、项目负责人、后台管理员,各司其职、权限隔离。
3. **材料与费用规范化**:会议材料分类上传、发票自动识别、劳务费 / 会务费自动汇总。
4. **签署电子化**:医生在线填写劳务信息、手写签名,自动生成 PDF 劳务协议并归档。
5. **消息实时触达**:短信 + 站内信 + 页面角标实时推送,关键节点主动通知。
### 1.3 术语定义
| 术语 | 含义 |
|---|---|
| 医生(专家) | 参与项目 / 会议的医务人员,注册后需资质审核通过方可登录 |
| 执行方 | 承接项目并负责会议执行、材料上传、建会的单位(含主账号 + 执行人员子账号) |
| 支持方 | 项目申办 / 资金支持单位,承担材料二级审核(监察)职责 |
| 合规人员 | 平台核心审核与项目管理角色,负责材料一级审核、结算、完结 |
| 监察员 | 支持方下派到项目 / 会议的监督人员,负责材料二级审核 |
| 项目负责人 | 只读查看本人负责项目的角色 |
| 劳务电子签 | 医生在线签署劳务协议、生成 PDF 归档的全过程 |
| 策划方案 | 医生 / 执行方 / 支持方投稿的项目方案,审核通过后立项为正式项目 |
| 专项计划 | 项目方向的选项来源,由后台管理员维护 |
| 主账号 / 子账号 | 执行方、支持方机构的账号形态:主账号代表机构,子账号为机构下属人员 |
---
## 二、系统总体设计
### 2.1 技术架构
系统采用「前后端分离」架构,面向不同使用场景提供多个入口:
```
┌─────────────────────────────────────────────────────┐
│ 前端(多端) │
│ 管理后台 Web(六类角色) │ 公开门户(公示/注册/协议) │
│ H5 移动端(扫码签署 / 拍照上传) │
└───────────────────────────┬─────────────────────────┘
│ HTTP 接口(JWT 鉴权)
┌───────────────────────────▼─────────────────────────┐
│ 业务后端(API) │
│ 账号权限 │ 项目 │ 会议 │ 材料 │ 审核 │ 费用 │ 电子签 │ 消息 │
└───────┬──────────────┬───────────────┬───────────────┘
│ │ │
┌────▼───┐ ┌─────▼─────┐ ┌─────▼─────┐
│ 数据库 │ │ 对象存储 │ │ 外部服务 │
│(业务数据)│ │(文件/PDF) │ │ OCR/短信/微信│
└────────┘ └───────────┘ └───────────┘
```
- **后端**Java + Spring Boot,业务模块统一以 `/business/*` 对外提供接口,鉴权采用 JWT。
- **前端**Vue 3 + Element Plus,按角色划分为六套后台菜单 + 一套公开门户 + H5 移动端。
- **数据库**:MySQL,业务表逻辑删除、快照留档。
- **文件**:统一对象存储(OSS),材料、凭证、PDF 协议、海报等文件云端存储。
- **外部服务**:发票 OCR 识别、短信验证码、微信分享、OA(ecology)项目信息拉取。
### 2.2 角色与账号模型
平台共六类角色,角色是账号的固有属性,由 `sys_user.role_type` 单一字段确定:
| 角色 | 业务定位 | 账号形态 |
|---|---|---|
| 后台管理员(admin) | 系统维护、基础数据、后台用户 | 无企业归属 |
| 合规人员(manager) | 核心审核与项目管理 | 无企业归属 |
| 医生(doctor) | 投稿、参会、签署劳务 | 无企业归属 |
| 执行方(executor) | 承接项目、建会、上传材料 | 主账号(注册即建单位)+ 子账号(执行人员) |
| 支持方(sponsor) | 申办、监察、查看项目 | 主账号 + 子账号(监察员) |
| 项目负责人(leader) | 只读查看负责的项目 | 无企业归属 |
执行方、支持方机构内部区分「主账号(MAIN)/ 子账号(SUB)」:
- **主账号**:代表机构,注册时创建,关联到机构(`biz_org.user_id`)。
- **子账号**:机构下属人员,通过 `parent_user_id` 关联到主账号,数据权限按「本人」严格隔离。
### 2.3 功能架构总览
| 功能域 | 核心能力 |
|---|---|
| 门户与访问 | 首页、项目公示、公示详情、注册、登录、协议、专项计划 |
| 账号与组织 | 用户 / 角色 / 机构 / 人员 / 科室职称字典管理 |
| 医生管理 | 医生注册、资质审核、账号开通、档案维护 |
| 策划方案 | 医生 / 执行方 / 支持方投稿、合规审核、专项计划维护 |
| 项目管理 | 立项、分配、公示、意向、报名、评分 |
| 会议管理 | 建会、参会人、材料、发票、两级审核、费用、结算、完结 |
| 劳务电子签 | 推送签署、填写劳务信息、手写签名、PDF 归档 |
| 消息通知 | 站内信、短信、页面角标实时推送 |
| 内容管理 | 协议文章、公益支持函、邀请函、劳务协议模板 |
---
## 三、账号与认证设计
### 3.1 登录(短信验证码登录)
平台采用**短信验证码登录**(无密码登录),接口如下:
| 接口 | 方法 | 说明 |
|---|---|---|
| `/business/auth/smsSendCode` | POST | 发送登录短信验证码(手机号须已注册;合规人员 / 项目负责人可从 OA 视图自动建号后放行发码) |
| `/business/auth/smsLogin` | POST | 校验短信验证码,颁发 JWT Token |
短信验证码的通用发送 / 校验接口(登录与各注册场景共用):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/business/sms/send` | GET | 发送短信验证码(返回 uuid,前端校验时回传) |
| `/business/sms/verify` | POST | 校验短信验证码 |
| `/business/auth/registerSendSms` | POST | 注册专用发码(发码前校验手机号未被注册) |
短信验证码登录的后端校验链路(按顺序):
1. 校验手机号格式(11 位)与验证码非空;
2. 校验短信验证码(`verifyCode`);
3. 按手机号查用户(合规人员 / 项目负责人若不在本地,会从 OA ecology 视图自动建档);
4. 校验账号状态:已删除、已停用均拒绝登录;
5. 子账号专属校验:主账号被停用 / 不存在时拒绝登录(「您所属的机构已禁用」);
6. 医生待审核拦截:`role_type=doctor` 且档案审核状态为「待审核」时拒绝登录(「您的信息正在审核中」);
7. 颁发 JWT Token 并记录登录日志。
### 3.2 注册(三类主体)
| 主体 | 接口 | 注册结果 |
|---|---|---|
| 医生(专家) | `/business/auth/registerExpert` | 创建 `sys_user`(用户名 = 手机号,`role_type=doctor`)+ 医生档案(状态 = 待审核);审核通过前不能登录 |
| 执行方(供应商) | `/business/auth/registerExecutor` | 创建主账号 `sys_user``role_type=executor`+ 执行机构 `biz_org` + 本人人员档案 |
| 支持方 | `/business/auth/registerSponsor` | 从已有支持方企业中选一家,创建**子账号** `sys_user``account_type=SUB``role_type=sponsor`+ 人员档案 |
三类注册均需:短信验证码校验、用户名 / 手机号唯一性校验、密码长度(6–20 位)校验。医生注册额外要求手机号格式与密码 6–20 位。
### 3.3 忘记密码
| 接口 | 方法 | 说明 |
|---|---|---|
| `/business/auth/forgotSendSms` | POST | 发送短信(手机号须已注册) |
| `/business/auth/resetPassword` | POST | 校验短信验证码后重置密码 |
### 3.4 登录状态与角色跳转
登录成功后,前端根据返回的用户角色(`role_type` 单一可信源)跳转到各自首页:
| 角色 | 首页 |
|---|---|
| admin | `/admin/workbench`(工作台) |
| manager | `/manager/workbench`(工作台) |
| doctor | `/doctor/home`(首页) |
| executor | `/executor/overview`(首页) |
| sponsor | `/sponsor/home`(首页) |
| leader | `/leader/home`(首页) |
---
## 四、角色权限与数据可见性
### 4.1 权限矩阵
| 能力 | 后台管理员 | 合规人员 | 医生 | 执行方 | 支持方 | 项目负责人 |
|---|:---:|:---:|:---:|:---:|:---:|:---:|
| 维护科室 / 职称字典(写) | ✓ | — | — | — | — | — |
| 维护专项计划 | ✓ | — | — | — | — | — |
| 维护协议文章 | ✓ | — | — | — | — | — |
| 配置劳务协议模板 | ✓ | — | — | — | — | — |
| 后台新建用户 | ✓ | — | — | — | — | — |
| 维护机构 / 人员 | ✓ | ✓ | — | 本人机构 | 本人机构 | — |
| 审核医生资质 | ✓ | ✓ | — | — | — | — |
| 新建 / 编辑项目 | ✓ | ✓ | — | — | — | — |
| 删除项目 | ✓ | — | — | — | — | — |
| 删除公示公告 | ✓ | ✓ | — | — | — | — |
| 分配执行单位 / 场次金额 | ✓ | ✓ | — | — | — | — |
| 分配监察员 | — | — | — | — | ✓ | — |
| 分配执行人 | — | — | — | ✓ | — | — |
| 投稿策划方案 | — | — | ✓ | ✓ | ✓ | — |
| 审核策划方案 | — | ✓ | — | — | — | — |
| 建会 / 编辑会议 | ✓ | ✓ | — | ✓ | — | — |
| 删除会议 | ✓ | ✓ | — | — | — | — |
| 上传 / 提交材料 | — | — | — | ✓ | — | — |
| 材料一级审核(合规) | — | ✓ | — | — | — | — |
| 材料二级审核(监察) | — | — | — | — | ✓ | — |
| 结算 / 完结 / 解冻 | ✓ | ✓ | — | — | — | — |
| 项目评分 | ✓(按合规口径) | ✓ | — | — | ✓ | — |
| 签署劳务(电子签) | — | — | ✓ | — | — | — |
| 推送电子签 / 邀请参会 | ✓ | ✓ | — | — | — | — |
### 4.2 数据可见性(数据隔离规则)
数据隔离在**后端**强制实施,每个角色的可见范围如下:
| 角色 | 项目可见范围 | 会议可见范围 |
|---|---|---|
| 后台管理员 | 全部项目 | 全部会议 |
| 合规人员 | 本人创建的项目(`create_user_id` | 本人创建项目下的会议 |
| 医生 | 本人报名的项目(`biz_execution_intent` 反查) | 本人参加的会议(参会人中间表反查) |
| 执行方(主账号) | 分配给本单位的项目(执行方分配 / 执行单位归属) | 本单位执行单位下的会议 |
| 执行方(子账号 / 执行人) | 被分配为执行人的项目(严格隔离,不回退主账号) | 本人创建的会议 |
| 支持方(主账号) | 本单位申办的项目(`sponsor_admin_user_id` / `sponsor_org_id` | 申办项目下的会议 |
| 支持方(子账号 / 监察员) | 被分配为监察员的项目(严格隔离,不回退主账号) | 被分配监察的会议 |
| 项目负责人 | 本人负责的项目(`lead_user_id` | 本人负责项目下的会议 |
补充可见性要点:
- **医生**:仅可见「我参与的会议」「我报名的项目」及本人投稿。
- **执行方子账号**:场次 / 金额按「本公司(主账号)维度」聚合展示,但会议列表范围仍是「本人创建的会议」。
- **支持方子账号**:监察员仅可见被分配监察的会议;支持方查看会议参会人时,敏感信息(姓名 / 手机号 / 银行卡号 / 账户名称 / 身份证号)在后端脱敏后下发。
- **支持方**:已完结且未「开通」的项目在支持方项目列表中不可见(项目「开通」开关,见 5.5 节)。
- **项目负责人**:全程只读。
- **门户(匿名)**:仅可访问公示、注册、登录、协议等公开内容。
---
## 五、功能模块详细设计
### 5.1 公开门户
公开门户无需登录,主要接口:
| 接口 | 方法 | 说明 |
|---|---|---|
| `/business/public/index` | GET | 首页数据(已发布项目、策划方案、机构介绍) |
| `/business/public/announcements` | GET | 已发布项目公示列表(按发布时间倒序) |
| `/business/public/project/{projectId}` | GET | 公示详情 |
| `/business/public/supportLetter/{annId}` | GET | 支持函详情 |
| `/business/public/invitation/{annId}` | GET | 邀请函详情 |
| `/business/public/article/{type}` | GET | 协议 / 隐私政策(`type=agreement/privacy` |
| `/business/public/specialPlan/list` | GET | 专项计划列表 |
| `/business/public/specialPlan/{id}` | GET | 专项计划详情 |
| `/business/public/biddingNotice` | GET | 按项目编号查外部招标平台公告并返回跳转地址 |
| `/business/public/wx/jssdk` | GET | 微信 JS-SDK 分享签名配置 |
| `/business/auth/sponsorOrgOptions` | GET | 支持方注册企业下拉(匿名) |
### 5.2 账号与组织管理
**机构管理**(支持方 / 执行方共用,`/business/org`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/list` | GET | 机构列表(按 `orgType` 区分支持方 / 执行方) |
| `/sponsorOptions``/executorOptions` | GET | 机构下拉选项(供项目分配弹窗) |
| `/myCompany` | GET | 当前登录支持方所属公司(供账号页回显) |
| `/add``/edit` | POST / PUT | 新增 / 编辑机构 |
| `/toggleStatus` | PUT | 启用 / 禁用机构(同步主账号状态) |
| `/remove` | DELETE | 删除机构 |
| `/importTemplate``/importData` | GET / POST | 机构批量导入(只导机构,不建人员账号) |
**人员管理**`/business/person`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/list` | GET | 人员列表(主账号自动隔离到「本人 + 子账号」对应人员) |
| `/sponsorList``/executorList` | GET | 支持方 / 执行方端专属人员列表(按机构圈人) |
| `/add` | POST | 新建人员(同时创建 `sys_user` 子账号,默认密码 123456) |
| `/edit``/remove` | PUT / DELETE | 编辑 / 删除人员 |
| `/profile` | PUT | 个人资料编辑(本人姓名 / 手机号) |
| `/changeAdmin` | PUT | 更换机构管理员(人员晋升为 MAIN,原管理员降为 SUB) |
| `/resetPassword` | PUT | 重置人员登录密码(默认 123456) |
| `/sponsorImport``/executorImport` | POST | 人员批量导入(executor 模板多一个「邮箱」必填列) |
**业务字典**(科室 / 医生职称,`/business/dict`):读接口(list / active / getById)对所有登录用户开放;写接口(POST / PUT / DELETE)仅后台管理员可操作。
**后台新建用户**`/business/adminUser/create`):仅后台管理员可调用,按角色级联创建用户。
### 5.3 医生(专家)管理
医生档案是劳务结算与电子签的数据源,接口(`/business/expert`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/list` | GET | 医生列表 |
| `/getInfo/{expertId}` | GET | 医生详情 |
| `/profile` | GET | 当前登录医生的档案(按 userId 路由) |
| `/byPhone/{phone}` | GET | 按手机号查医生(参会人弹窗放大镜回填) |
| `/add` | POST | 新建医生(同时创建 `sys_user`,用户名 = 密码 = 手机号) |
| `/edit` | PUT | 编辑医生档案 |
| `/status` | PUT | 启用 / 禁用(同步 `biz_expert.status` + `sys_user.status` |
| `/profile`(PUT) | PUT | 医生个人档案更新(后端强制注入当前用户) |
| `/remove` | DELETE | 删除医生 |
| `/export` | POST | 导出医生列表 |
| `/importTemplate``/importData` | GET / POST | 医生批量导入 |
医生档案关键字段:姓名、手机号、工作单位、科室、职称、地区、身份证号、银行卡号、开户行、执业证书 / 职称证书附件、审核状态(待审核 / 通过 / 拒绝)、启停状态。
### 5.4 策划方案与专项计划
**策划方案**`/business/projectPlan`):医生、执行方、支持方均可投稿(`isSubmitterRole` = 非 admin / manager),投稿角色只能看到 / 只能改自己投的稿(后端强制 `submitter_id` 写自己);管理角色(admin / manager)查看时排除未提交草稿(`status='0'`),用于审核。
- 投稿角色投稿默认状态「未提交」,提交后进入「待审核」;
- 合规人员审核通过时填写项目编号,方案立项为正式项目。
**专项计划**`/business/specialPlan`):后台管理员维护「项目方向」选项(`/list``business:specialPlan:list` 权限;`/options` 对登录用户开放供下拉填充)。作为投稿与立项的选项来源。
### 5.5 项目管理
项目管理接口(`/business/project`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/list` | GET | 项目列表(manager 只看本人创建,leader 只看本人负责) |
| `/myProjects` | GET | 我报名的项目(`biz_execution_intent` 反查) |
| `/sponsorList` | GET | 支持方项目列表(MAIN / SUB 分流) |
| `/executorList` | GET | 执行方项目列表(主账号 / 执行人分流) |
| `/projectNoOptions` | GET | 项目编号下拉 |
| `/getInfo/{projectId}` | GET | 项目详情 |
| `/assignedSessions` | GET | 执行方建会「总场次」口径(分配给本单位的场次) |
| `/add``/edit` | POST / PUT | 新建 / 编辑项目 |
| `/remove` | DELETE | 删除项目(仅 admin,软删除级联) |
| `/announcement` | DELETE | 删除公告(admin / manager |
| `/assigns` | GET / POST / DELETE | 执行方分配(查 / 保存 / 清空) |
| `/sponsorAssign``/sponsorAssigns` | POST / GET | 支持方分配监察员 |
| `/executorAssign``/executorAssigns` | POST / GET | 执行方分配执行人 |
| `/listByRole` | GET | 按 `role_type` 查用户列表(下拉用) |
| `/sponsorAssignBatch` | POST | 支持方批量分配监察员(多项目) |
| `/rate``/ratings` | POST / GET | 项目评分(写入 / 查询) |
| `/export``/ratingExport``/signupExpertExport` | POST | 项目 / 评价 / 报名专家导出 |
**项目分配**要点:
- 合规人员(或管理员)给项目分配执行单位,按场次 + 金额拆分;已结题项目不能再分配。
- 支持方给项目分配监察员(一项目支持多名监察员);执行方给项目分配执行人。
- 分配结果会向被分配方发送站内信通知(内容未变化时不重复通知)。
**项目评分**要点:
- 评分人角色由后端按登录人 `role_type` 派生(不信任前端):admin / manager → 合规口径(`manager`),sponsor → 支持方口径(`sponsor`),其他角色不可评分。
- 评分维度 4 个:质量、响应、配合、合规。
- 聚合分 = 该角色所有评分记录 4 维度值的平均(保留 1 位小数,多人评分取平均而非覆盖),实时回写到项目 `manager_score` / `sponsor_score`
- 评分明细公开可读(任何角色可查 `GET /ratings`)。
**项目公示与意向**
- 项目发布(`is_published`)后进入门户「项目公示」。
- 公示详情页面向访客提供两个匿名意向入口:公益支持(支持意向)、项目执行申请(执行意向),接口为 `/business/publicity/supportIntent``/business/publicity/executionIntent`(提交时按 `projectId + 手机号` 查重,已登录自动回填 `user_id`)。
- 医生「立即报名」走 `/business/executionIntent/signup`(写入报名意向,按 `userId + projectNo` 查重)。
- 合规人员可查看、导出支持意向 / 执行意向数据(`/business/publicitySupportIntent``/business/publicityExecutionIntent`)。
**项目开通**
- 经理可对项目「开通」(置 `open_status=Y` 并设置开通截止日 `open_deadline`),到期(截止日 ≤ 当天)由后台每天 00:05 自动回收为「未开通」。
- 已完结且未「开通」的项目对支持方不可见(与结题状态配合,控制支持方可见范围)。
**项目金额与进度口径**(查询时实时汇总,非静态落库):
- 项目总金额 / 可用金额 / 已付劳务费 / 已付会务费为查询时实时计算(按分配与会议费用汇总反推),避免人工结算回写不一致。
- 已执行场次 / 待执行场次按项目下会议执行状态实时聚合(「冻结中」计入已执行)。
### 5.6 会议管理
会议管理接口(`/business/meeting`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/list` | GET | 会议列表(按角色数据隔离) |
| `/getInfo/{meetingId}` | GET | 会议详情(executor 返回分配给本单位的场次作为总期数) |
| `/add``/edit` | POST / PUT | 建会 / 编辑(executor 有期数上限与重复校验) |
| `/generate-poster` | POST | 生成会议日程海报(叠加会议信息 → 上传 OSS) |
| `/remove` | DELETE | 删除会议(admin / manager,软删除级联 5 张子表) |
| `/submit-material` | POST | 执行方提交材料(劳务 / 会务分轨多选) |
| `/audit-compliance` | POST | 材料一级审核(合规人员,分轨) |
| `/batch-audit-compliance` | POST | 批量材料一级审核(合规人员) |
| `/audit-supervision` | POST | 材料二级审核(支持方监察员,分轨) |
| `/settle``/finish``/unfreeze` | POST | 结算 / 完结 / 解冻(manager / admin |
| `/audit-trail` | GET | 审核轨迹(审核日志列表) |
**建会校验**(执行方):执行机构人员建会时,会议期数不得超过分配给本公司的场次;本机构已创建同项目、同期数的会议则拒绝重复;会议时间区间必须在项目起止时间区间内(闭区间)。
**参会人管理**`/business/meetingAttendee`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/unsigned` | GET | 当前用户「待签署」的会议(用于医生工作台) |
| `/invited` | GET | 当前用户「待参加」的会议 |
| `/invitation/{attendeeId}` | GET | 会议邀请函详情(仅参会人本人可见,点开即自动报名) |
| `/list/{meetingId}` | GET | 某会议全部参会人(支持方查看时脱敏) |
| `/add` | POST | 按手机号新增参会人(定位 / 新建 `sys_user` 医生账号) |
| `/edit``/remove` | PUT / DELETE | 编辑 / 删除参会人 |
| `/diff` | POST | 新增 / 编辑前比对医生档案,返回不一致字段(前端二次确认) |
| `/esign` | POST | 推送电子签(逐条发短信 + 站内信 + 置 `is_esigned` |
| `/invite` | POST | 邀请参会(逐条发站内信 + 置 `is_invited` |
| `/handsign` | PUT | 更新手写签名(Base64 |
| `/laborProtocol` | PUT | 更新劳务协议 URL(首次回填时发「待签」通知) |
| `/importTemplate``/importData` | GET / POST | 参会人批量导入(两段式:dry-run 比对 → force 入库) |
| `/export` | POST | 导出参会人档案 |
| `/agreementTemplate``/uploadAgreements` | GET / POST | 劳务协议目录模板下载 / zip 上传回填 |
| `/expertPhotoTemplate``/uploadExpertPhotos` | GET / POST | 专家照片目录模板下载 / zip 上传回填 |
参会人记录包含**签字快照**(姓名、手机号、单位、科室、职称、身份证、银行卡、开户行、账户名称等,从医生档案预填、可改)与**劳务信息**(劳务形式、应发金额、个税、实发金额、增值税及附加、摘要、现场照片),以及签字结果(手写签名、签字时间、签字 IP、劳务协议 URL、脱敏版协议 URL)。
**会议材料**`/business/meetingMaterial`,单表设计,GET 查 / PUT 全删全插):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/{meetingId}` | GET | 查该会议所有材料记录 |
| `/{meetingId}` | PUT | 保存材料(全删全插,`creator_id` 后端兜底) |
| `/saveVouchers` | POST | 合规 / 管理员随时保存付款凭证(劳务 + 会务凭证) |
| `/cameraUpload` | POST | 扫码拍照回传(H5 端直传 OSS 后回传 URL,白名单校验) |
| `/downloadZip``/downloadLaborZip` | GET | 下载会务 / 劳务材料 zipadmin / manager |
| `/batchDownloadZip``/batchDownloadLaborZip` | POST | 多会议合并下载(admin / manager |
| `/serviceTemplate``/uploadServiceMaterials` | GET / POST | 会务材料目录模板下载 / zip 上传回填 |
材料分为 4 大类、17 子类:
| 大类 | 子类 |
|---|---|
| 会务材料(SERVICE) | 物料制作、酒店、大交通、小交通、执行、设计、其他、结算、发票(`M_*` |
| 劳务材料(LABOR) | 明细、协议、企业效益、电子签到、签到表、全景、专家照片(`L_*` |
| 会务凭证(SERVICE_VOUCHER | `SV_PAYMENT` |
| 劳务凭证(LABOR_VOUCHER | `LV_PAYMENT` |
**发票识别**`/business/meeting/invoice`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/recognize` | POST | 提交发票识别(后台异步 OCR,zip 自动解压;替换场景携带 `oldMaterialId` 先清旧发票) |
| `/list` | GET | 查某会议下所有发票明细 |
**会议级分配**`/business/meeting/supervisor``/business/meeting/executor`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/business/meeting/supervisor/list/{meetingId}` | GET | 查该会议分配的监察员 |
| `/business/meeting/supervisor/{meetingId}` | PUT | 分配监察员(全删全插,传入支持方企业 `org_id` 列表) |
| `/business/meeting/executor/list/{meetingId}` | GET | 查该会议分配的执行人员 |
| `/business/meeting/executor/{meetingId}` | PUT | 分配执行人员(全删全插,传入执行方企业 `org_id` 列表) |
会议级监察员与项目级监察员共同决定「材料二级审核」的授权主体:项目级监察员 / 会议级监察机构 / 支持方主账号三类主体均可监察。
**批量上传回填机制**(劳务协议 / 专家照片 / 会务材料共用):目录模板下载 → 本地按模板归档 → zip 上传 → 后台异步解压、逐条回填。上传接口返回 `jobId`,前端轮询 `GET /business/upload/progress/{jobId}`(返回已完成 / 总数 / 是否结束 / 错误 / 结果)直至结束,拿到逐条成功 / 失败结果。
### 5.7 材料两级审核
会议材料(劳务材料 + 会务材料)提交后经两级审核,劳务 / 会务两轨独立流转:
```
执行方提交材料(分轨:劳务 LABOR / 会务 SERVICE,可多选)
→ ① 合规人员审核(一级,逐轨)
├─ 拒绝 → 退回执行方(意见必填,提交截止时间重新计算)
└─ 通过 → 进入二级
→ ② 支持方监察员审核(二级,逐轨)
├─ 拒绝 → 退回执行方并通知(待整改)
└─ 通过 → 审核通过,进入待结算(并写入监察意见)
```
- 每轨单轨状态机:`未提交(N) → 已提交待合规审(C0) → 已通过合规待支持方审(C1) → 审核通过(A)`,任一步可被 `退回(R)` 打断。
- 合规人员支持**批量审核**(一次对多个会议的合规审中材料执行同一结果,逐条处理、状态不符跳过)。
- 每次审核动作均记录审核日志,同时保存当时各角色看到的阶段状态快照,形成完整追溯链。
- 支持方监察权限与列表可见性同源:项目级监察员 / 会议级监察机构 / 支持方主账号三类主体均可监察。
### 5.8 费用汇总与结算
**费用口径**
- 劳务费 = 参会人应发金额(`fee_pre_tax`)合计;
- 会务费 = 会议发票(`M_INVOICE`)及子类发票金额合计;
- 总费用 = 劳务费 + 会务费。
**费用汇总**:材料保存 / 发票 OCR 完成后立即同步重算;后台每分钟扫描 `fee_calc_status=0` 的会议兜底重算(多线程无锁、幂等)。费用汇总状态 `fee_calc_status``0` 待汇总(费用变化后重置)、`1` 已汇总;结算要求已汇总完成(`fee_calc_status=1`)。
**结算流程**(合规人员 / 管理员手动点击):
1. 前置:劳务、会务两轨材料均已「审核通过」;
2. 前置:会议费用已汇总完成(`fee_calc_status=1`);
3. 前置:劳务凭证(`LV_PAYMENT`)、会务凭证(`SV_PAYMENT`)均已上传保存(凭证由合规人员在「凭证」标签页随时上传保存,结算时校验是否已存在);
4. 结算即终态:结算时直接落「已结算」+「已完结」标记(省去二次完结动作)。
**解冻**:会议冻结后,合规 / 管理员可手动解冻,清除冻结标记、保留冻结历史(列表据此显示「超时提交」),提交截止时间重新计算。
### 5.9 劳务电子签
参会医生在会议执行后完成劳务签署,全流程线上化。签署接口(`/business/sign`):
| 接口 | 方法 | 说明 |
|---|---|---|
| `/info?attendeeId=X` | GET | 拉取填写页全部数据 |
| `/resolve?meetingId=X` | GET | 扫码入口(只有 meetingId 时返回会议信息与参会人 id) |
| `/saveProfile` | POST | 保存医生填写的劳务字段 |
| `/contract?attendeeId=X` | GET | 拉取完整协议 HTML(占位符已替换) |
| `/submit` | POST | 提交签字(手写签名 + 协议正文 → 生成 PDF 归档) |
流程:
1. **推送电子签**:管理方在会议详情向参会医生发起电子签,医生收到短信与站内信(含签署链接)。
2. **填写劳务信息**:医生填写姓名、手机号、单位、科室、职称、身份证附件、银行卡等劳务信息。
3. **手写签名**:展示劳务协议正文,医生在手写签名画板签名确认(记录签字时间与 IP)。
4. **生成 PDF**:系统按劳务协议模板自动填入信息,生成 PDF 劳务协议并归档(同时生成脱敏版协议)。
5. **查看归档**:签署后医生可查看 / 下载签字 PDF;重复打开链接直接展示已签协议。
### 5.10 消息通知
- **站内信**`/business/message`):个人消息中心,含未读统计、单条 / 全部标记已读、详情、管理员群发与批量删除。
- **实时推送**`/business/message/stream`):SSE 实时推送当前用户的未读信号(只推「有新消息 + 未读数」信号,不带消息体),页面顶部消息铃铛即时刷新与角标消减;心跳 25 秒一条防断连。
- **短信**:关键节点(登录验证码、注册、电子签、审核结果等)短信触达。
### 5.11 内容管理
| 模块 | 接口 | 说明 |
|---|---|---|
| 协议文章 | `/business/article` | 用户协议 / 隐私政策,后台编辑启用 / 停用 |
| 支持函 | `/business/supportLetter` | 公益支持函,公示关联,可查看 / 下载 / 分享 |
| 邀请函 | `/business/invitation` | 专家参与邀请函,公示关联 |
| 劳务协议模板 | `/business/laborProtocolTemplate` | 劳务协议模板,全局共享,`default_flag='Y'` 同一时刻仅 1 条默认 |
### 5.12 工作台统计
各角色首页 / 工作台的统计指标由独立统计端点提供:
| 角色 | 端点 | 统计口径 |
|---|---|---|
| 合规人员 | `GET /business/dashboard/manager` | 项目总数、会议总数、专家总数、待办会议(未开始)、进行中会议(执行中 / 待合规 / 待支持方 / 待整改)、已办结会议(已结算 / 已完结) |
| 支持方 / 项目负责人 | `GET /business/meeting/stageStats` | 按会议阶段分组计数;支持方主账号统计本单位全部项目会议、监察员统计本人负责项目会议、项目负责人统计本人负责项目会议;前端据此算「已执行 / 未执行」 |
---
## 六、核心状态机与流程
### 6.1 项目全生命周期
```
医生注册·资质审核 → 投稿·立项 → 项目创建·分配·公示
→ 公示意向·报名 → 执行方建会·上传材料 → 医生签署劳务
→ 材料两级审核·结算·完结
```
| 环节 | 主要动作 | 责任角色 |
|---|---|---|
| 1. 注册与资质审核 | 医生提交资质,审核通过后开通账号 | 医生 / 合规人员 / 管理员 |
| 2. 投稿与立项 | 投稿策划方案,审核通过后立项 | 医生 / 执行方 / 支持方 / 合规人员 |
| 3. 项目创建与分配 | 新建项目,分配支持 / 执行单位,发布公示 | 合规人员 / 管理员 |
| 4. 公示与报名 | 门户公示,访客意向 / 医生报名 | 匿名访客 / 医生 |
| 5. 建会与材料 | 执行方建会、上传材料、提交审核 | 执行方 |
| 6. 签署劳务 | 医生电子签,生成 PDF 协议 | 医生 |
| 7. 审核结算完结 | 材料两级审核、结算、完结 | 合规人员 / 支持方 |
### 6.2 会议阶段状态机(事实 + 推导模型)
会议阶段采用「**事实 + 推导**」模型:数据库只存「事实」字段(是否执行 / 是否结算 / 是否完结 / 是否冻结 + 劳务 / 会务两轨各自审核阶段 + 合规通过标记 + 审核时间),各角色看到的「阶段名称」由后端实时推导。
**物理阶段**10 值,`current_stage` 缓存,用于列表筛选):
```
NOT_STARTED(未开始) → RUNNING / IN_PROGRESS(执行中) → 已执行
→ AWAITING_COMPLIANCE(待合规审核) → AWAITING_SUPERVISION(待支持方审核)
→ AWAITING_SETTLEMENT(待结算) → SETTLED(已结算) → FINISHED(已完结)
异常分支:RECTIFYING(待整改,退回后)、FROZEN(冻结中,逾期未提交)
```
| 物理阶段 | 中文名 | 说明 |
|---|---|---|
| NOT_STARTED | 未开始 | 会议已建,尚未到开始时间 |
| RUNNING / IN_PROGRESS | 执行中 | 已到开始时间,进行中 |
| 已执行(`is_executed=1` | 已执行 | 已到结束时间 |
| AWAITING_COMPLIANCE | 待合规审核 | 材料已提交,待合规一级审核 |
| AWAITING_SUPERVISION | 待支持方审核 | 合规通过,待支持方二级审核 |
| AWAITING_SETTLEMENT | 待结算 | 两轨审核通过,待结算 |
| SETTLED | 已结算 | 结算完成 |
| FINISHED | 已完结 | 完结 |
| RECTIFYING | 待整改 | 材料被退回 |
| FROZEN | 冻结中 | 逾期未提交被冻结 |
**时间驱动**(后台每分钟执行):
| 事件 | 结果 |
|---|---|
| 会议开始时间到 | 置「执行中」 |
| 会议结束时间到 | 置「已执行」(`is_executed=1` |
| 提交截止时间到 且 任一轨未提交 / 已退回 | 置「冻结」(`is_frozen=1` |
**单轨状态码**(劳务 / 会务各自独立):`R(退回)=0 < N(未提交)=1 < C0(待合规审)=2 < C1(待支持方审)=3 < A(通过)=4`,会议级物理阶段 = 两轨取最小进度。
**各角色展示阶段名**(同一会议,不同角色看到不同措辞):
- 固定顶格:冻结中 → 已完结 → 已结算。
- 三流程角色(执行方 / 支持方 / 合规人员)两轨合并,并按劳务 / 会务前缀区分(如「劳务待审核」「会务待整改」)。
- 待办态最高优先:合规人员优先「待合规审核」,支持方优先「待支持方审核」,执行方优先「待整改」。
### 6.3 材料审核状态机(单轨)
```
N(未提交) → C0(已提交·待合规审) → C1(合规通过·待支持方审) → A(审核通过)
↘ R(退回) ↙ —— 任一步被拒后回到 R,重新提交回到 C0
```
- 提交门槛:劳务轨 = 至少 1 名参会人;会务轨 = 至少 1 条会务材料。
- 退回后提交截止时间重新计算(now + 项目天数)。
### 6.4 结算流程
```
两轨材料审核通过(APPROVED
→ 会议费用汇总完成(fee_calc_status=1
→ 劳务凭证 + 会务凭证已上传
→ 合规人员 / 管理员点击「结算」
→ 置「已结算」+「已完结」(结算即终态)
```
### 6.5 医生注册与资质审核流程
```
医生注册(提交姓名/单位/科室/职称/执业证书/职称证书 + 短信验证码)
→ 待审核(此时不能登录)
→ 合规人员 / 管理员审核
├─ 通过 → 医生可登录,看到「我参与的会议 / 我报名的项目」
└─ 拒绝 → 通知医生补充材料重新提交
```
### 6.6 劳务电子签流程
```
管理方推送电子签(短信 + 站内信)
→ 医生扫码 / 打开链接(登录后访问)
→ 第一步:填写劳务信息(身份、银行等)
→ 第二步:手写签名确认
→ 第三步:签字成功,系统生成 PDF 劳务协议并归档
```
### 6.7 关键接口数据流转(请求示例)
核心审核链路的请求报文如下(`meetingId` 为路径参数):
| 环节 | 接口 | 请求体 |
|---|---|---|
| 提交材料 | `POST /business/meeting/{meetingId}/submit-material` | `{ "types": ["LABOR","SERVICE"] }`(劳务 / 会务分轨多选) |
| 材料一级审核 | `POST /business/meeting/{meetingId}/audit-compliance` | `{ "items": [{ "type": "LABOR", "approved": true }], "opinion": "通过" }`(拒绝时 `opinion` 必填) |
| 材料二级审核 | `POST /business/meeting/{meetingId}/audit-supervision` | 同上(`items` + `opinion` |
| 批量一级审核 | `POST /business/meeting/batch-audit-compliance` | `{ "meetingIds": [1,2], "approved": true, "opinion": "通过" }` |
| 结算 | `POST /business/meeting/{meetingId}/settle` | 无请求体(路径参数即可,前置条件由后端校验) |
| 完结 / 解冻 | `POST /business/meeting/{meetingId}/finish``/unfreeze` | 无请求体 |
建会请求体为 `BizMeeting`(会议名称、所属项目、期数、起止时间、参会人 `attendeeUserIds` 数组等);电子签签署 `POST /business/sign/submit` 提交手写签名与协议正文,生成 PDF 归档。
---
## 七、端与页面设计
### 7.1 公开门户(Web,无需登录)
首页、项目公示、公示详情、支持函详情、邀请函详情、医生注册、执行单位(供应商)注册、支持方注册、登录、协议(用户协议 / 隐私政策)、专项计划详情。
### 7.2 管理后台(Web,按角色分菜单)
| 角色 | 菜单 |
|---|---|
| 后台管理员 | 工作台、用户管理、角色管理、项目管理、会议管理、科室管理、职称管理、专家管理、支持单位管理、执行单位管理、支持单位下人员、执行单位下人员、协议管理、专项计划管理、项目类别管理、劳务协议配置、消息通知、账号信息 |
| 合规人员 | 工作台、策划方案管理、项目管理、项目分配、会议管理、专家审核、支持单位管理、执行单位管理、支持单位下人员、执行单位下人员、支持意向、执行意向、消息通知、账号管理 |
| 医生 | 首页、我参与的会议、我报名的项目、我的项目策划方案、消息通知、账号信息(隐藏页:填写劳务信息 / 签署劳务协议 / 签字成功 / 会议邀请函) |
| 执行方 | 首页、我的项目策划方案、会议列表、项目列表、人员管理、劳务凭证、消息通知、账号信息 |
| 支持方 | 首页、我的项目策划方案、项目管理、我的项目、会议列表、人员管理、消息通知、账号信息 |
| 项目负责人 | 首页、项目列表、会议列表、消息通知、账号信息 |
### 7.3 移动端(H5
- **扫码签署**:医生扫码进入劳务电子签,完成填写信息与手写签名。
- **拍照上传**:身份证正反面、签到表等现场照片,通过移动相机采集并上传(后端白名单校验后归档,签到表自动生成高斯模糊脱敏版)。
- **兼容手机浏览器**:无需安装 App,扫码即用。
---
## 八、关键技术能力
| 能力 | 说明 |
|---|---|
| 发票自动识别 | 上传发票图片(或 zip),后台异步 OCR 识别金额等字段,减少人工录入 |
| 对象存储 | 材料、凭证、PDF 协议、海报等文件统一云端存储,可预览 / 下载 / 打包 |
| 短信服务 | 登录验证码、注册、电子签、审核结果等关键节点短信触达 |
| 微信分享 | 邀请函 / 支持函等生成 PDF 与分享链接,便于微信传播 |
| 实时消息 | 站内信 SSE 实时推送,顶部角标即时更新 |
| 数据脱敏 | 签到表、参会人敏感信息(手机、银行卡、身份证)展示时自动打码,支持方只见脱敏版 |
| OA 对接 | 新建项目时按项目编号拉取 OA(ecology)项目信息自动回填 |
| 海报生成 | 会议日程海报自动生成并叠加会议信息 |
| 供应商账号同步 | 从外部供应商平台定时拉取账号(加密传输),自动同步到执行方机构 / 人员 / 登录账号 |
### 8.1 外部数据集成
- **OAecology)项目信息拉取**:新建项目时按项目编号从 OA 拉取项目信息自动回填。
- **供应商账号同步**:后台定时从外部供应商平台拉取账号(传输加密、本地解密),按邮箱自动同步到执行方机构、人员与登录账号,避免人工重复录入;触发时机为系统启动后立即全量(近 30 天)、每分钟增量(近 5 分钟)、每晚 2 点全量。
---
## 九、数据设计概览
数据模型按业务域划分,详见配套文档《数据库设计文档 V2.0》:
| 域 | 主要表 |
|---|---|
| 组织与人员 | 机构、人员、医生(专家)、科室、职称 |
| 项目 | 项目、执行方分配、支持方分配、执行方(执行人)分配、策划方案、专项计划、项目评分 |
| 公示与意向 | 项目公告、支持意向、执行意向、报名意向 |
| 会议 | 会议、参会人、材料、发票、执行人员、监察员、审核日志、结算、邀请函、劳务电子签、劳务协议模板 |
| 内容与消息 | 协议文章、资源、消息、支持函 |
设计要点:
- 业务表统一逻辑删除,删除后保留记录、可追溯。
- 主键采用雪花 ID / 自增 ID,关键编号(如凭证编号)唯一。
- 金额统一保留两位小数。
- 开关 / 状态字段采用「是 / 否」或「启用 / 停用」等明确取值(`char(1)``Y` / `N`)。
- 参会人、凭证等采用快照机制,与源数据解耦,保证历史归档稳定。
### 9.1 核心实体字段速览
> 以下仅列业务关键字段,字段类型、约束、索引详见《数据库设计文档 V2.0》。
- **项目**:项目编号、项目名称、项目形式、总场次、总金额、可用金额、已付劳务费、已付会务费、已执行 / 待执行场次、管理费及税金、角色劳务设置、起止时间、提交材料截止天数、支持方企业、项目负责人、是否招标、支持合同 / 执行合同 / 邀请函 / 支持函 / 公示 / 日程文件、是否完结、是否结算、是否发布、发布时间、开通状态、开通截止日、合规评分、支持方评分。
- **会议**:会议名称、所属项目、项目编号、业务 ID、项目形式、执行方归属、开始 / 结束时间、总期数、期数、地址、备注、当前阶段、劳务 / 会务审核阶段、是否执行 / 结算 / 完结 / 冻结及对应时间、提交截止时间、监察意见 / 监察人 / 监察时间、邀请函 / 日程 / 海报文件、劳务费用、会务费用、总费用、费用汇总状态、劳务签署标记。
- **机构**:机构名称、机构类型(支持方 / 执行方)、主账号、企业性质、地址、税号、联系人、联系电话、状态、意向次数(支持方)、同步来源标记。
- **人员**:姓名、手机号、所属公司、部门、职务、关联登录账号、邮箱、账号类型(主 / 子)、主账号、启停状态。
- **策划方案**:方案名称、项目方向(专项计划)、类别、项目形式、设计文件、学科方向、状态、是否结算、项目编号、审核意见 / 审核人 / 审核时间、投稿人、提交时间。
- **项目评分**:项目、评分人、评分人角色、质量 / 响应 / 配合 / 合规四维得分、备注、评分时间。
- **公示意向(支持 / 执行)**:项目、姓名、手机号、工作单位、部门、职务、来源、意向状态、备注(支持匿名提交)。
- **报名意向**:用户、项目、姓名、工作单位、部门、职务、手机号、入职状态。
- **消息**:接收人、类型(通知 / 待办 / 系统)、标题、内容、业务类型、关联业务 ID、已读标记、已读时间。
- **会议审核日志**:会议、审核人、意见、审核类型(材料 / 凭证)、审核结果(通过 / 退回)、材料类型、各角色当时展示状态快照、审核时间。