Files
zyt/artifacts/diagnosis-edit-masked-phone-backend.md
T
2026-10-17 16:08:24 +08:00

46 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 诊单编辑:脱敏手机号缺省提交的后端修复
日期:2026-10-17。范围:后端编辑校验及离线 PHP 回归。
## 根因
桌面医生账户无 `tcm.diagnosis/phonePlain` 权限时只看到脱敏手机号,保存时会排除 `phone`/`id_card`。`DiagnosisController::edit()` 先执行 `DiagnosisValidate::sceneEdit()`,后调用 `DiagnosisLogic::edit()`。编辑场景原样继承全局 `phone = require|mobile`,因此合法的缺省 `phone` 请求在到达更新逻辑前就被“请输入手机号”拦截。
同一编辑场景还继承 `patient_name`、`gender`、`age` 的全局 `require`,即使这些基本信息被业务锁定、调用者仅修改临床信息,省略后也会被拦截。新增回归在修复前首先复现“请输入患者姓名”;另有单独省略 `phone`、其他基础信息照常提交的用例对应本次医生保存失败。
`DiagnosisLogic::edit()` 已直接用收到的 `$params` 更新,不会为缺省手机号补空值。基本信息变更比较也已使用 `array_key_exists` 跳过未提交字段,因此不需要修改 controller 或 logic。
## 修改
- `server/app/adminapi/validate/tcm/DiagnosisValidate.php`:仅在 `sceneEdit()` 中,将 `phone`、`patient_name`、`gender`、`age` 的无条件 `require` 替换为 `requireWhenPresent`。
- 新规则区分缺省键与显式提交:缺省表示保留;显式空串/null 仍拒绝,原有 `mobile`、姓名长度、性别范围、年龄类型/范围规则继续执行。`require` 前缀确保 ThinkPHP 对空串/null 也调用此规则。
- `server/tests/DiagnosisValidateEditSceneTest.php`:运行真实 validator 与真实 `DiagnosisLogic::edit()`,仅模型、数据库边界及权限读取使用内存替身,覆盖保存与业务锁行为。
## 边界与回归覆盖
- 编辑可省略所有受保护的基本信息,也可仅省略手机号而保留姓名/性别/年龄;省略的 `phone`、`id_card`、姓名/性别/年龄不会加入 update,原值保持。
- 显式手机号 `''`、null、`156****7862`、短号码、带空格号码、false、数组均拒绝;合法新号码仍通过格式校验。
- 显式姓名/性别/年龄为空仍拒绝;姓名超长、非法性别、非法或越界年龄仍拒绝;`gender = 0`、`age = 0` 仍有效。
- 编辑 ID 必填且诊单必须存在。`diagnosis_type`、`local_hospital_name` 等无关要求不变。
- 新增场景仍要求手机号、姓名、性别、年龄;新增空/脱敏手机号仍拒绝。
- 无额外权限的医生在最近订单未完成时,可以保存不含基本信息的临床修改;任何实际基本信息变更仍返回“最近业务订单未完成,无法修改患者基本信息”,且不会写入。原有 root 编辑能力保持。
- 未修改明文手机号权限、返回数据、创建权限、其他业务授权、统计或 AI 服务实现。
## 实际验证
执行目录:`D:/web/zyt`;PHP 8.2.9 CLI。测试未初始化应用、未读取生产配置,数据库/模型/权限边界为测试内存替身,没有数据库或外部服务调用。
| 命令 | 实际结果 |
| --- | --- |
| `php server/tests/DiagnosisValidateEditSceneTest.php`(修复前) | exit 1,`edit accepts omitted locked/basic/masked fields; got: "请输入患者姓名"` |
| `php -l server/app/adminapi/validate/tcm/DiagnosisValidate.php` | exit 0,No syntax errors detected |
| `php -l server/tests/DiagnosisValidateEditSceneTest.php` | exit 0,No syntax errors detected |
| `php server/tests/DiagnosisValidateEditSceneTest.php` | exit 0,Diagnosis edit-scene validation and masked/basic-field preservation: OK |
| `php server/tests/DiagnosisValidateAddSceneTest.php` | exit 0,Diagnosis add-scene validation: OK |
| `php server/tests/DiagnosisWorkspaceRowAuthorizationTest.php` | exit 0,Diagnosis workspace row authorization: OK |
| `php server/tests/DiagnosisAiPrescriptionGeneratePermissionTest.php` | exit 0,Diagnosis AI prescription generation permission: OK |
| `php server/tests/DiagnosisAiAnalysisSecurityTest.php` | exit 0,Diagnosis AI analysis security: OK |
| `git diff --check -- server/app/adminapi/validate/tcm/DiagnosisValidate.php server/tests/DiagnosisValidateEditSceneTest.php` | exit 0,无输出 |
本报告证明离线编辑校验、更新参数保留与原有业务锁行为;未进行生产登录或真实数据库写入。