46 lines
4.3 KiB
Markdown
46 lines
4.3 KiB
Markdown
# 诊单编辑:脱敏手机号缺省提交的后端修复
|
||
|
||
日期: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,无输出 |
|
||
|
||
本报告证明离线编辑校验、更新参数保留与原有业务锁行为;未进行生产登录或真实数据库写入。
|