Files
guoju0808/测试设计方案.md
郭庆泰 5a0a892574 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) 入库
2026-09-10 20:40:49 +08:00

34 KiB
Raw Permalink Blame History

测试设计方案(内部)

版本:V2.0 读者:研发 / 测试 / QA(内部文档,含风险、覆盖缺口、遗留问题) 被测系统:合规管理平台(六角色全流程协同,前后端分离 + H5 移动端) 配套文档:《详细设计方案 V2.0》《数据库设计文档 V2.0》《待优化遗留项》


0. 阅读约定

  • 所有接口路径均以 /business 为前缀(完整示例:POST /business/auth/smsLogin)。
  • 所有「预期结果」中标注的错误文案均取自后端 Controller 源码中的 AjaxResult.error(...) 字面量,测试时以 msg 字段为准,逐字比对
  • HTTP 语义:本系统所有业务接口统一返回 HTTP 200 + AjaxResult 结构体 {code, msg, data}成功 code=200、失败 code=500(部分全局异常/无权限由框架返回 401/403)。本文「预期结果」中提到的 code 均指 AjaxResult.code,除非特别注明 HTTP 状态码。
  • 「返回体结构」统一约定:列表接口返回 {code, msg, total, rows};详情/操作返回 {code, msg, data};错误返回 {code:500, msg:"<错误文案>"}

1. 测试目的与范围

1.1 测试目的

  1. 验证六类角色(后台管理员 / 合规人员 / 医生 / 执行方 / 支持方 / 项目负责人)的功能正确性数据隔离正确性
  2. 验证会议「事实 + 推导」状态机、材料两级审核、费用汇总与结算等核心业务规则符合设计。
  3. 验证短信登录、注册、电子签、OCR、供应商同步、OA 对接等跨服务 / 跨系统链路的可用性与容错。
  4. 在验收前暴露高风险缺陷,明确覆盖缺口与遗留问题,为回归与验收提供依据。

1.2 测试范围(范围内)

功能域 覆盖内容
账号与认证 短信验证码登录、三类注册、登录状态与角色跳转
角色权限与数据隔离 六角色权限矩阵、主 / 子账号隔离、越权拦截、数据脱敏
专家管理 建档、启用/停用、查询回填、导入导出
机构 / 人员管理 机构、人员、供应商账号同步
策划方案与专项计划 投稿、审核、立项、专项计划维护
项目管理 立项、分配(执行方 / 监察员 / 执行人)、公示、意向、报名、评分、项目开通
会议管理 建会校验、参会人、材料、发票、海报、会议级分配
材料两级审核 提交、一级审核、二级审核、批量审核、退回重算、审核日志
费用与结算 费用口径、费用汇总、结算 / 完结 / 解冻
劳务电子签 推送、填写、手写签名、PDF 归档
消息中心 列表、未读、已读、SSE 推送

1.3 测试范围(范围外 / 不覆盖)

原因
单元测试 / 接口自动化脚本 本方案为手工测试设计,不含自动化用例代码
生产环境数据迁移校验 由 DBA 单独负责(见《数据库设计文档 V2.0》)
性能压测(并发量级、TPS 阈值) 仅做功能级性能冒烟(见 §5
安全渗透 / 代码审计 由安全团队单独进行,本方案只覆盖权限与越权功能面

2. 测试环境与测试数据

2.1 测试账号矩阵(基础账号,后续用例引用)

统一短信验证码:固定测试码 123456(测试环境短信网关 mock,发码后固定回 123456,验证码有效期 5 分钟)。 账号状态列 audit_status'1'=待审核(拦截登录)、'2'=通过(可登录)、'3'=拒绝;biz_expert.status'Y'=正常、'N'=禁用。smsLogin"您的信息正在审核中" 的判定值为 audit_status='1'

编号 角色 用户名 手机号 role_type account_type 关键字段 / 备注
U01 后台管理员 admin 13800000000 admin MAIN 框架管理员,可访问 admin 全部菜单
U02 合规经理 manager01 13800000002 manager MAIN create_user_id=U02
U03 医生(已通过) doctor01 13800000001 doctor MAIN audit_status='2'
U04 医生(待审核) doctor02 13800000003 doctor MAIN audit_status='1'
U05 执行方主账号 execmain 13800000010 executor MAIN exec_user_id=U05, execution_unit_id=EU1
U06 执行方子账号 execsub 13800000011 executor SUB parent_user_id=U05, staff_user_id=U06
U07 支持方主账号 sponsormain 13800000020 sponsor MAIN sponsor_admin_user_id=U07, sponsor_org_id=SO1
U08 支持方子账号 sponsorsub 13800000021 sponsor SUB parent_user_id=U07, monitor_user_id=U08
U09 项目负责人 leader01 13800000030 leader MAIN lead_user_id=U09
U10 执行方子账号2 execsub2 13800000012 executor SUB parent_user_id=U05, staff_user_id=U10
U11 支持方子账号2 sponsorsub2 13800000022 sponsor SUB parent_user_id=U07, monitor_user_id=U11

2.2 基础业务数据(测试前置,一次性准备)

数据 字段值 说明
机构(支持方)SO1 org_id=SO1, org_name="XX医药支持机构", status='0'(启用) sponsor 主/子账号挂靠
执行单位 EU1 execution_unit_id=EU1, name="XX执行单位" executor 主/子账号挂靠
项目 P1 project_no="P202609001", create_user_id=U02, 总场次 totalSessions=10, is_published='Y' 由 U02 立项
项目 P2 project_no="P202609002", create_user_id=U02, is_published='N' 未发布,用于公示过滤用例
项目 P3 project_no="P202609003", create_user_id=U02, is_finished='Y' 已结题,用于「已结题不能分配」用例
会议 M1 meeting 属于 P1, 第 1 期, is_executed=0 未执行,用于建会/参会人/材料用例
会议 M2 属于 P1, 第 2 期, is_executed=1, laborAuditStage=4, serviceAuditStage=4, fee_calc_status=1, 凭证已传 已执行且可结算,用于结算用例
会议 M3 属于 P1, 第 3 期, is_frozen=1 已冻结,用于「冻结不能提交材料」用例
专家 E1 expert_id=E1, name="王医生", phone=13800000001, status='0'(启用), title="主任医师", dept="心内科" 供参会人回填、评分用例

2.3 数据准备 / 清理规则

  • 准备:每轮回归前,按 §2.2 用 admin 或 manager 账号在界面/接口建好基础数据;短信验证码固定 123456
  • 清理:费用结算、评分、意向等有状态流转的用例,执行前先重置目标对象状态(见各用例「前置条件」的还原说明),避免用例间互相污染。
  • 原则:涉及唯一性约束的用例(如「本机构已创建第 X 期会议」),先删掉同名对象再执行,保证可重复。

3. 测试策略

3.1 分层策略

层级 内容 手段
L1 功能测试 每个用例逐条验证接口/界面行为 手工 + 接口联调(Postman/Apifox
L2 业务规则测试 状态机、审核链、费用口径、结算前置 场景组合(§4 核心用例)
L3 权限/隔离测试 六角色越权、主/子账号隔离、脱敏 交叉矩阵(§4.3、§4.5
L4 链路测试 短信、OCR、OSS、电子签、SSE、供应商同步 端到端(§4.9、§4.11、§5

3.2 优先级定义

优先级 定义 举例
P0 核心主流程,阻塞验收 登录、建会、结算、材料审核
P1 重要业务规则/权限隔离 越权、状态机、费用口径、脱敏
P2 一般功能/边界 分页、排序、字段回显、提示文案
P3 次要/低频 导出、日志、操作留痕

3.3 判定标准

  • 每条用例结果分 Pass / Fail / Block(阻塞)/ NA(不适用)
  • 一条用例 Pass 的标准:实际返回/表现与「预期结果」完全一致,包括错误文案逐字一致、code 一致、字段值与脱敏规则一致。
  • 出现任何一条 P0 用例 Fail → 该模块不可验收;P1 用例存在未关闭的 Fail → 整体验收不通过。

4. 分模块测试设计

每个模块给出「测试点清单」(全部要点)+「代表用例」(展开到可逐行执行的步骤)。代表用例是本文的核心,覆盖最高风险路径。

4.1 登录与账号体系(M1

测试点清单

编号 测试点
M1-01 已注册手机号发码成功,未注册手机号发码报错
M1-02 验证码登录成功返回 JWTrole_type 驱动跳转
M1-03 医生 audit_status='0' 登录拦截
M1-04 停用/删除账号登录拦截
M1-05 执行方/支持方子账号在主账号停用/机构禁用时的拦截
M1-06 执行方注册(校验链 + 密码/用户名规则)
M1-07 支持方注册(企业/角色校验)
M1-08 验证码错误、过期、手机号格式错误

代表用例 M1-02-01:验证码登录成功(医生)

  • 前置U03doctor01 / 13800000001audit_status='1')存在且启用。
  • 步骤
    1. POST /business/auth/smsSendCode,请求体 {"phone":"13800000001"}
      • 预期:{code:200, msg:"发送成功", data:...}data 含 uuid
    2. 取出 uuidPOST /business/auth/smsLogin,请求体 {"phone":"13800000001", "smsCode":"123456", "uuid":"<第1步uuid>"}
      • 预期:{code:200, msg:"登录成功", data:{token:"<JWT>"}}data.token 非空;后续请求携带 Authorization: Bearer <token> 可正常访问医生首页。
    3. GET /business/auth/getInfo(携带 token)。
      • 预期:data.user.roleType == "doctor",前端据此跳转医生首页。

代表用例 M1-03-01:待审核医生登录拦截

  • 前置U04doctor02 / 13800000003audit_status='0')。
  • 步骤:发码后 POST /business/auth/smsLogin {"phone":"13800000003","smsCode":"123456","uuid":...}
  • 预期{code:500, msg:"您的信息正在审核中"};不返回 token;登录失败。

代表用例 M1-04-01:停用/删除账号登录拦截(错误文案覆盖)

  • 前置:分别准备「已删除」账号(del_flag='2')与「已停用」账号(status='1')。
  • 步骤:对两个账号分别发码登录。
  • 预期:删除账号 → msg:"账号已被删除";停用账号 → msg:"账号已被停用"

代表用例 M1-06-01:执行方注册——用户名/密码规则校验链

  • 步骤POST /business/auth/registerExecutor,逐条发送以下 body 并断言 msg:
    1. {"username":"ab","unitName":"XX","businessNature":"服务商","phone":"13900000001","smsCode":"123456","password":"123456","confirmPassword":"123456","uuid":...}msg:"用户名长度 4-20 位"
    2. {"username":"a b!","...同1}msg:"用户名只能包含字母/数字/下划线"
    3. {"username":"valid01","unitName":"","...}msg:"企业名称不能为空"
    4. {"username":"valid01","unitName":"XX","businessNature":"","...}msg:"企业性质不能为空"
    5. {"username":"valid01","unitName":"XX","businessNature":"服务商","password":"123","confirmPassword":"123",...}msg:"密码长度 6-20 位"
    6. 密码 123456 / 确认 654321msg:"两次密码输入不一致"
    7. phone 填已注册手机号 → msg:"该手机号已注册, 请直接登录"
    8. username 填已占用用户名 → msg:"用户名已被占用: <用户名>"
    9. 全部合法 → {code:200},且自动创建 sys_user。

代表用例 M1-07-01:支持方注册——企业/角色校验链

  • 步骤POST /business/auth/registerSponsor,逐条断言:
    1. 缺少 orgIdmsg:"请选择企业"
    2. 缺少 realNamemsg:"请输入联系人姓名"
    3. orgId 不存在 → msg:"所选企业不存在"
    4. orgId 指向非支持方机构 → msg:"所选企业不是支持方"
    5. 全部合法 → {code:200}

4.2 专家管理(M2

测试点清单

编号 测试点
M2-01 admin 建档(同建 sys_user,用户名/密码=手机号)
M2-02 启用/停用专家(同步 biz_expert.status + sys_user.status
M2-03 按手机号查询回填(命中返回档案,未命中返回 null)
M2-04 profile 按当前登录用户路由
M2-05 编辑(注意:不改动 expertId,否则后端 WHERE 失效)
M2-06 导入(dry-run 预检 / force 覆盖)

代表用例 M2-01-01admin 建档专家

  • 步骤POST /business/expertbody {"name":"李医生","phone":"13800000004","dept":"神经内科","title":"副主任医师","status":"0"}
  • 预期{code:200, data:{...sys_user 含明文 password}};库中 biz_expert 新增一条,且 sys_user.user_name=13800000004sys_user.password=13800000004 对应的 BCrypt 密文。

代表用例 M2-03-01:手机号放大镜回填

  • 步骤
    1. GET /business/expert/byPhone/13800000001 → 预期 data 为 E1 档案。
    2. GET /business/expert/byPhone/19999999999 → 预期 data == null,前端不报错、显示「未找到」。

代表用例 M2-05-01:编辑专家(回归已知缺陷)

  • 前置E1 存在。
  • 步骤PUT /business/expertbody 带 expertId=E1、修改 dept="心内科二区"必须携带原 expertId)。
  • 预期{code:200},库中 E1.dept 已更新;expertId 字段不被清空。

4.3 机构 / 人员管理(M3

测试点清单

编号 测试点
M3-01 机构启用/停用对子账号登录的影响
M3-02 人员(biz_person)显示登录账号(join sys_user
M3-03 供应商账号同步(开放接口账号密码校验链)

代表用例 M3-01-01:机构停用后子账号登录拦截

  • 前置U07/U08 挂靠 SO1;先验证 U08 可正常登录。
  • 步骤admin 停用 SO1status='1')→ U08 再次发码登录。
  • 预期msg:"您所属的机构已禁用",登录失败。恢复 SO1 后可再次登录。

代表用例 M3-02-01:人员列表显示登录账号

  • 步骤GET /business/person/listmanager)。
  • 预期:行数据含 account 字段(来自 sys_user.user_name),与 loginUsername 字段命名不冲突;未绑 sys_user 的人员 account 为空。

4.4 项目管理(M4

测试点清单

编号 测试点
M4-01 manager 只见自己 create_user_id 的项目
M4-02 sponsor 主/子账号项目可见性(sponsorAdminUserId / monitorUserId 反查)
M4-03 executor 主/子账号项目可见性(execUserId / staffUserId 反查)
M4-04 项目删除(仅 admin;软删除级联)
M4-05 分配执行方/监察员/执行人(参数必填 + 已结题拦截)
M4-06 公示过滤(按 is_published
M4-07 评分(角色限制 + 聚合口径 sum/(count×4)
M4-08 项目开通(openStatus / openDeadline

代表用例 M4-04-01:项目删除权限与软删级联

  • 步骤
    1. U09leaderDELETE /business/project/{P1} → 预期 {code:500, msg:"只有管理员可删除项目"}
    2. U01adminDELETE /business/project/{P1} → 预期 {code:200}
    3. 断言级联:biz_project、项目关联的 5 张分配表、会议链记录 is_deleted 均为软删标记(非物理删除)。

代表用例 M4-05-01:已结题项目不能分配

  • 前置P3is_finished='Y')。
  • 步骤POST /business/project/saveAssignsbody 含 projectId=P3
  • 预期msg:"已结题项目不能分配";未写入分配表。

代表用例 M4-05-02:分配参数必填校验

  • 步骤
    1. sponsorAssign 缺 monitorUserIdsmsg:"monitorUserIds 必填"(或 "monitorUserId 必填")。
    2. executorAssign 缺 staffUserIdsmsg:"staffUserIds 必填"(或 "staffUserId 必填")。
    3. 批量分配传空数组 → msg:"请提供至少一个分配记录"

代表用例 M4-07-01:评分聚合口径

  • 前置:P1 已有 2 条评分(分值为 4、4)。
  • 步骤U02managerPOST /business/project/ratebody {"projectId":"P1","score":4}
  • 预期data.score == 4.0(4+4+4)/(3×4)=1.0 → ×4 = 4.0,四舍五入保留 1 位)。
  • 反向U03doctor)评分 → msg:"当前角色不可评分";缺 projectId → msg:"projectId 必填"

4.5 会议管理(M5)—— 状态机核心

测试点清单

编号 测试点
M5-01 建会校验链(projectId 必填、期数上限、重复期数、时间窗)
M5-02 删除会议(仅 admin / 合规经理)
M5-03 阶段推导(劳务/会务两轨 min 汇总;FROZEN 仍算已执行)
M5-04 提交材料前置(非执行方 / 未执行 / 已冻结拦截)
M5-05 一级审核 / 二级审核(合规人 / 监察员权限 + 拒绝意见必填)
M5-06 批量审核(返回 successCount/failCount
M5-07 会议级分配与批量上传回填
M5-08 sponsor 会议详情脱敏

代表用例 M5-01-01:建会校验链(逐条断言)

  • 前置:P1 总场次=10,已建 0 场;P1 开始时间 2026-09-01、结束时间 2026-09-30。
  • 步骤POST /business/meeting,逐条断言:
    1. projectIdmsg:"建会必须指定 projectId"
    2. projectId 存在但 meetingNo(期数)填 11 → msg:"期数不能超过分配给本公司的场次 (共 10 场)"
    3. 首次建第 1 期成功 → 再次建第 1 期 → msg:"本机构已创建第 1 期会议, 请勿重复"
    4. 会议开始时间早于项目开始 → msg:"会议开始时间不能早于项目开始时间";结束晚于项目结束 → msg:"会议结束时间不能晚于项目结束时间"
  • 上限分支:把「分配给本公司场次」调成 1,建满后 → msg:"本项目分配给本公司的场次为 1 场, 已建 1 场, 已达上限"

代表用例 M5-03-01:阶段推导(两轨 min

  • 前置M1 处于 laborAuditStage=4(A/已审核) + serviceAuditStage=1(N/待审核)。
  • 步骤GET /business/meeting/{M1}manager)。
  • 预期:会议级 stage == 服务轨 min1),而非 4is_executed 保持推导值。

代表用例 M5-04-01:提交材料前置拦截

  • 步骤POST /business/meeting/submit-materialbody {"meetingId":"M1","types":["LABOR"]},逐条断言:
    1. 以 U02(非执行方)提交 → msg:"您不是该项目的执行方, 无法提交材料"
    2. 以 U05(执行方)对「未执行会议」提交 → msg:"会议尚未执行, 不能提交材料"
    3. 以 U05 对 M3(已冻结)提交 → msg:"会议已冻结, 不能提交材料"
    4. types 为空 → msg:"请选择要提交的材料类型"
    5. types 含 "XXX"msg:"未知材料类型: XXX"
    6. types 只含 "SERVICE" 且无会务材料 → msg:"会务材料至少上传一条"
    7. 提交 "LABOR" 但会议无参会人 → msg:"请先添加参会人员 (劳务材料)"

代表用例 M5-05-01:二级审核权限与拒绝意见

  • 步骤
    1. 非合规人 POST /business/meeting/audit-compliancemsg:"仅合规人员可操作"
    2. 合规人提交 items=[{type:"LABOR",approved:false}]opinion 为空 → msg:"拒绝时意见不能为空"
    3. 非监察员 POST /business/meeting/audit-supervisionmsg:"您不是该会议监察员, 无权监察"

代表用例 M5-06-01:批量审核返回统计

  • 前置M1、M2 均处于待一级审核。
  • 步骤POST /business/meeting/batch-audit-compliancebody {"meetingIds":["M1","M2"],"approved":true,"opinion":"通过"}
  • 预期data == {total:2, successCount:2, failCount:0, failures:[]};两会议审核状态推进。

代表用例 M5-08-01sponsor 会议详情脱敏

  • 前置:M1 有参会人(姓名李小明、手机号 13800000005、银行卡 6222000000000000、身份证 110101199001011234)。
  • 步骤GET sponsor 视角会议详情 / 参会人列表(走 maskForSponsor)。
  • 预期
    • maskName:李小明→李*明;张三→张*
    • maskPhone138****0005(前3+****+后4)。
    • maskBankCard6222********0000
    • maskIdCard110101********1234
    • 操作区只读、身份证附件列隐藏。

4.6 参会人管理(M6

测试点清单

编号 测试点
M6-01 邀请函打开即报名(权限校验)
M6-02 新增参会人(劳务费字段)
M6-03 编辑锁定(劳务已提交后不可改)
M6-04 导入(dry-run 预检 vs force 覆盖,返回 ngList
M6-05 劳务费= fee_pre_tax 合计口径

代表用例 M6-01-01:邀请函打开即报名

  • 前置M1 下存在参会人 A1attendee_id=A1)。
  • 步骤
    1. GET /business/meetingAttendee/invitation/{A1}(无权限用户)→ msg:"无权限查看该邀请函"
    2. GET /business/meetingAttendee/invitation/999999msg:"参会记录不存在"
    3. 合法用户 GET .../invitation/{A1}{code:200},且该参会人报名状态变为已报名。

代表用例 M6-03-01:劳务已提交后不可修改参会人

  • 前置M1 已提交劳务材料。
  • 步骤PUT /business/meetingAttendeebody 修改 A1 的 feePreTax
  • 预期msg:"劳务已提交, 不能修改参会人";或 checkAttendeeEditable 返回不可编辑标记,前端禁用编辑。

代表用例 M6-04-01:导入预检与覆盖

  • 前置:准备参会人 Excel(含手机号/姓名/工作单位等,其中 1 条手机号与现有参会人冲突)。
  • 步骤
    1. dry-run 模式导入 → 预期返回 {total, mismatches}mismatches 列出冲突行,不落库
    2. force 模式导入 → 预期返回 ImportResult {okNum, ngNum, ngList}okNum 为成功数、ngList 为失败明细。

4.7 材料与凭证(M7

测试点清单

编号 测试点
M7-01 凭证上传权限(仅合规/管理员)
M7-02 拍照上传白名单(L_PANORAMA 拆 FRONT/BACK
M7-03 打包下载权限(会务/劳务)
M7-04 会务材料上传异步 jobId

代表用例 M7-01-01:凭证上传权限

  • 步骤U03(医生)POST /business/meetingMaterial/saveVouchersmsg:"只有合规或管理员可上传凭证"
  • 预期:U01/U02 可正常上传并返回 code 200。

代表用例 M7-03-01:打包下载权限

  • 步骤U03 GET /business/meetingMaterial/downloadZip?meetingId=M1 → 拦截;U02 同请求 → 返回 zip 流。
  • 预期:劳务材料同理(downloadLaborZip),仅管理员/合规经理可下载。

4.8 费用与结算(M8

测试点清单

编号 测试点
M8-01 劳务费=参会人 fee_pre_tax 合计
M8-02 会务费=总发票(M_INVOICE)合计(覆盖 SUB
M8-03 fee_calc_status 门控(未汇总完成不能结算)
M8-04 结算前置(两轨 APPROVED + 凭证上传)
M8-05 结算即终态(settle 自动 finish
M8-06 完结/解冻权限与前置

代表用例 M8-03-01:费用未汇总完成不能结算

  • 前置:M2 两轨已审核通过 + 凭证已传,但 fee_calc_status=0
  • 步骤U01 POST /business/meeting/settle body {"meetingId":"M2"}
  • 预期msg:"会议费用尚未汇总完成,无法结算"。等 FeeCalcScheduler 汇总至 fee_calc_status=1 后再结算 → 成功。

代表用例 M8-04-01:结算前置校验(逐条)

  • 步骤:对 M2 依次制造缺失条件,逐个断言:
    1. 非合规/管理员 → msg:"只有合规或管理员可结算"
    2. 仅劳务轨通过 → msg:"劳务与会务材料都审核通过后才能结算"
    3. 已结算后再次结算 → msg:"会议已结算"
    4. 缺劳务凭证 → msg:"请先上传劳务凭证";缺会务凭证 → msg:"请先上传会务凭证";都缺 → msg:"请先上传劳务凭证与会务凭证"

代表用例 M8-05-01:结算即终态

  • 步骤M2 满足全部前置后 POST .../settle
  • 预期{code:200};库中 is_settled=1is_finished=1,会议进入已完结终态,不可再结算/完结。

代表用例 M8-06-01:完结/解冻

  • 步骤
    1. 未结算会议 POST .../finishmsg:"会议尚未结算, 不能完结"
    2. 已完结再次 finish → msg:"会议已完结";非合规人 → msg:"只有合规或管理员可完结"
    3. 未冻结会议 POST .../unfreezemsg:"会议未冻结, 无需解冻";非合规人 → msg:"只有合规或管理员可解冻"

4.9 电子签章(M9

测试点清单

编号 测试点
M9-01 sign info / resolve 查询
M9-02 saveProfile 保存参保信息
M9-03 contract 返回 HTML
M9-04 submit 手写签名 + 内容 + X-Real-IP

代表用例 M9-04-01:提交签名

  • 前置A1 已报名且处于可签署状态。
  • 步骤POST /business/sign/submit?attendeeId=A1header 加 X-Real-IP: 1.2.3.4body {"handsign":"data:image/png;base64,...","contentHtml":"<html>...</html>"}
  • 预期{code:200};库中签名记录落库,labor_signed 相关状态推进(若已接线);IP 字段记录 1.2.3.4。

4.10 策划方案 / 专项计划(M10)

测试点清单

编号 测试点
M10-01 投稿角色只见自己 submitter_id 的稿
M10-02 投稿角色新建/编辑强制 submitter_id 写自己
M10-03 管理角色排除 status='0' 草稿
M10-04 专项计划 status 0/1 语义

代表用例 M10-01-01:投稿角色数据隔离

  • 步骤U03doctorGET /business/projectPlan/list
  • 预期:返回行全部 submitterId == U03;不包含其他医生投稿。

代表用例 M10-02-01:越权篡改 submitter 被后端强制覆盖

  • 步骤U03 POST /business/projectPlanbody 里 submitterId 故意写 U04。
  • 预期:落库 submitter_id 被后端强制改为 U03(controller 覆盖),且 status 缺省为 '0'

代表用例 M10-03-01:管理角色排除草稿

  • 步骤U02managerGET /business/projectPlan/list
  • 预期:不返回任何 status='0' 的未提交草稿,仅返回已提交稿。

4.11 消息中心与 SSEM11

测试点清单

编号 测试点
M11-01 my 分页/快捷模式返回 {rows, unread, total}
M11-02 单条已读(归属校验)
M11-03 详情归属校验(非管理员只能看自己的)
M11-04 管理员发送(接收人/标题必填)
M11-05 SSE 推送不弹窗、静默刷新 + 角标

代表用例 M11-02-01:已读归属校验

  • 前置U03 有一条消息 msgId=MSG1receiver=U03)。
  • 步骤U02 PUT /business/message/read/MSG1
  • 预期msg:"消息不存在或无权操作",MSG1 未读状态不变。U03 自己操作 → code 200。

代表用例 M11-04-01:管理员发送校验

  • 步骤U01 POST /business/message
    1. receiverUserIdmsg:"接收人不能为空"
    2. titlemsg:"标题不能为空"
    3. 合法 → code 200。

代表用例 M11-05-01:SSE 推送不打扰用户

  • 步骤:U03 登录并订阅 SSE;触发一条发送给 U03 的消息。
  • 预期:前端不弹 ElNotification,仅列表静默刷新 + 未读角标自增;重新进入后角标随已读动作递减。

4.12 公示意向(M12

测试点清单

编号 测试点
M12-01 公示页匿名意向按钮落库到 publicity_support_intent / publicity_execution_intent
M12-02 SUB sponsor 可见性 UNION publicity_support_intent + sponsor_assign
M12-03 意向数据不混入登录视角强绑表

代表用例 M12-01-01:匿名意向落库隔离

  • 步骤:公示页点「支持意向」→ 落库 biz_publicity_support_intent;点「执行意向」→ 落库 biz_publicity_execution_intent
  • 预期:两张表独立、互不写入 biz_support_intent(已删表)或登录强绑表;同一用户可分别产生两类意向记录。

5. 非功能测试

类别 测试点 方法 通过标准
性能冒烟 项目/会议列表查询耗时 200 条数据下 GET .../list 响应 < 2s,无明显 N+1 慢查询
性能冒烟 OCR 识别单张发票 上传标准发票图片 无异常、结果可读(已知瓶颈 8–10s,记录即可)
兼容 六角色主要页面在 Chrome/Edge 正常 手工走查 无 JS 报错、布局正常
移动端 H5 相机拍照上传、无 margin 二次叠加 真机/模拟器 拍照回传、页面无 2x 间距
容错 短信/OCR/OSS 服务不可用 断点注入 后端返回友好错误、前端有 toast、不白屏
安全-功能面 越权访问他人数据、主/子账号越界 §4.3/§4.5 交叉矩阵 全部拦截

6. 已知风险与覆盖缺口(GAP

来源于《待优化遗留项》与代码走查,测试时必须把以下项作为「已知风险」显式记录到缺陷/风险表,不能按「通过」处理。

编号 风险 / 缺口 影响 测试时的处理
GAP-1 biz_special_plan.status / biz_doctor_title.status / biz_org.status / sys_user.status / biz_project_assign.status 仍为 0/1,与新 Y/N 约定不一致 0/1 语义各表不同,易误判 逐表查 COLUMN_COMMENT 确认语义后再断言,不要照搬 Y/N 方向
GAP-2 biz_project_plan.is_finished 是死字段(无列、无映射) 接口/前端若读它恒为空 断言该字段应被移除;出现读取即 Bug
GAP-3 biz_meeting.is_finished 是 tinyint 0/1(与项目级同名不同型) 会议/项目状态判断不一致 会议侧按 0/1 断言,项目侧按 Y/N 断言
GAP-4 biz_meeting.labor_signed 签署链路未接线(全库恒 N,无 setLaborSigned 调用) 「签署劳务」动作未实现 M9 用例标注为 NA/Block,待实现后补测;落库值应为 'Y'
GAP-5 执行方子账号项目可见性走 staff_user_id 反查,需严格隔离 子账号可能看到非本人项目 M4-03 需覆盖子账号 A/B 互不可见
GAP-6 缴费口径两态无锁 + FeeCalcScheduler 每分钟 并发下可能重复/遗漏汇总 M8-03 覆盖「汇总中」「汇总完成」两态门控
GAP-7 sponsor 会议详情脱敏复用 labor_protocol_masked(未 alter table 若列不存在则脱敏失效 M5-08 断言列存在且打码正确

7. 验收准出标准

  1. 所有 P0 用例 100% Pass(无 Block/NA 说明未实现且已登记)。
  2. P1 用例 Pass 率 ≥ 98%,未关闭 Fail 需有明确责任人与修复计划。
  3. 每个 GAP 项均已登记,并明确「已处理 / 遗留 + 计划」。
  4. 缺陷单完整:每条 Fail 有可复现步骤、实际结果、预期结果、截图/接口响应。
  5. 回归通过:P0 全量 + 受影响模块 P1 重跑通过后,方可验收。

8. 附录:接口/文案速查(供测试断言)

模块 接口 关键错误文案
登录 POST /business/auth/smsLogin 手机号格式错误 / 请输入短信验证码 / 验证码错误或已过期 / 用户不存在 / 账号已被删除 / 账号已被停用 / 所属主账号不存在, 请联系管理员 / 您所属的机构已禁用 / 您的信息正在审核中
注册 POST /business/auth/registerExecutor 用户名长度 4-20 位 / 用户名只能包含字母/数字/下划线 / 企业名称不能为空 / 企业性质不能为空 / 密码长度 6-20 位 / 两次密码输入不一致 / 该手机号已注册, 请直接登录 / 用户名已被占用: X
注册 POST /business/auth/registerSponsor 请选择企业 / 请输入联系人姓名 / 所选企业不存在 / 所选企业不是支持方
项目 POST /business/project/rate projectId 必填 / 当前角色不可评分
项目 DELETE /business/project/{id} 只有管理员可删除项目
项目 分配 monitorUserIds 必填 / staffUserIds 必填 / 项目不存在 / 已结题项目不能分配 / 请提供至少一个分配记录
会议 POST /business/meeting 建会必须指定 projectId / 期数不能超过分配给本公司的场次 (共 X 场) / 本机构已创建第 X 期会议, 请勿重复 / 已达上限 / 会议开始时间不能早于项目开始时间 / 会议结束时间不能晚于项目结束时间
会议 POST /business/meeting/submit-material 您不是该项目的执行方, 无法提交材料 / 会议尚未执行, 不能提交材料 / 会议已冻结, 不能提交材料 / 请选择要提交的材料类型 / 未知材料类型: X / 会务材料至少上传一条 / 请先添加参会人员 (劳务材料)
会议 audit-compliance 仅合规人员可操作 / 拒绝时意见不能为空
会议 audit-supervision 您不是该会议监察员, 无权监察
会议 settle 只有合规或管理员可结算 / 劳务与会务材料都审核通过后才能结算 / 会议已结算 / 会议费用尚未汇总完成,无法结算 / 请先上传劳务凭证与会务凭证 / 请先上传劳务凭证 / 请先上传会务凭证
会议 finish / unfreeze 只有合规或管理员可完结 / 会议尚未结算, 不能完结 / 会议已完结 / 只有合规或管理员可解冻 / 会议未冻结, 无需解冻
参会人 invitation 缺少参会记录 / 参会记录不存在 / 无权限查看该邀请函
参会人 编辑 劳务已提交, 不能修改参会人
材料 saveVouchers 只有合规或管理员可上传凭证
材料 downloadZip / downloadLaborZip 只有管理员或合规经理可下载会务材料 / …劳务材料
消息 POST /business/message 接收人不能为空 / 标题不能为空
消息 PUT /business/message/read/{id} 消息不存在或无权操作
消息 GET /business/message/{id} 消息不存在 / 无权查看