33 KiB
接诊台 / 问诊列表:管理后台到医生桌面的逐项一致性审计
审计日期:2026-08-10
基准:D:\web\zyt\admin\src\views 中从现行路由可达的 Vue/TS 实现
对比对象:D:\web\zyt\app\src\doctor_workstation 当前 Python 实现
约束:本次只读审计;未修改 src/,未发网络请求。
1. 结论摘要
当前 Python 不是管理后台两个页面的等价移植,而是“接诊队列 + 简化问诊表 + 原生直呼视频”的医生端子集。端点骨架中,挂号列表、接诊聚合详情、通知、添加文字备注、完成接诊、诊单列表以及 getCallSignature/startCall/bindCallRoom/endCall 已接通;但今日队列边界、异步选人一致性、挂号状态判定、病例详情/编辑、开方、日常记录、备注媒体、复杂筛选和操作权限仍有显著差异。
发布阻断级结论:
- P0 — 接诊台快速切换患者会出现旧患者详情挂在新患者选择下。 管理后台每次选人递增请求序号并同时校验序号和
selectedId(D:\web\zyt\admin\src\views\patient\reception\index.vue:398-418);Python 在任一详情请求进行中时直接拒绝下一次加载(D:\web\zyt\app\src\doctor_workstation\ui\pages\reception.py:406-418),旧响应只按旧 generation 接受(同文件:437-447)。这会把显示、备注目标和当前队列行拆成两个患者上下文。 - P0 — Python 接诊队列没有“今天”条件。 基准固定发送
start_date=end_date=today(patient/reception/index.vue:296-305);Python 只发送status/keyword/page/page_size(reception.py:344-361)。因此历史或未来的状态 1/4 记录可能进入“今日接诊台”,并可触发通知、备注、视频和完成。 - P0 — 问诊列表的视频门槛读取了错误的状态域。 基准以
has_appointment && appointment_status===1为唯一可视频条件(tcm/diagnosis/index.vue:1778-1780;H5 同口径index_h5.vue:949-950)。Python 读取诊单模型的status,并允许 1 或 4(consultations.py:310-317);模型又优先取根status,而不是根appointment_status(core/models.py:362-366,406-414)。结果是已完成/过号记录可能仍可直呼,合法已预约记录也可能被误禁用。
其余 P1 缺口集中在:完整病例核对与只读详情、诊单编辑、从诊单开方、接诊详情字段/日常记录/备注附件、手机号脱敏、动作权限契约,以及问诊列表的筛选/状态/多挂号语义。详见第 8 节。
2. 判定口径与路由范围
状态含义:
- exact:端点、关键参数、状态门槛和结果语义均一致;不要求 Qt 与 Web 视觉相同。
- partial:已有对应能力,但参数、字段、权限、状态或边界行为不完整。
- missing:基准可达的医生核心能力在 Python 中没有入口或 repository 合同。
- intentionally unsupported:明确属于 H5 布局、小程序二维码或医助/后台运营角色,当前原生医生桌面选择了不同交互或没有承载;这是审计分类,不代表产品已正式批准删除。
路由证据:
- 管理后台主菜单是服务端动态路由:Vite 收集所有
views/**/*.vue,菜单组件名交给loadRouteView匹配(D:\web\zyt\admin\src\router\index.ts:9-15,28-69)。因此接诊台主文件是views/patient/reception/index.vue,问诊列表 PC 主文件是views/tcm/diagnosis/index.vue。 /tcm/diagnosis/h5静态指向index_h5.vue(D:\web\zyt\admin\src\router\routes.ts:82-85)。- PC 问诊列表的“查看”与双击跳转隐藏路由
/tcm/diagnosis-readonly?id=...(tcm/diagnosis/index.vue:2165-2172),静态路由指向readonly.vue(router/routes.ts:87-102)。 index.vue.bak的后缀不是.vue,不会进入import.meta.glob('/src/views/**/*.vue');add.vue没有被现行两个入口导入;两者均未作为基准。PC 虽挂载detail.vue,却没有存活的handleDetail调用;该弹窗仅由 H5 卡片点击实际触发(index_h5.vue:121,144,264-268,1013-1015)。
Python 页面级门控与主入口一致:接诊台使用 doctor.appointment/lists,问诊列表使用 tcm.diagnosis/lists(D:\web\zyt\app\src\doctor_workstation\ui\shell.py:40-47,69-75,248-264),判定为 exact。
3. 实际可达文件与依赖图
以下只列业务 Vue/TS 和决定行为的共享文件,不展开 Element Plus、基础 popup/upload 等纯框架组件。
3.1 接诊台
views/patient/reception/index.vue:队列、轮询、详情、通知、完成、快捷文字备注、通话入口(导入证据:191-210)。views/patient/reception/components/NoteTimeline.vue:备注文本、舌苔图片、检查报告、单附件删除(:1-121,125-132)。views/tcm/diagnosis/components/PatientInfoCard.vue:脱敏手机号、预约与人员摘要(:1-41)。views/tcm/diagnosis/components/PatientCaseCard.vue:病例全字段和生命体征阈值(:1-124,128-153)。views/tcm/diagnosis/components/DailyMatrix.vue→DiagnosisTodoList.vue:7/30/自定义日期窗、血糖血压/饮食/运动/跟踪备注/待办(DailyMatrix.vue:317-332,342-470)。components/chat-dialog/index.vue→ChatMessageItem.vue及本地录制/截图/IM 工具:实时聊天与通话、通话落库、房间绑定、结束、可选本地录制;API 导入见chat-dialog/index.vue:129-175。views/tcm/diagnosis/edit.vue及其下述诊单详情依赖:DailyMatrix.vue、CaseRecordList.vue、CallRecordPanel.vue→RecordingPlaybackBlock.vue→RecordingVideoPlayer.vue、ImChatRecordPanel.vue、AssignLogPanel.vue、AppointmentRecordPanel.vue、NoteTimeline.vue、TrackingNoteTimeline.vue、PatientOrderList.vue→PrescriptionOrderDetailDrawer.vue、components/tcm-prescription/index.vue(导入证据edit.vue:788-806)。
3.2 问诊列表
views/tcm/diagnosis/index.vue:PC 列表、全部筛选/角标、行操作、20 秒静默轮询(导入及异步组件:727-746)。views/tcm/diagnosis/index_h5.vue:静态 H5 路由;复用同一 edit/detail/prescription/appointment/watch-call 组件(:588-630)。原生 Python 不需要复刻 H5 布局,标为 intentionally unsupported;但它证明的业务状态和动作边界仍计入对比。views/tcm/diagnosis/readonly.vue:PC 隐藏详情路由;复用 PatientInfo/Case、DailyMatrix、备注、通话回放、IM、指派、挂号、业务订单组件(:151-167)。views/tcm/diagnosis/detail.vue:H5 卡片的简版诊单详情(:1-165)。views/tcm/diagnosis/edit.vue:新增/编辑/只读抽屉及所有扩展 Tab。components/tcm-prescription/index.vue:按诊单开方、查已有处方、作废、处方库导入和 PDF。views/tcm/diagnosis/appointment.vue:预约、排班、号源、渠道和今日重复挂号边界。views/tcm/diagnosis/components/AssistantWatchCallDialog.vue:医助 TRTC 只拉流旁观(:23-26,120-219)。- 决定字段与边界的 TS:
hooks/usePaging.ts(:13-58)、utils/perm.ts(:3-17)、install/directives/perms.ts(:13-32)、utils/diag-display.ts、utils/blood-thresholds.ts、utils/diabetes-discovery-display.ts。
4. 接诊台逐项差异
| 项目 | 基准证据 | Python 证据 | 判定 | 差异/影响 |
|---|---|---|---|---|
| 页面权限 | 动态菜单页面权限为 doctor.appointment/lists |
shell.py:40-47,248-264 |
exact | 页面级一致。 |
| 状态队列 | 仅 status 1“待接诊”和 4“已过号”(index.vue:33-45,235) |
两个 QTab 映射 1/4(reception.py:152-156,334-336) |
exact | 状态集合一致。 |
| 今日范围 | 每次请求带当天 start_date/end_date(index.vue:296-305) |
未发送日期(reception.py:344-361) |
missing / P0 | 非今日记录污染工作台并暴露写动作。 |
| 搜索 | patient_name,清空也自动搜索(index.vue:20-32,296-305,431-436) |
UI 只在回车/搜索按钮触发;repository 将 keyword 改为 patient_name(reception.py:159-168,352-360; repository.py:231-236) |
partial | 请求字段一致;清空不自动刷新。 |
| 分页与数量 | page size 15、另一状态独立 count、无限滚动、去重合并(index.vue:212-213,296-318,359-379,606-620) |
固定第一页 50 条,仅显示已加载条数(reception.py:344-386) |
partial | 50 条以上不可见;没有 waiting/passed 总数或加载更多。 |
| 轮询 | 5 秒链式轮询、倒计时、队列/详情/双 count、防重入、页面隐藏暂停/恢复立即刷新(index.vue:254-259,539-592) |
8 秒 QTimer,只刷新当前队列;页面 QWidget 隐藏时停(reception.py:138-140,663-672) |
partial | 无倒计时/另一状态 count;应用最小化不等价于 document.hidden;周期不同。 |
| 异步选人 | 每次选人递增 seq、清空详情、结果校验 seq + selected id(index.vue:398-418) |
请求进行中拒绝新选人;旧结果仍应用(reception.py:406-418,437-447) |
missing / P0 | 可显示旧患者详情并对新选择行执行其他动作。 |
| 队列行字段 | id、patient/diagnosis/doctor/assistant、日期时间、性别年龄、status、处方、remark(index.vue:215-233);实际显示姓名、性别年龄、过号、时间、医助(:57-90) |
显示同一核心子集(reception.py:50-95) |
exact | 行上显示字段基本一致。 |
| 聚合详情端点 | GET /doctor.appointment/reception?id(api/patient.ts:9-12) |
get_reception() 同端点/参数(repository.py:242-250) |
exact | 传输合同一致。 |
| 患者/病例字段 | PatientInfo 显示脱敏电话、性别年龄、身高体重地区、预约、医生/客服、状态/开方、remark(PatientInfoCard.vue:3-25);PatientCase 显示基本信息、生命体征、糖尿病史、现病史、既往/其他病史、处方意见(PatientCaseCard.vue:8-124) |
仅预约时间/电话/医生/医助,加主诉、临床诊断、舌脉、治则摘要和开方提示(reception.py:241-285,471-516) |
partial / P1 | 大量临床字段缺失;无法达到基准的接诊前核对深度。 |
| 手机脱敏 | 两张卡都调用 maskPhone(PatientInfoCard.vue:8; PatientCaseCard.vue:15) |
直接显示 patient_phone/phone/phone_masked 中第一个非空值(reception.py:478-480) |
missing / P1 | API 若下发明文即展示;未受 tcm.diagnosis/phonePlain 控制。 |
| 医生备注读取 | 聚合详情 doctor_notes,编辑/只读还会 GET /doctor.appointment/doctorNotes 并保留详情兜底(readonly.vue:177-217; api/patient.ts:29-32) |
仅消费聚合详情中的 doctor_notes/notes(reception.py:518-548);Remote 无 doctorNotes 方法 |
partial | 无独立补拉;备注元数据只显示 creator/time,忽略 note_date 语义。 |
| 文字备注写入 | diagnosis_id + trimmed content,最多 500 字,空值/无诊单拒绝(index.vue:175-181,514-536) |
同端点和空值/诊单检查(reception.py:575-601; repository.py:257-272),但 QTextEdit 无 500 字限制 |
partial | 端点 exact;客户端长度边界缺失。 |
| 舌苔/报告 | NoteTimeline 支持最多 99 个图片/文件、新增后刷新、单附件确认删除(NoteTimeline.vue:3-40,52-101,195-227,260-268; api/patient.ts:19-40) |
repository 可发送 tongue_images/report_files,但 UI 不展示附件、无上传/预览/删除入口(repository.py:257-272; reception.py:524-548) |
missing / P1 | 核心检查资料不可见、不可维护。 |
| 日常记录 | 只读 DailyMatrix,按诊单/患者加载(index.vue:129-139);7/30/自定义窗、trackingWindow/trackingNotes(DailyMatrix.vue:410-458,550-564,838-875) |
无 UI、模型和 repository 合同 | missing / P1 | 接诊时看不到血糖血压、饮食、运动、跟踪备注及阈值。 |
| 编辑病历 | tcm.diagnosis/edit 权限后打开 edit.vue(index.vue:155-161,474-480) |
无按钮、无 tcm.diagnosis/detail/edit repository 方法 |
missing / P1 | 接诊工作台不能维护病历。 |
| 通知医助 | POST /doctor.appointment/notifyAssistant {id},防重入、成功后刷新队列与详情(index.vue:460-471; api/patient.ts:14-17) |
端点/防按钮重入一致,但只 toast、不刷新(reception.py:558-573; repository.py:252-255) |
partial | 后端动作 exact;页面不会立即反映服务端副作用。 |
| 完成接诊 | 仅 apt.status 1/4,权限 doctor.appointment/complete,不可逆确认,POST {id: apt.id} 后清选中并重载(index.vue:162-171,492-511; api/doctor.ts:84-87) |
同权限、确认和端点(reception.py:326-328,610-641; repository.py:274-277) |
partial | 正常队列内近似 exact;受“非今日队列”和错患者详情竞态放大风险,UI 本身未再校验状态。 |
| 通话标识 | 缺 patient_id 拒绝;`diagnosis_id = row.diagnosis_id | row.id(index.vue:438-453`) |
app 同时要求 patient/diagnosis id;payload 优先真实 diagnosis_id(reception.py:643-661; app.py:496-537) |
|
| 通话生命周期 | ChatDialog 调 get signature、start、bind、end(chat-dialog/index.vue:641-695,996-1032,1089-1096) |
Remote 同四端点(repository.py:443-483),FIFO 生命周期按 start→bind→end(video/lifecycle.py:184-209,211-263,265-292) |
exact(核心) | Python 的核心通话落库顺序一致。 |
| 通话扩展 | ChatDialog 还有 IM、截图写备注、云/本地录像上传(chat-dialog/index.vue:129-175,241-265,1276-1301) |
原生 companion 未提供这些管理后台附属入口 | partial | 核心视频可用;聊天、截图备注和本地录像回填不等价。 |
接诊台权限差异
- 基准悬浮备注/编辑/完成分别使用
doctor.appointment/addDoctorNote、tcm.diagnosis/edit、doctor.appointment/complete(patient/reception/index.vue:146-171)。Python 已实现备注与完成门控,但编辑缺失(reception.py:322-331)。 - 基准队列行“通知医助”和“发起通话”没有
v-perms(index.vue:75-90)。Python 额外要求doctor.appointment/notifyAssistant与tcm.diagnosis/videoQr(reception.py:322-325)。后者在基准中是“小程序视频二维码”权限,不是直呼权限;这可能把拥有接诊页但没有二维码权限的医生挡在视频之外,判为 partial / P1。 - NoteTimeline 的“添加文字备注”检查 addDoctorNote 权限,但两个媒体 picker 和删除图标只受 readonly 控制(
NoteTimeline.vue:3-40,64-99,150-151)。这是基准自身的权限不对称,不能据此推导 Python 应无条件开放媒体写入。
5. 问诊列表逐项差异
5.1 列表、筛选与分页
| 项目 | 基准 | Python | 判定 |
|---|---|---|---|
| 列表端点 | GET /tcm.diagnosis/lists(api/tcm.ts:3-6) |
同端点(repository.py:414-440) |
exact |
| 分页 | usePaging 默认 page size 15,发送 page_no/page_size(usePaging.ts:13-21,25-48) |
page size 20、PageResult 容错(consultations.py:93-95,264-300) |
partial |
| 默认范围 | PC/H5 均默认 appointment_date=today(index.vue:2174-2182; index_h5.vue:1427-1437) |
默认日期同为今天;Remote 在起止相等时转换为 appointment_date(consultations.py:129-141,248-251,264-282; repository.py:420-424) |
exact(日期) |
| 默认状态 | 基准默认今天的所有挂号语义,不额外传 appointment status | Python status 下拉默认 1,并转成 appointment_status=1(consultations.py:121-128,276-279; repository.py:429-434) |
partial / P1 |
| 关键词 | keyword,提示姓名/手机号(index.vue:72-75,773-775) |
同字段(consultations.py:116-120,276) |
exact |
| 日期快捷项 | 前天、昨天、今天、明天、后天、全部;另有待预约、已完成、待分配及 9 路角标(index.vue:963-1085) |
单个起止日期控件和“今天”;无角标 | partial |
| 挂号/确认 | has_appointment 0/1;diagnosis_confirmed 0/1(index.vue:78-97,804-833) |
无这两个筛选 | missing |
| 诊断/证型/医助 | 字典筛选(index.vue:104-113,1158-1188) |
无 | missing |
| 最近挂号 | 起止日期 + 渠道,且与 appointment_date/未挂号互斥(index.vue:114-149,1197-1228) |
多日 start/end 被隐式映射为 latest appointment 起止,但无渠道、无互斥提示(repository.py:420-428) |
partial |
| 最近指派 | 起止日期(index.vue:124-133,1203-1216,1230-1232) |
无 | missing |
| 未服务排序 | sort_unserved_days=asc/desc(index.vue:297-304,1234-1248) |
无 | missing |
| 待分配宽搜 | 有关键词时只保留 page、pending_assign 和 pending_assign_keyword,主动清空其他筛选(index.vue:836-861,923-954) |
无 | intentionally unsupported(医助分配) |
| 定时刷新 | PC 20 秒且 document.hidden 时跳过(index.vue:1098-1105);H5 15 秒(index_h5.vue:1418-1437) |
20 秒,页面 QWidget 隐藏时停(consultations.py:238-240,325-334) |
exact(PC 周期)/ partial(可见性语义) |
| 路由 query id | ?id= 会在异步 edit ref 就绪后打开编辑(index.vue:1343-1357,2184-2188) |
无 deep-link | missing |
Python 的“状态下拉”不是基准筛选:它提供待接诊/取消/完成/过号(consultations.py:121-127),Remote 再把 3 映射为 completed_appointment=1,其他值映射成 appointment_status(repository.py:429-434)。基准 PC 没有该下拉;“已完成”定义为至少有一条 appointment.status=3(index.vue:1007-1020),取消状态也不在展示映射中。因此这里只能判 partial,不能视为同一合同。
5.2 行字段与状态映射
基准 PC 行字段:
- 诊单 ID/NEW、患者姓名、性别年龄(
index.vue:191-218)。 appointments[]多挂号;回退到 appointment_id/status/doctor/time 主字段;最近渠道(:219-261,1747-1757)。- 确认状态来自
DiagnosisViewRecord.some(is_confirmed == 1)(:262-267,1313-1317)。 - 复诊时间/医生/处方已作废、助理、是否开方(
:268-296)。 unserved_days与 last blood tooltip,阈值 null 灰、>=7 红、3-6 橙、<=2 绿(:297-317,1319-1329)。video_call_hint.state映射 none/live/pending_room/label(:318-341,1373-1427)。
Python 只显示预约时间、患者、状态、联系方式、医助、确认、处方、remark(consultations.py:183-225),判 partial / P1。具体错误为:
Consultation模型没有正式字段has_appointment、appointment_status、appointments、followup、unserved、last blood、video hint;虽保留 raw,但 UI 不读取这些字段(core/models.py:322-350)。- 模型从根
status优先取值,只有根 status 缺失才使用首个 nested appointment.status(:362-366,406-414)。基准明确把 appointment status 放在appointment_status/appointments[].status,并将诊单本身的 status 用作启用状态。这是 P0 视频门槛错误的根因。 - Python
diagnosis_confirmed属性只来自根confirmed/diagnosis_confirmed(:413-423),不计算DiagnosisViewRecord;存在把已确认显示成待确认的风险。 - Python 联系方式列直接显示
patient_phone/phone/phone_masked(consultations.py:195-201),而基准 PC/H5 列表不展示手机号明文;编辑页仅tcm.diagnosis/phonePlain可保持明文(edit.vue:822-856,1263-1277)。判 missing / P1(隐私)。
挂号状态基准只有:1=已预约、3=已完成、4=已过号(index.vue:1732-1745);取消仅允许 status 1/4,status 3 明确拒绝,且多挂号必须按具体 appointment id 操作(:1782-1857)。Python 把 2 显示为“已取消”,并把 4 也设为可直呼(consultations.py:53-58,310-317),不符合基准。
5.3 详情、编辑与操作
| 能力 | 基准行为与证据 | Python | 判定 |
|---|---|---|---|
| 只读病例详情 | PC 查看/双击需 tcm.diagnosis/readonlyDetail,路由 query id;加载 /tcm.diagnosis/readonlyDetail + doctorNotes(index.vue:345-354,2165-2172; readonly.vue:172-240; api/tcm.ts:8-11) |
表格双击直接发起视频;无详情页/端点(consultations.py:227-228,319-323) |
missing / P1 |
| H5 简版详情 | 卡片头/体打开 detail.vue;GET /tcm.diagnosis/detail,显示基础、病史、舌苔/报告、症状舌脉治则处方医嘱状态(index_h5.vue:121,144; detail.vue:10-122,157-165) |
无 | missing |
| 完整诊单编辑 | tcm.diagnosis/edit;GET detail 后 POST edit;新增用 add;手机号/身份证唯一性检查(edit.vue:1263-1375; api/tcm.ts:44-61,77-90) |
无 repository 方法或 UI | missing / P1 |
| 编辑字段 | patient/id card/phone/gender/age/marital/height/weight/region/BP/glucose/type/status/source/card/current medicine/local diagnosis、全部现病史/既往史/其他史/symptoms/remark(edit.vue:86-624,916-970) |
Consultation 只存列表摘要(core/models.py:322-350) |
missing / P1 |
| 编辑验证 | 姓名、手机、性别、年龄、空腹血糖、诊断类型、当地医院必填;手机号正则;身份证 18 位正则;病史发现最多 50(edit.vue:1026-1175) |
无 | missing |
| 开方/查看 | tcm.diagnosis/kaifang;审核通过且未作废显示“查看”,否则“开方”;传 diagnosis id + appointment id(index.vue:354-363,1671-1694) |
无问诊行开方入口;只有独立已开处方列表/详情 | missing / P1 |
| 处方边界 | 先按 appointment 查已有;临床诊断、至少一味药、药名/正剂量、无重复、手写签名必填;可作废但有业务订单时禁止(tcm-prescription/index.vue:1829-1922,2219-2328) |
Remote 仅 list/detail issued prescription(repository.py:354-397),无 add/getByAppointment/void |
missing / P1 |
| 预约 | tcm.diagnosis/guahao;医生排班/未来 7 天/可用时段;今天过去时段禁用;渠道必填;指定自媒体渠道补充必填;今天已有 status1/4 禁止重复约今天(appointment.vue:239-420,423-448,535-619,669-724) |
无 | intentionally unsupported(后台/医助调度) |
| 取消挂号 | status1/4 可取消,3 拒绝,多 appointment 精确到子记录(index.vue:1782-1857; api/doctor.ts:59-67) |
无 | intentionally unsupported(后台/医助调度) |
| 指派/取消指派 | tcm.diagnosis/assign;单条/批量、继承标志、取消传 assistant_id=0(index.vue:1532-1661) |
无 | intentionally unsupported(医助管理) |
| 视频二维码/确认二维码 | 仅 has_appointment && appointment_status=1;需 weapp config;权限 videoQr/guahao(index.vue:390-391,1778-1780,1964-2055) |
用同一 videoQr 权限启动原生直呼(consultations.py:102-106) |
intentionally unsupported(二维码)+ partial(权限/状态复用错误) |
| 医助旁观 | 仅当前被指派医助 + tcm.diagnosis/watchCall;pending_room 显示但不能进,live 才进;TRTC 只拉流(index.vue:1380-1413; AssistantWatchCallDialog.vue:120-219) |
无旁观角色/入口 | intentionally unsupported(医助角色) |
| 挂号日志 | tcm.diagnosis/guahaoLogList,空数组容错,显示 action/operator/summary/time(index.vue:1859-1897) |
无 | intentionally unsupported |
| 补身份证 | 15/18 位前端校验,POST fillIdCard 后自动年龄(index.vue:1918-1961) |
无 | intentionally unsupported(后台资料维护) |
| 企微记录 | records/contact 并行、20 条分页、文字 note 新增/删除(index.vue:2066-2160) |
无 | intentionally unsupported(后台企微归档) |
| 创建订单 | order_type、amount、remark 后生成订单二维码(index.vue:1430-1515) |
无 | intentionally unsupported(后台运营) |
5.4 只读详情的权限化子区块
基准 /tcm/diagnosis-readonly 不是一个简单摘要,它按权限加载:
tcm.diagnosis/dailyRecord:DailyMatrix(readonly.vue:42-54,183)。doctor.appointment/addDoctorNote:NoteTimeline 的可写版本在 edit;readonly route 固定只读(readonly.vue:56-70)。tcm.diagnosis/patientOrders:业务订单(:74-88)。tcm.diagnosis/huifang:通话录制回放(:90-101)。tcm.diagnosis/chat:IM 记录(:103-113)。tcm.diagnosis/assign或tcm.diagnosis/detail:指派日志(:115-131)。doctor.appointment/lists:挂号记录(:133-146)。
Python 问诊列表没有选中详情容器,因此上述全部为 missing;其中病例、日常记录、备注、挂号记录属于医生核对链路,列 P1;订单、指派和后台 IM 可按角色继续列 intentionally unsupported。
6. API 覆盖矩阵
此表只包含从上述可达 view/component 实际导入的业务 API;端点定义证据集中在 D:\web\zyt\admin\src\api\patient.ts:3-40、api\doctor.ts:49-87、api\tcm.ts:3-109,202-310,313-372,591-648。
| API 组 | 管理后台可达用途 | Python 状态 |
|---|---|---|
doctor.appointment/lists |
接诊队列、预约/挂号记录、最近就诊/今日重复检查 | exact 端点 / partial 参数;接诊台漏 today |
doctor.appointment/reception |
接诊聚合详情 | exact |
notifyAssistant |
通知医助 | exact 端点 / partial 刷新与权限 |
addDoctorNote |
文字、舌苔、报告、通话截图 | partial;Remote 参数齐,UI 只有文字 |
doctorNotes, deleteDoctorNoteImage |
备注补拉、附件删除 | missing |
doctor.appointment/complete |
完成接诊 | exact 端点 / partial 上下文边界 |
tcm.diagnosis/lists |
问诊列表、全部角标 | exact 端点 / partial filters/model |
readonlyDetail, detail, add, edit, delete, checkPhone, checkIdCard, fillIdCard |
详情与资料维护 | missing |
assign, assignLogList, getAssistants, watchCall |
医助分配与旁观 | intentionally unsupported |
trackingWindow, trackingNotes, addTrackingNote |
日常记录/备注窗 | missing |
| blood/diet/exercise add/edit | 编辑页日常记录 | missing |
| diagnosisTodo lists/add/cancel | 日常记录待办 | missing |
getCallSignature, startCall, bindCallRoom, endCall |
原生实时视频核心 | exact |
getCallRecords, attachLocalCallRecording, createManualCallRecord |
回放与人工补传 | missing(可选扩展) |
getImChatMessages, triggerImChatSync |
IM 归档 | missing |
prescription/listByDiagnosis, getByAppointment, add, void |
病例处方与开方 | missing / P1 |
prescription/detail, prescription/lists |
查看已开处方 | exact,但只在独立页面 |
prescriptionLibrary/lists |
开方时导入本人模板 | exact endpoint,但问诊开方 UI 缺失 |
| availableSlots/create/roster/lists | 预约 | intentionally unsupported |
| generateMiniProgramQrcode/generateOrderQrcode + weapp config | 二维码 | intentionally unsupported,由原生直呼替代 |
| WeChat records/contact/add/delete | 企微归档 | intentionally unsupported |
| prescriptionOrder lists/detail/logs | 只读业务订单 | intentionally unsupported |
Remote 的相关实现块只覆盖 appointment/reception/actions(D:\web\zyt\app\src\doctor_workstation\services\repository.py:226-277)、diagnosis list 与四个 call endpoint(:414-483);因此上述“missing”不是 UI 隐藏但 repository 已具备,而是端到端合同确实不存在。
7. 权限码对照
基准中实际出现
- 页面/读取:
doctor.appointment/lists、tcm.diagnosis/lists、tcm.diagnosis/readonlyDetail、tcm.diagnosis/detail、tcm.diagnosis/dailyRecord、tcm.diagnosis/patientOrders、tcm.diagnosis/huifang、tcm.diagnosis/chat。 - 接诊写动作:
doctor.appointment/addDoctorNote、doctor.appointment/complete、tcm.diagnosis/edit。 - 问诊列表动作:
tcm.diagnosis/add、edit、delete、assign、kaifang、guahao、videoQr、watchCall、guahaoLogList、order。 - 编辑扩展:
tcm.diagnosis/phonePlain、tcm.diagnosis/chufang、tcm.diagnosis/setRevisitSlotStartOffset、tcm.prescriptionOrder/detail。
证据:接诊 patient/reception/index.vue:146-171;问诊 PC tcm/diagnosis/index.vue:318-400;readonly readonly.vue:42-146;edit edit.vue:674-748,822-856;PatientOrderList components/PatientOrderList.vue:20-33,99-114。
Python 实际门控
- 页面:两个页面码 exact(
shell.py:40-75)。 - 接诊:
notifyAssistant、videoQr、complete、addDoctorNote(reception.py:322-331);缺 edit。 - 问诊:只有
videoQr(consultations.py:102-106);其余动作根本没有 UI。 - Python PermissionSet 本身支持
*、all/any(core/permissions.py:60-104),问题在页面选择了哪些码,而不是权限容器能力。
特别注意:Web 的 v-perms 是数组 OR(install/directives/perms.ts:13-32),hasPermission() 工具是数组 AND(utils/perm.ts:3-17);当前页面绝大多数调用只有一个码,唯一显式 OR 的 assign/detail 是两个独立调用(readonly.vue:117-120),所以本次差异不受二者实现差别影响。
8. P0 / P1 缺口清单(按严重度排序)
P0
- RACE-RECEPTION-01:快速切换患者导致详情与选择错配。 修复验收应覆盖 A 请求未返回时选 B,A/B 任意顺序返回后 UI、备注 diagnosis_id、通知/完成 appointment_id 和视频 payload 必须全部指向 B;详见第 1、4 节证据。
- SCOPE-RECEPTION-02:接诊列表漏
start_date=end_date=today。 必须在 UI 或 repository 的专用 reception query 中固定今日,不能让通用 appointment list 隐式决定。 - STATE-CALL-03:问诊视频使用
status而非has_appointment + appointment_status,且错误允许 4。 模型和 UI 都需改;只修 UI 的字段名仍会被当前 dataclass 的根 status 优先级遮蔽。
P1
- DETAIL-04:问诊列表没有
readonlyDetail/详情入口,双击反而直呼。 医生无法先核对完整病例、日常记录、备注和挂号历史。 - EDIT-05:接诊台和问诊列表均无诊单详情/edit 合同。 基准接诊台明确提供“编辑病历”。
- RX-06:没有从诊单开方/查看/作废的工作流。 独立“已开处方”页面不能替代
diagnosis_id + appointment_id上下文开方。 - RECEPTION-DETAIL-07:接诊详情只显示摘要,缺完整 PatientCase、日常记录、备注附件和附件删除。
- PRIVACY-08:接诊和问诊列表可能直接显示明文手机号,未遵守基准的 mask/phonePlain 边界。
- PERM-09:用
tcm.diagnosis/videoQr保护原生直呼、用未在基准按钮上出现的doctor.appointment/notifyAssistant保护通知,可能让合法接诊医生缺动作;同时缺tcm.diagnosis/edit入口。 需要后端权限清单确认专用 call permission,而不是继续借用二维码码。 - MODEL-10:Consultation 未正式解析 appointment_status、has_appointment、多挂号、DiagnosisViewRecord、unserved/video hint 等;当前确认和状态显示不可靠。
- FILTER-11:问诊筛选缺 has_appointment、confirmed、诊断类型、证型、医助、最新挂号渠道、最新指派、未服务排序及顶部 count;Python 自创 status 下拉又改变默认结果集。
- BOUNDARY-12:文字备注没有 500 字客户端限制;通知成功不刷新;完成动作未在 handler 中二次验证 1/4。
不列 P0/P1 的 intentionally unsupported 项:H5 响应式布局、小程序/订单二维码、批量指派、医助旁观、企微后台归档、后台订单创建和排班预约。若产品决定医生桌面也承担医助/运营职责,应把这些重新分类为 missing 并另立需求。
9. 基准自身的可疑点(不可静默照搬)
以下均是当前 admin/src/views 的真实行为,本报告仅记录,不用其他资料修正它:
- 接诊台“编辑病历”把
diag.patient_id传给edit.open('edit', id)(patient/reception/index.vue:474-476),而 edit 将该 id 直接传给/tcm.diagnosis/detail(tcm/diagnosis/edit.vue:1263-1265,1288-1302);问诊列表传的则是row.id(index.vue:1667-1669)。这是明显 ID 口径冲突。 - PC/H5 的“视频二维码”请求把
diagnosis_id赋成row.appointment_doctor_id(index.vue:1987-1993;index_h5.vue:1262-1268),而“诊单二维码”正确使用row.id(index.vue:2037-2042)。Python 原生直呼当前没有复制此错误。 PatientCaseCard的 consultation_type 三元两边都返回“复诊”(PatientCaseCard.vue:148-151)。- 接诊行通知/通话无权限指令、NoteTimeline 媒体写入未复用 addDoctorNote 门控,见第 4 节;应先确认服务端授权模型,再决定桌面行为。
10. 建议的最小合同测试
后续实现至少应加入不发网络的合同测试:
- Reception request 必含 status、today start/end、patient_name、page_no/page_size。
- A/B 详情乱序返回不会产生跨患者详情或写动作目标。
- Consultation row 的
status=1, appointment_status=3不可视频;status=1, has_appointment=1, appointment_status=1可视频;status 4 一律不可从问诊列表直呼。 DiagnosisViewRecord=[{is_confirmed:1}]显示已确认;多 appointments 保留并正确挑选 active appointment。- 无 phonePlain 权限时列表和详情只出现掩码。
- readonlyDetail、edit 和 prescription 动作分别由准确权限码控制;缺码时不创建可调用控件。
- 备注 501 字在客户端拒绝;媒体 note payload 保留 tongue/report 数组;删除附件的三字段合同固定。