14 KiB
诊单视觉重构最终业务回归审计(三次终验)
- 终验日期:2026-08-10
- 范围:生产视频/IM、医生备注与日常记录 mutation、处方/订单、多挂号精确取消、诊单 Shell owner、列表 QR/日志/订单;并复核上一版已关闭的权限、DTO、隐私与 generation 项。
- 基准:当前最新 Python 源码与测试,以及
D:/web/zyt/admin、D:/web/zyt/server的实际 admin 行为和服务端控制器/Logic。 - 约束:只读业务终验;未安装依赖、未打包、未访问线上接口。除更新本报告外,未修改业务源码或测试。
最终结论
第三次终验后的剩余项为:
- P0:0,明确无 P0。
- P1:1 项 OPEN。 诊单列表“创建订单”已调用真实
order.order/create,但没有消费返回的order_no并调用现成的generate_order_qrcode,admin 的付款二维码闭环仍中断。 - P2:2 项 OPEN。 一是日常矩阵不能编辑已有血糖/饮食/运动记录;二是视频回放只显示每条记录的第一个 URL,且没有 admin 的“向具体通话记录追加回放”入口。
- 服务端不可实现限制:不计入 P0/P1/P2。 医生备注与跟踪备注的服务端契约只支持按当天追加;服务端没有任意旧正文覆盖或整条删除 endpoint,桌面端无法在不扩展后端的前提下实现这些动作。
- 其余本轮复核项均 CLOSED:生产视频/IM 取数与同步、备注追加/附件、日常新增与待办、处方动作、订单详情/偏移、精确挂号取消、列表视频/确认 QR 与日志、真实 Shell 60%/move-resize/close generation。
- 定向离线回归:128/128 passed。
| 复核项 | 三次终验状态 | 最终等级 | 摘要 |
|---|---|---|---|
生产视频/IM only_archived、sync、上传、回放 |
OPEN(主体 CLOSED) | P2 | 生产接口、同步、工具栏上传和首个回放可用;多 URL 与指定 call-record 追加入口缺失 |
| 医生备注 mutation | CLOSED | — | 追加正文、上传舌象/报告、删除单附件均走真实合同;正文覆盖/整条删除属后端无 endpoint 限制 |
| 日常记录 mutation | OPEN(新增 CLOSED) | P2 | 新增血糖/饮食/运动/跟踪备注及待办新增/取消可用;已有三类记录不能编辑 |
| 处方/详情订单动作 | CLOSED | — | 开方、处方查看、业务订单列表/详情与诊次偏移均真实落库/取数 |
| 多挂号精确取消 | CLOSED | — | 每个挂号卡携带精确 ID,最终调用 doctor.appointment/cancel |
| 诊单 owner、60%、move-resize、generation | CLOSED | — | 每次打开重绑真实 Shell,宽度为 Shell 60%,移动/缩放/关闭同步且所有异步代次失效 |
| 列表 QR / 日志 / 创建订单 | OPEN(QR/日志/创建主体 CLOSED) | P1 | 视频/确认 QR、日志、创建订单均真实调用;创建成功后的支付 QR 未接入 UI |
上一版已关闭的 phonePlain、canonical diagnosis_type、viewOnly endpoint 分流、detail 失败禁存、身份证 15/18 位校验、权限 Tab 裁剪与隐私脱敏,本轮定向回归均未发现反弹。
逐项证据
1. 生产视频/IM:[OPEN / P2,主体 CLOSED]
已关闭部分:
RemoteDoctorRepository已实现生产getCallRecords、手工 call record、附件关联及“上传 → 创建记录 → 关联”顺序:src/doctor_workstation/services/repository.py:1875-1943。这与 adminCallRecordPanel的真实流程一致:D:/web/zyt/admin/src/views/tcm/diagnosis/components/CallRecordPanel.vue:109-180。- IM 首次读取明确发
only_archived=1,同步走triggerImChatSync:src/doctor_workstation/services/repository.py:1945-1965;dialog 的 lazy 查询也固定only_archived=True:src/doctor_workstation/ui/dialogs/diagnosis.py:2016-2038。admin 对照为D:/web/zyt/admin/src/views/tcm/diagnosis/components/ImChatRecordPanel.vue:148-185。 - edit 态视频工具栏调用真实上传,成功后按 media generation 重新加载;聊天同步成功后延时重新读取归档:
src/doctor_workstation/ui/dialogs/diagnosis.py:2541-2611。聊天图片/文件只能通过 HTTP(S) 安全打开::2652-2658。 - production/server 合同存在:
D:/web/zyt/server/app/adminapi/controller/tcm/DiagnosisController.php:397-438、:505-538;归档快路径在D:/web/zyt/server/app/adminapi/logic/tcm/DiagnosisLogic.php:1015-1045。
仍 OPEN 的 P2:
- 服务端返回
recording_urls_list数组:D:/web/zyt/server/app/adminapi/logic/tcm/DiagnosisLogic.php:1810-1833;admin 把完整数组交给播放器,并在每个具体 call row 提供上传入口:D:/web/zyt/admin/src/views/tcm/diagnosis/components/CallRecordPanel.vue:30-72。 - Python
_fill_video只取raw_urls[0],其余回放不可见,且视频表没有指定call_record_id的上传操作列:src/doctor_workstation/ui/dialogs/diagnosis.py:1126-1135、:2844-2881。虽然 repository 已支持call_record_id(src/doctor_workstation/services/repository.py:1894-1913),UI 没有把它接出来。
该问题不造成错误写入,且工具栏上传与一个回放可用,故按 P2 而非 P1 计。
2. 医生备注:[CLOSED;后端限制已明确]
- NotesTimeline 已暴露新增、上传、删除单附件与打开附件信号:
src/doctor_workstation/ui/diagnosis_drawer.py:1804-1810、:1820-1851、:1887-1961;dialog 绑定真实方法:src/doctor_workstation/ui/dialogs/diagnosis.py:989-997、:2376-2487。 - production DTO 分别走
doctor.appointment/addDoctorNote、doctor.appointment/doctorNotes、doctor.appointment/deleteDoctorNoteImage:src/doctor_workstation/services/repository.py:935-985。权限分别按新增与删除附件 endpoint 裁剪:src/doctor_workstation/ui/dialogs/diagnosis.py:478-483、:1233-1241。 - admin 自身也只有追加、上传、删除单附件动作:
D:/web/zyt/admin/src/views/patient/reception/components/NoteTimeline.vue:195-268;API 定义仅三条:D:/web/zyt/admin/src/api/patient.ts:19-40。
服务端不可实现边界:
- controller 仅暴露
addDoctorNote、doctorNotes、deleteDoctorNoteImage,随后类即结束:D:/web/zyt/server/app/adminapi/controller/doctor/AppointmentController.php:168-198。 DoctorNoteLogic::addOrAppend对当天正文使用换行追加,不支持任意旧正文覆盖:D:/web/zyt/server/app/adminapi/logic/doctor/DoctorNoteLogic.php:12-76;唯一删除逻辑只删除附件数组中的单项::111-136。
因此“任意旧笔记正文覆盖/整条删除”不是桌面端漏接已有合同,而是服务端没有 endpoint;本报告将其列为后端限制,不计客户端 P0/P1/P2。
3. 日常记录:[OPEN / P2,新增 CLOSED]
已关闭部分:
- edit 态已提供血糖、饮食、运动、跟踪备注新增按钮和待办新增/取消;只读态/无权限态隐藏:
src/doctor_workstation/ui/diagnosis_drawer.py:1363-1371、:1431-1450、:1481-1511、:1760-1791。 - dialog 将 signal 接到真实 add/todo repository,并为每次 mutation 使用 diagnosis-id + generation 校验后强制刷新:
src/doctor_workstation/ui/dialogs/diagnosis.py:1089-1101、:2175-2358。 - production 合同为
tcm.bloodRecord/add、tcm.dietRecord/add、tcm.exerciseRecord/add、tcm.diagnosis/addTrackingNote、todo add/cancel:src/doctor_workstation/services/repository.py:1745-1765、:1778-1805、:1847-1873。
仍 OPEN 的 P2:
- admin 点击已有单元格时会把记录(含
id)放入表单,保存时分别调用 blood/diet/exercise edit:D:/web/zyt/admin/src/views/tcm/diagnosis/components/DailyMatrix.vue:921-1013。 - Python matrix 明确
NoEditTriggers、NoSelection,只有daily_add_requested,没有已有记录 edit signal:src/doctor_workstation/ui/diagnosis_drawer.py:1366-1371、:1455-1463。dialog 也只选择add_*:src/doctor_workstation/ui/dialogs/diagnosis.py:2260-2284。 - 这不是后端限制:production repository 已实现三类 edit:
src/doctor_workstation/services/repository.py:1767-1776、:1787-1796、:1807-1818。
跟踪备注例外:server 设计就是“仅给今天追加”。controller 仅有 add/list:D:/web/zyt/server/app/adminapi/controller/tcm/DiagnosisController.php:180-214;TrackingNoteLogic 只有 addOrAppend/getByDiagnosis,类在第 95 行结束:D:/web/zyt/server/app/adminapi/logic/tcm/TrackingNoteLogic.php:8-95。其任意旧正文覆盖/整条删除同样属于后端无 endpoint 限制,不计客户端问题。
4. 处方与详情订单动作:[CLOSED]
- “开具处方”打开真实
PrescriptionEditorDialog,accepted 后调用create_prescription,并携带 diagnosis/appointment/case snapshot:src/doctor_workstation/ui/dialogs/diagnosis.py:2489-2539。 - 历史处方的“查看”打开真实
PrescriptionDetailDialog::2791-2842。 - 业务订单 lazy 列表、详情权限/真实 repository 门禁、异步 order generation 及详情 dialog 均已接通:
:1998-2000、:2069-2074、:2883-2991。 - 全局诊次偏移调用真实
setRevisitSlotStartOffset,并有独立 generation::2613-2650。
未发现处方或详情订单的假动作/越权入口,本项 CLOSED。
5. 多挂号精确取消:[CLOSED]
- 每个可取消挂号卡按精确 primary key 生成按钮,signal 携带原 record 与该 appointment-id:
src/doctor_workstation/ui/diagnosis_index_widgets.py:150-163、:1121-1148。歧义的行级“取消挂号”仍只在唯一挂号时出现::1403-1410。 - handler 选择当前诊单后再次按 ID 和状态校验,确认前后都防 stale,最终仅调用 exact capability:
src/doctor_workstation/ui/pages/consultations.py:1868-1921。 - production 方法明确走
doctor.appointment/cancel,不再误用患者工作区 endpoint:src/doctor_workstation/services/repository.py:1545-1555。 - 新测试覆盖两个挂号、超 32 位 appointment-id、错误诊单、状态刷新、权限/能力缺失与 canonical endpoint:
tests/test_diagnosis_index_visual.py:340-379、tests/test_consultations_parity_ui.py:610-774、tests/test_diagnosis_detail_contract.py:90-105。
本项 CLOSED。
6. 真实 Shell owner / 60% / move-resize / generation:[CLOSED]
_owner不再在 page 构造期缓存;每次open_for/showEvent都从当前parent.window()重绑真实 Shell:src/doctor_workstation/ui/dialogs/diagnosis.py:526-527、:1314-1349、:1398-1408。- overlay 与 owner 同位置/尺寸,宽屏 drawer 固定为 owner 宽度 60%;监听 owner 的 Resize/Move/Show/Close:
:1283-1299、:1351-1371。 reject/done及 owner Close 会使 detail/save/orders/order-detail/daily/notes/media/offset/所有 lazy-tab generation 全部失效::1373-1383、:1681-1700。
真实 ShellWindow -> QStackedWidget -> ConsultationsPage -> cached DiagnosisDialog offscreen 探针结果:
OPEN owner_shell=True shell=(1200,760) dialog=(1200,760) panel=720 expected=720 pos=(80,60)
MOVED shell=(1024,650) dialog=(1024,650) panel=614 expected=614 pos=(190,140)
CLOSE visible=False generation=True media=True
本项 CLOSED。现有 tests/test_diagnosis_drawer_visual.py:837-861 仍只用直接顶层 owner;本次额外真实 Shell 探针补足了业务终验,但建议后续把该探针固化成回归测试。
7. 列表 QR / 日志 / 订单:[OPEN / P1,主体 CLOSED]
已关闭部分:
- 页面只在 canonical 权限与真实 repository 方法同时存在时展示视频 QR、确认 QR、日志、订单入口:
src/doctor_workstation/ui/pages/consultations.py:704-715、:1005-1030。 - QR DTO 校验 patient/doctor/share-user/diagnosis,日志使用 diagnosis-id,所有菜单请求均受 selection generation 保护:
:1972-2091。 - production repository 真实调用
generateMiniProgramQrcode、guahaoLogList、order.order/create:src/doctor_workstation/services/repository.py:1967-2060。测试验证 exact DTO、权限裁剪与 stale callback:tests/test_diagnosis_detail_contract.py:85-127、tests/test_consultations_parity_ui.py:777-958。
仍 OPEN 的 P1:
- admin 创建订单成功后读取
order_no,立即调用generateOrderQrcode并展示付款 QR:D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:1474-1509。 - Python
_create_diagnosis_order把真实 create 放进通用_run_mutation;该 helper 丢弃_result,只 toast + refresh,因此永远不会生成付款 QR:src/doctor_workstation/ui/pages/consultations.py:2093-2128、:2460-2479。 - repository 明明已有
generate_order_qrcode:src/doctor_workstation/services/repository.py:2062-2076,但 UI 源码没有任何调用。现有测试也只分别测试“UI 创建订单”和“repository 可生成 QR”,未覆盖两者串联:tests/test_consultations_parity_ui.py:777-872、tests/test_diagnosis_detail_contract.py:88-89。
订单已实际创建却不展示付款入口,用户容易停在半完成状态或重复建单;这是主流程闭环缺失,按 P1 OPEN 计。
离线验证记录
使用项目现有 .venv,设置 QT_QPA_PLATFORM=offscreen、PYTHONDONTWRITEBYTECODE=1,禁用 pytest cache,并把 basetemp 放在系统临时目录;未安装任何依赖:
pytest -q -p no:cacheprovider \
tests/test_diagnosis_detail_contract.py \
tests/test_diagnosis_index_visual.py \
tests/test_diagnosis_drawer_visual.py \
tests/test_appointment_drawer_visual.py \
tests/test_consultations_parity_ui.py \
tests/test_prescription_security_ui.py \
tests/test_patients_ui.py \
tests/test_repository_parity.py \
tests/test_permissions.py
128 passed
测试退出码为 0;--collect-only -q 分文件计数合计 128。另执行了上述真实 Shell owner 探针,退出码为 0。
发布判断
当前不存在错误 endpoint、歧义挂号取消、权限泄漏、隐私明文回流或关闭后旧异步回调落地等 P0 风险。生产视频/IM、备注追加、日常新增、处方、订单详情及列表主要动作均已从“假动作/未接入”进展为真实 repository 行为。
但若发布标准是“完整保留 admin 的订单支付闭环与所有已存在的数据编辑/回放能力”,当前仍不满足:剩余 P0 0 / P1 1 / P2 2。其中任意旧医生/跟踪笔记正文覆盖或整条删除必须先扩展 server endpoint,不能作为桌面端单独修复项。