# 牦牛疾病预警 — 测试用例 > 依据:`牦牛疾病预警功能需求.md`、`牦牛疾病预警技术方案.md` > **后台接口 Base Path(示例)**:`/dataModel/yakDiseaseWarning`;**移动端**:`/app/healthAlert`;若含 `context-path` 或网关前缀须补齐。鉴权与若依一致(Cookie / Token)。 **通用前置(无特殊说明)**:具备本模块菜单与按钮权限的账号已登录;已执行 `sql/biz_yak_disease_warning.sql`、`sql/biz_yak_health_source_record.sql`;库中已有同步或造数样本。 **预警类型 `warning_type`(技术方案 §2.2)**:`1` 体温异常、`2` 运动量异常、`3` 检疫集中预警、`4` 诊疗集中预警、`9` 其他。 **同步流程**:拉取检疫/诊疗/养殖过程 → 写入健康源表 → 分析未分析记录生成预警(`insertCount` 含源记录新增与新生成预警条数)。 **样本约定(示例,评审可替换为环境真实 ID)** | 代号 | 说明 | 要点 | | --- | --- | --- | | **P1** | 牧场甲,`pasture_id=101` | 用户 **UA** 数据权限可见 | | **P2** | 牧场乙,`pasture_id=202` | 仅用户 **UB** 可见;UA **不可见** | | **AW1** | 近期预警 | `yak_no=YAK-W-001`,`pasture_id=P1`,`alert_time` 为 3 日内;`alert_message` 含「体温异常」 | | **AW2** | 超窗预警 | 同 P1,`alert_time` 为 4 个月前 | | **AW3** | 越权样本 | 归属 P2;UA 列表/详情应不可见 | **界面(UI)测试**:**Playwright** + **Chromium**(`channel: 'chrome'` 使用本机 **Google Chrome**)。菜单组件路径以 `dataModel/yakDiseaseWarning/index` 为准。 --- ## 一、单元测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYNBJY-UT-001 | 日期校验 | 开始晚于结束 | 单元测试 | JUnit5 | 功能需求 §5.1 | 无 | `validateDateRange(start=2026-05-10,end=2026-05-01)` | 抛 `ServiceException`;msg 含「开始日期不能晚于结束日期」 | | ZCZX-MYNBJY-UT-002 | 日期校验 | 仅开始日期 | 单元测试 | JUnit5 | 结束缺省今天 | 固定「今天」=2026-05-20 | `buildCriteria(start=2026-05-01,end=null)` | SQL 条件:`alert_time>=2026-05-01 00:00:00` 且 `<=2026-05-20 23:59:59` | | ZCZX-MYNBJY-UT-003 | 日期校验 | 仅结束日期 | 单元测试 | JUnit5 | §5.1 | 无 | `buildCriteria(start=null,end=2026-04-30)` | `alert_time<=2026-04-30 23:59:59` | | ZCZX-MYNBJY-UT-004 | 日期校验 | 起止均为空 | 单元测试 | JUnit5 | 不过滤日期 | 无 | `buildCriteria` 双空 | 生成条件不含 `alert_time` 上下界 | | ZCZX-MYNBJY-UT-005 | 枚举 | warning_type 合法 | 单元测试 | JUnit5 | §2.2 | 无 | 入参 1、2、3、4、9 | 通过;写入 DTO 不报错 | | ZCZX-MYNBJY-UT-006 | 枚举 | warning_type 非法 | 单元测试 | JUnit5 | 枚举边界 | 无 | 入参 0、5、null(若业务禁止) | 映射失败或落 null(与实现一致并固定) | | ZCZX-MYNBJY-UT-007 | 文案拼接 | 组装 alert_message | 单元测试 | JUnit5 | 技术方案 §4 | 无 | `measured=39.8℃`、`reference=正常体温`、`type=1` | 生成文案含实测值、参考范围、体温异常语义 | | ZCZX-MYNBJY-UT-008 | 同步合并 | 源记录 external_id 新增 | 单元测试 | JUnit5+Mockito | 幂等 | DB 无 Q:2001 | `persistSourceRecord` | `insert`;`insertCount+1` | | ZCZX-MYNBJY-UT-009 | 预警入库 | 分析生成 insert | 单元测试 | JUnit5+Mockito | 本地分析 | DB 无对应预警 | `persistAlert` | `insert`;返回 true | | ZCZX-MYNBJY-UT-021 | 分析规则 | 检疫集中阈值 | 单元测试 | JUnit5+Mockito | 功能需求 §5 | 同区同日 3 条阳性/异常 | `analyzeAndGenerate` | 生成 1 条 `warning_type=3`;源记录已分析 | | ZCZX-MYNBJY-UT-022 | 分析规则 | 诊疗集中阈值 | 单元测试 | JUnit5+Mockito | 功能需求 §5 | 同区同日 3 条诊疗 | `analyzeAndGenerate` | 生成 1 条 `warning_type=4` | | ZCZX-MYNBJY-UT-023 | 映射 | 检疫 OpenAPI → 源表 | 单元测试 | JUnit5 | 技术方案 §4 | 样例 DTO | `HealthRecordOpenApiMapper.fromQuarantine` | `external_id=Q:{id}`;`analyzed_flag=0` | | ZCZX-MYNBJY-UT-010 | 同步安全 | 失败不清库 | 单元测试 | JUnit5+Mockito | §5.3 | 已有 AW1 | Mock 第三方抛异常;`sync` | 已有记录条数与内容不变 | | ZCZX-MYNBJY-UT-011 | 同步安全 | 单条失败不抹成功条 | 单元测试 | JUnit5+Mockito | 部分成功 | 批次 2 条第 2 条非法 | `syncAll` | 第 1 条落库;`failCount>=1` | | ZCZX-MYNBJY-UT-012 | 并发 | 同步防重入 | 单元测试 | JUnit5 | 技术方案 §1 | 无 | 连续 `tryLock` 两次 | 第二次失败或跳过;返回「正在同步,请稍候」 | | ZCZX-MYNBJY-UT-013 | 牧场映射 | 映射成功 | 单元测试 | JUnit5+Mockito | §4 | `biz_pasture` 有编码 | 同步带第三方牧场码 | `pasture_id` 非空;`pasture_name` 与主数据一致 | | ZCZX-MYNBJY-UT-014 | 牧场映射 | 映射失败仅名称 | 单元测试 | JUnit5+Mockito | §4 | 无匹配主数据 | 未知牧场码+名称 | `pasture_id` 空;`pasture_name` 为第三方名 | | ZCZX-MYNBJY-UT-015 | Service | 列表牧场权限 | 单元测试 | JUnit5+Mockito | §5.1.4 | UA 仅可见 P1 | `selectList(UA)` | 结果仅 `pasture_id=101`;不含 AW3 | | ZCZX-MYNBJY-UT-016 | Service | 详情不存在 | 单元测试 | JUnit5+Mockito | 异常 | id 不存在 | `selectById(99999)` | null 或 `ServiceException`「预警记录不存在」 | | ZCZX-MYNBJY-UT-017 | Service | 详情越权牧场 | 单元测试 | JUnit5+Mockito | §3.2.1 | AW3 属 P2 | UA `selectDetail(AW3.id)` | `ServiceException`「无权查看该预警」 | | ZCZX-MYNBJY-UT-018 | Mapper | 列表排序 | 单元测试 | JUnit5 | §3.1.1 | 审阅 XML | `selectList` | `ORDER BY alert_time DESC, id DESC` | | ZCZX-MYNBJY-UT-019 | Mapper | 牧场精确筛选 | 单元测试 | JUnit5 | §3.1.1 | 无 | 审阅 XML | `pastureId` 非空时 `pasture_id = #{pastureId}` | | ZCZX-MYNBJY-UT-020 | 关联 | yakAssetId 解析 | 单元测试 | JUnit5+Mockito | §3.2.1 可选 | `biz_yak_asset` 有 YAK-W-001 | `selectDetail(AW1)` | `data.yakAssetId` 非空 | --- ## 二、接口测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYNBJY-API-001 | 列表 | 默认分页排序 | 接口测试 | Postman/curl | §5.1 | UA 登录;有 AW1、AW2 | `GET /dataModel/yakDiseaseWarning/list` | `code=200`;`rows`≤20;首条 `alertTime` 最新 | | ZCZX-MYNBJY-API-002 | 列表 | 日期范围命中 | 接口测试 | Postman | 含 AW1 不含 AW2 | 已登录 | `startDate`、`endDate` 覆盖 AW1 日历日 | 含 AW1;不含 AW2 | | ZCZX-MYNBJY-API-003 | 列表 | 仅开始日期 | 接口测试 | Postman | §5.1 | 有 AW2 超窗 | 仅传 `startDate`(AW2 之后) | 含 AW2;至今天止 | | ZCZX-MYNBJY-API-004 | 列表 | 仅结束日期 | 接口测试 | Postman | §5.1 | 有 AW1、AW2 | 仅传 `endDate` 早于 AW1 | 不含 AW1;含更早记录 | | ZCZX-MYNBJY-API-005 | 列表 | 日期颠倒 | 接口测试 | Postman | 异常 | 已登录 | `startDate=2026-05-10&endDate=2026-05-01` | 失败;msg 含「开始日期不能晚于结束日期」 | | ZCZX-MYNBJY-API-006 | 列表 | 牧场精确筛选 | 接口测试 | Postman | §5.1 | 有 P1、P2 数据 | `pastureId=101` | 仅 P1 记录 | | ZCZX-MYNBJY-API-007 | 列表 | 组合筛选 | 接口测试 | Postman | 且关系 | 已登录 | `startDate`+`endDate`+`pastureId` | 同时满足 | | ZCZX-MYNBJY-API-008 | 列表 | 分页参数 | 接口测试 | Postman | 分页 | 数据>20 | `pageNum=2&pageSize=10` | 第 2 页;条数≤10 | | ZCZX-MYNBJY-API-009 | 列表 | 数据权限隔离 | 接口测试 | Postman | §5.1.4 | UA 登录;存在 AW3 | `GET list` 不传牧场 | 无 AW3 | | ZCZX-MYNBJY-API-010 | 列表 | 无数据空列表 | 接口测试 | Postman | 空态 | 新环境无预警 | `GET list` | `rows=[]`;`total=0`;不报错 | | ZCZX-MYNBJY-API-011 | 详情 | 有效 id 全字段 | 接口测试 | Postman | §3.2.1 | AW1 含扩展字段 | `GET /dataModel/yakDiseaseWarning/{id}` | `data` 含 `yakNo`、`alertTime`、`pastureName`、`alertMessage`、`warningType`、`measuredValue` 等 | | ZCZX-MYNBJY-API-012 | 详情 | 无效 id | 接口测试 | Postman | 异常 | 已登录 | `GET /{id}` id=999999 | 失败;msg「预警记录不存在」或 `data` 空 | | ZCZX-MYNBJY-API-013 | 详情 | 越权牧场 | 接口测试 | Postman | §3.2.1 | UA;AW3 属 P2 | `GET /{AW3.id}` | 失败;msg「无权查看该预警」 | | ZCZX-MYNBJY-API-014 | 详情 | yakAssetId 可选 | 接口测试 | Postman | 跳转档案 | 档案有 YAK-W-001 | `GET detail` | `yakAssetId` 非空(若已实现) | | ZCZX-MYNBJY-API-015 | 同步 | 成功摘要 | 接口测试 | Postman/Mock | §3.3.1 | Stub 三类源各 1 新 | `POST .../sync` | `insertCount`/`updateCount`/`syncTime` 正确;含分析生成预警 | | ZCZX-MYNBJY-API-016 | 同步 | 幂等更新 | 接口测试 | Postman/Mock | 集中预警键 | 已同步同区同日 | 再次同步 | `updateCount>=1` 或源记录 update;预警不重复插多条 | | ZCZX-MYNBJY-API-017 | 同步 | 第三方超时 | 接口测试 | Postman/Mock | §5.3 | Mock 超时 | `POST .../sync` | 失败;msg 提示不可用/超时;库内 AW1 仍在 | | ZCZX-MYNBJY-API-018 | 同步 | 鉴权失败 | 接口测试 | Postman/Mock | 第三方 | Mock 401 | `POST .../sync` | 失败;不误删数据 | | ZCZX-MYNBJY-API-019 | 同步 | 处理中拒重复 | 接口测试 | Postman | 防重 | 同步耗时 Mock | 连续两次 `POST sync` | 第二次 msg「正在同步,请稍候」或 HTTP 业务失败 | | ZCZX-MYNBJY-API-020 | 同步 | 更新后列表可见 | 接口测试 | Postman | 端到端 | Mock 新预警 | `POST sync`→`GET list` | 列表出现新 `yakNo`/`alertMessage` | | ZCZX-MYNBJY-API-021 | 范围约束 | 无维护接口 | 接口测试 | Postman | 本期无 CRUD | 已登录 | `POST/PUT/DELETE` 预警实体路径(非 sync) | 404/405 或无权限 | | ZCZX-MYNBJY-API-022 | 鉴权 | 未登录后台 | 接口测试 | curl | 安全 | 无 Token | `GET .../list` | 401 或统一未登录 | | ZCZX-MYNBJY-API-023 | 权限 | 无 list | 接口测试 | Postman | §6 | 无 list 角色 | `GET list` | 403 或业务无权限 | | ZCZX-MYNBJY-API-024 | 权限 | 无 query | 接口测试 | Postman | §6 | 仅有 list | `GET/{id}` | 无权限失败 | | ZCZX-MYNBJY-API-025 | 权限 | 无 sync | 接口测试 | Postman | §6 | 有 list+query 无 sync | `POST sync` | 403 或业务无权限 | | ZCZX-MYNBJY-API-026 | 移动端 | 列表默认 | 接口测试 | Postman | §3.5 M1 | 牧民 Token;有 AW1 | `GET /app/healthAlert/list` | `code=200`;含 `yakNo`、`alertTime`、`alertMessage`;时间倒序 | | ZCZX-MYNBJY-API-027 | 移动端 | 数据权限 | 接口测试 | Postman | 与后台一致 | UA 移动端;有 AW3 | `GET /app/healthAlert/list` | 不含 AW3 | | ZCZX-MYNBJY-API-028 | 移动端 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET /app/healthAlert/list` | 401 | | ZCZX-MYNBJY-API-029 | 移动端 | 详情可选 | 接口测试 | Postman | M2 可选 | 已实现 M2 | `GET /app/healthAlert/{id}` | 与后台详情字段一致或精简子集 | | ZCZX-MYNBJY-API-030 | 牧场下拉 | 复用牧场列表 | 接口测试 | Postman | §3.4 | 已登录 | `GET /dataModel/pasture/list?pageSize=500` | 下拉选项与筛选 `pastureId` 一致 | | ZCZX-MYNBJY-API-031 | 端到端 | 同步-查-详情 | 接口测试 | Postman | §4 | sync+query 权限;Mock | `POST sync`→`GET list`→`GET/{id}` | 各步成功;详情与列表核心字段一致 | | ZCZX-MYNBJY-API-032 | 响应 | 失败可读 | 接口测试 | Postman | §7 | 已登录 | 触发日期颠倒、不存在 id、越权、同步失败 | `code`、`msg` 可区分场景 | --- ## 三、界面测试用例(UI) **测试工具**:**Playwright** + **Chromium**(`channel: 'chrome'` 使用本机 **Google Chrome**)。 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYNBJY-UI-001 | 列表 | 菜单与标题 | UI 测试 | Playwright+Chrome | 入口 | UA 有菜单权限 | 登录→进入「牦牛疾病预警」 | 页面标题/面包屑正确;见列表区 | | ZCZX-MYNBJY-UI-002 | 列表 | 表头列完整 | UI 测试 | Playwright+Chrome | §5.1 | 有 AW1 | 查看表头 | 含预警时间、牦牛编号、所属牧场、预警信息、操作 | | ZCZX-MYNBJY-UI-003 | 列表 | 默认排序 | UI 测试 | Playwright+Chrome | 时间倒序 | 有多条不同时间 | 进入页不筛选 | 最新 `alertTime` 在上 | | ZCZX-MYNBJY-UI-004 | 列表 | 预警日期筛选 | UI 测试 | Playwright+Chrome | §5.1 | 有 AW1、AW2 | 选范围仅含 AW1→搜索 | 仅 AW1;无 AW2 | | ZCZX-MYNBJY-UI-005 | 列表 | 所属牧场筛选 | UI 测试 | Playwright+Chrome | 精确 | 有 P1、P2 数据 | 下拉选牧场甲→搜索 | 仅牧场甲记录 | | ZCZX-MYNBJY-UI-006 | 列表 | 日期颠倒提示 | UI 测试 | Playwright+Chrome | §7 | 已登录 | 开始日晚于结束日→搜索 | 前端校验或接口错误提示;不刷新为错误数据 | | ZCZX-MYNBJY-UI-007 | 列表 | 重置 | UI 测试 | Playwright+Chrome | §5.2 | 已筛选 | 搜索→点「重置」 | 日期、牧场清空;恢复默认列表 | | ZCZX-MYNBJY-UI-008 | 列表 | 无数据空态 | UI 测试 | Playwright+Chrome | §5.1.4 | 筛选无结果 | 输入不存在组合→搜索 | 「未找到符合条件的预警」或等价空态 | | ZCZX-MYNBJY-UI-009 | 列表 | 预警信息长文案 | UI 测试 | Playwright+Chrome | §5.1 | AW1 长 `alertMessage` | 查看列表行 | 换行或 Tooltip 可看全文 | | ZCZX-MYNBJY-UI-010 | 列表 | 无增删改 | UI 测试 | Playwright+Chrome | §3 | 已登录 | 查看工具栏与操作列 | 无「新增」「编辑」「删除」;操作仅「查看」 | | ZCZX-MYNBJY-UI-011 | 同步 | 成功提示 | UI 测试 | Playwright+Chrome | §5.3 | 有 sync 权限;第三方可用 | 点「同步」等待完成 | 成功 Message 含新增/更新摘要;列表可刷新 | | ZCZX-MYNBJY-UI-012 | 同步 | 执行中防重复 | UI 测试 | Playwright+Chrome | 防重 | 有 sync 权限 | 同步中快速再次点击 | 按钮禁用或二次无效 | | ZCZX-MYNBJY-UI-013 | 同步 | 失败提示 | UI 测试 | Playwright+Chrome | §7 | Mock/断网第三方 | 点「同步」 | 失败提示;列表原数据仍在 | | ZCZX-MYNBJY-UI-014 | 同步 | 无 sync 权限 | UI 测试 | Playwright+Chrome | §6 | 仅 list+query 账号 | 进入列表 | 无「同步」或点击被拒绝 | | ZCZX-MYNBJY-UI-015 | 详情 | 入口与只读 | UI 测试 | Playwright+Chrome | §5.4 | 有 query 权限 | 列表点「查看」 | 打开详情/抽屉;无「保存」「确定」编辑主按钮 | | ZCZX-MYNBJY-UI-016 | 详情 | 核心字段展示 | UI 测试 | Playwright+Chrome | §5.4 | AW1 | 查看详情表单 | 牦牛编号、预警时间、所属牧场、预警信息与接口一致 | | ZCZX-MYNBJY-UI-017 | 详情 | 扩展字段展示 | UI 测试 | Playwright+Chrome | §5.4 | 样本含扩展字段 | 查看详情 | 展示预警类型、实测值、参考范围、设备号、采集时间等(有则显示) | | ZCZX-MYNBJY-UI-018 | 详情 | 跳转档案可选 | UI 测试 | Playwright+Chrome | §5.4 | 已实现跳转;档案存在 | 点击牦牛编号链接 | 打开牦牛资产档案详情;不存在则提示 | | ZCZX-MYNBJY-UI-019 | 详情 | 返回列表 | UI 测试 | Playwright+Chrome | 交互 | 在详情页 | 点返回/关闭 | 回到列表且筛选条件保留 | | ZCZX-MYNBJY-UI-020 | 权限 | 无菜单 | UI 测试 | Playwright+Chrome | §6 | 无本模块角色 | 登录浏览菜单 | 无「牦牛疾病预警」入口 | | ZCZX-MYNBJY-UI-021 | 权限 | 无 query 详情 | UI 测试 | Playwright+Chrome | §6 | 仅 list(若可配) | 直接访问详情路由 | 403 或拦截 | | ZCZX-MYNBJY-UI-022 | 端到端 | 同步-搜-详情 | UI 集成 | Playwright+Chrome | §4 | sync+query | 同步→按日期搜索→查看详情 | 全流程无报错;字段一致 | | ZCZX-MYNBJY-UI-023 | 移动端 | 健康预警列表 | UI 测试 | Playwright+Chrome | §5.5 | H5/模拟器可访问;牧民登录 | 打开「健康预警」页 | 列表含编号、预警时间、说明;时间倒序 | | ZCZX-MYNBJY-UI-024 | 移动端 | 头像占位 | UI 测试 | Playwright+Chrome | §5.5 | 无 `yakAvatarUrl` 样本 | 查看条目 | 显示默认占位图 | | ZCZX-MYNBJY-UI-025 | 移动端 | 空态 | UI 测试 | Playwright+Chrome | §5.5 | 账号无预警 | 进入健康预警 | 「暂无健康预警」类文案 | --- ## 四、Playwright 与谷歌浏览器(实施提示) - 安装:`npm i -D @playwright/test`;`npx playwright install chromium`;本机 Chrome:`npx playwright install chrome`。 - 配置:`playwright.config.ts` 中 `use: { channel: 'chrome', headless: false, locale: 'zh-CN', baseURL: 'http://localhost:80' }`;`storageState` 复用 UA 登录态。 - 后台路由:`await page.goto('/dataModel/yakDiseaseWarning')`(以菜单 `component` 为准)。 - 日期:`page.locator('.el-date-editor').first()` 填开始/结束;或 `getByPlaceholder('选择开始日期')`。 - 牧场:`page.locator('.el-select').filter({ hasText: '所属牧场' })` 选「牧场甲」。 - 搜索/重置:`page.getByRole('button', { name: '搜索' })` / `{ name: '重置' }`。 - 同步:`page.getByRole('button', { name: '同步' })`;断言 `page.locator('.el-message--success')` 含「同步」或「新增」「更新」。 - 详情:`page.getByRole('button', { name: '查看' }).first().click()`;断言 `page.getByText('预警信息')` 可见且无 `page.getByRole('button', { name: '保存' })`。 - 移动端 H5:独立 `baseURL` 或 `page.goto` 健康预警路径;登录态单独 `storageState`。 --- ## 五、覆盖对照 | 类别 | 单元 UT | 接口 API | 界面 UI | | --- | --- | --- | --- | | 正常流程 | UT-002~004、008~009、013~015、018~020 | API-001~004、006~008、011、015~016、020、026、031 | UI-001~005、011、015~019、022~023 | | 异常流程 | UT-001、006、010~011、016~017 | API-005、012~013、017~019、022、028、032 | UI-006、008、013、020~021 | | 业务约束 | UT-005~007、012、019 | API-006~009、021、027、030 | UI-004~005、007、009~010、014 | | 同步与第三方 | UT-008~012 | API-015~020 | UI-011~013、022 | | 数据权限 | UT-015、017 | API-009、013、027 | UI-020~021 | | 只读无 CRUD | — | API-021 | UI-010、015 | | 移动端 | — | API-026~029 | UI-023~025 | --- ## 六、功能需求追溯(自查) | 需求章节 | 要点 | 主要对应用例 | | --- | --- | --- | | §5.1 列表 | 日期、牧场、分页、排序、权限 | API-001~010;UI-002~009 | | §5.2 工具栏 | 搜索、重置、同步 | UI-007、011~013;API-031 | | §5.3 同步 | 幂等、失败不清库、防重、摘要 | UT-008~012;API-015~020 | | §5.4 详情 | 只读、全字段、跳转档案 | API-011~014;UI-015~019 | | §5.5 移动端 | 列表字段、倒序、空态 | API-026~028;UI-023~025 | | §5.6 协作 | 牧场下拉、统计口径 | API-030;UT-013~014 | | §6~§7 权限与提示 | 分权、可读错误 | API-022~025、032;UI-006、013~014、020~021 | | §3 范围外 | 无手工 CRUD | API-021;UI-010 | --- ## 七、修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初版:单元 20、接口 32、UI 25;对齐功能/技术方案;Playwright+Chrome;编号前缀 **ZCZX-MYNBJY** | | 1.1 | 对齐草稿:健康源三接口同步 + 集中分析;预警类型 3/4;新增 UT-021~023 |