Files
2026-09-08 11:40:15 +08:00

821 lines
38 KiB
Markdown
Raw Permalink 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.
# admin 医生端源码审计
审计日期:2026-08-10
参考项目:D:\web\zyt\admin
审计方式:只读检查 Vue/TypeScript 源码、API 封装、路由守卫、Pinia store、业务组件和权限判断;未修改 admin 项目,也未把 README 当作结论来源。
## 1. 结论摘要
1. admin 是 Vue 3 + TypeScript + Vite + Element Plus + Pinia 项目。医生端并不是一套独立的静态路由:除登录、H5 诊单和只读诊单外,页面路径、标题、组件和菜单权限都由登录后 GET /adminapi/auth.admin/mySelf 返回的 menu 动态注入。
2. 医生相关页面的全局状态很少。Pinia 只持有认证用户、权限、动态菜单、全局站点配置、布局与多标签;接诊台、处方、患者、问诊列表的查询条件和业务状态均保留在各页面的 ref/reactive 中,分页统一使用 usePaging。
3. “患者列表”有两个不同实现:
- 医生/一诊工作台的“我的患者”:src/views/first_visit/my_patients/index.vue,带患者、订单、面诊进度三个工作区,服务端按当前角色和部门数据范围收窄。
- 平台注册用户列表:src/views/consumer/lists/index.vue,仅展示头像、昵称、账号、手机号、渠道和注册时间,不是医生业务患者工作台。
4. “问诊列表”也有两个相关实现:
- 挂号/问诊执行列表:src/views/tcm/appointment/list.vue,默认“今天 + 待接诊”,支持通话、视频二维码、完成、开方、取消。
- 诊单/患者业务列表:src/views/tcm/diagnosis/index.vue,围绕诊单、挂号、确认、开方、医助指派、二维码和视频旁观。
最终菜单叫什么、URL 是什么取决于后端 menu 配置,不应仅根据文件名硬编码。
5. 实际视频问诊主链是 src/components/chat-dialog/index.vue:腾讯云 Chat UIKit 单聊 + TUICallKit 音视频;通话前后还串联后端通话记录、TRTC 房间绑定、云端混流录制、可选浏览器本地录制、截屏写医生备注。src/components/video-call/index.vue 是另一套旧/独立实现,目前源码中没有被任何页面引用。
6. 处方领域要区分三类对象:
- 处方库模板:tcm.prescriptionLibrary,供医生复用药材组合。
- 已开处方:tcm.prescription,处方笺、患者、医师签名、主辅方、审核与作废。
- 处方业务订单:tcm.prescriptionOrder,收货、费用、双审、支付单、药房和物流履约;它不是支付单 zyt_order。
## 2. 关键源码与路由
### 2.1 页面定位
| 业务 | 关键源文件(绝对路径) | 路由结论 |
|---|---|---|
| 登录 | D:\web\zyt\admin\src\views\account\login.vue | 静态精确路由 /login |
| 接诊台 | D:\web\zyt\admin\src\views\patient\reception\index.vue | 动态菜单组件键应指向 patient/reception/index;实际 URL 取 menu[].paths |
| 我的处方库 | D:\web\zyt\admin\src\views\consumer\prescription\list.vue | 动态菜单组件键应指向 consumer/prescription/list;实际 URL 取 menu[].paths |
| 药品库(不是处方库) | D:\web\zyt\admin\src\views\doctor\medicine.vue | 动态菜单组件键应指向 doctor/medicine |
| 已开处方/处方管理 | D:\web\zyt\admin\src\views\consumer\prescription\index.vue | 动态菜单组件键应指向 consumer/prescription/index |
| 处方业务订单 | D:\web\zyt\admin\src\views\consumer\prescription\order_list.vue | 动态菜单组件键应指向 consumer/prescription/order_list |
| 我的患者 | D:\web\zyt\admin\src\views\first_visit\my_patients\index.vue | 动态菜单组件键应指向 first_visit/my_patients/index |
| 平台用户列表 | D:\web\zyt\admin\src\views\consumer\lists\index.vue | 动态菜单组件键应指向 consumer/lists/index |
| 问诊/挂号列表 | D:\web\zyt\admin\src\views\tcm\appointment\list.vue | 动态菜单组件键应指向 tcm/appointment/list |
| 诊单列表 | D:\web\zyt\admin\src\views\tcm\diagnosis\index.vue | 动态菜单组件键应指向 tcm/diagnosis/index;另有静态 H5 路由 /tcm/diagnosis/h5 |
| 诊单编辑/只读抽屉 | D:\web\zyt\admin\src\views\tcm\diagnosis\edit.vue | 被多个页面异步复用,不一定是独立菜单 |
| 患者只读详情 | D:\web\zyt\admin\src\views\tcm\diagnosis\readonly.vue | 静态精确路由 /tcm/diagnosis-readonly?id=诊单ID |
| 预约视频问诊 | D:\web\zyt\admin\src\views\tcm\diagnosis\appointment.vue | 抽屉组件,由诊单列表/我的患者调用 |
| 诊间开方 | D:\web\zyt\admin\src\components\tcm-prescription\index.vue | 复用组件,由问诊列表和诊单编辑调用 |
| 聊天与视频问诊 | D:\web\zyt\admin\src\components\chat-dialog\index.vue | 浮动组件,由接诊台及问诊列表调用 |
| 医助视频旁观 | D:\web\zyt\admin\src\views\tcm\diagnosis\components\AssistantWatchCallDialog.vue | 诊单列表内异步组件 |
### 2.2 动态路由机制
关键文件:
- D:\web\zyt\admin\src\router\routes.ts
- D:\web\zyt\admin\src\router\index.ts
- D:\web\zyt\admin\src\permission.ts
- D:\web\zyt\admin\src\stores\modules\user.ts
流程:
1. 常量路由只注册 /login、/403、/change-password、/bind-work-wechat、/user/setting、/doctor/progress、/tcm/diagnosis/h5 和 /tcm/diagnosis-readonly 等少数页面。
2. 登录成功后 GET /auth.admin/mySelf。
3. user store 保存 data.user、data.permissions,并把 data.menu 交给 filterAsyncRoutes。
4. 每个后端菜单项使用以下字段转为 Vue Router:
- paths:路由路径;
- componentsrc/views 下的组件键;
- name:菜单标题;
- perms:写入 route.meta.perms
- is_show:控制 meta.hidden
- is_cache:控制 keepAlive
- params:默认 query
- selectedactiveMenu
- type:目录或菜单。
5. permission.ts 把转换后的路由动态挂到根布局;第一个可见菜单成为 / 的重定向目标。
因此,本仓库源码能确定组件和静态路由,但不能单独确定接诊台、处方库、已开处方、我的患者、问诊列表的生产 URL 与菜单标题。要得到精确值,必须取得当前环境 /auth.admin/mySelf 的 menu 响应或检查服务端菜单表。
## 3. 登录、认证、权限和状态管理
### 3.1 登录链路
关键文件:
- D:\web\zyt\admin\src\views\account\login.vue
- D:\web\zyt\admin\src\api\user.ts
- D:\web\zyt\admin\src\stores\modules\user.ts
- D:\web\zyt\admin\src\utils\request\index.ts
- D:\web\zyt\admin\src\utils\auth.ts
账号密码:
- POST /login/account
- 请求:account、password、terminal=1。
- 响应被页面使用的字段:token、is_paw、need_bind_work_wechat。
- token 写入本地缓存键 token,后续请求通过请求拦截器放到 HTTP 头 token。
- “记住账号”只缓存 account,不缓存密码,缓存键为 account。
企业微信:
- GET /login/workWechatConfig,使用 enabled、corp_id、agent_id。
- 企业微信内置浏览器走 OAuthscope=snsapi_privateinfo、state=admin_login。
- 普通浏览器动态加载 https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js 显示扫码登录。
- 回调 code 通过 POST /login/workWechatLogin,参数 code、terminal=1。
- 另有 POST /auth.admin/bindWorkWechat、POST /auth.admin/unbindWorkWechat。
守卫:
- is_paw=0 强制跳转 /change-password,并通过 POST /login/changeFirstPassword 修改。
- need_bind_work_wechat=true 强制进入 /bind-work-wechat。
- 没有 token 的非白名单路由跳 /login?redirect=原地址。
- /auth.admin/mySelf 没有任何有效菜单时清认证并跳 /403。
- 响应码约定:1 成功、0 失败、-1 登录失效、10 需要绑定企微、2 打开新页面、-2 未安装。
### 3.2 Pinia 与页面状态
| Store/Hook | 文件 | 职责 |
|---|---|---|
| user | D:\web\zyt\admin\src\stores\modules\user.ts | token、userInfo、routes、perms、isPaw;登录、退出、企微登录、加载个人信息 |
| app | D:\web\zyt\admin\src\stores\modules\app.ts | 网站配置、OSS 图片地址、移动端/侧栏状态、视图刷新 |
| tabs | D:\web\zyt\admin\src\stores\modules\multipleTabs.ts | 多标签与 keep-alive 缓存 |
| setting | D:\web\zyt\admin\src\stores\modules\setting.ts | 本地布局、主题配置 |
| usePaging | D:\web\zyt\admin\src\hooks\usePaging.ts | 页码、page_size、loading、count、lists、extend;支持 silent 静默刷新 |
列表接口统一期待服务端 data 为:
- lists:当前页数组;
- count:总数;
- extend:额外统计、日期、权限范围等扩展数据。
页面内筛选和弹窗状态不进入 Pinia。这一约定适合桌面端复用:认证/权限做全局 store,业务工作台保持页面级 store 或 view-model。
### 3.3 权限判断语义
关键文件:
- D:\web\zyt\admin\src\install\directives\perms.ts
- D:\web\zyt\admin\src\utils\perm.ts
需要特别注意两套语义不同:
- v-perms 数组是“任一权限命中即可显示”(OR)。
- hasPermission 数组是“数组内每个权限都必须存在”(AND)。
- permissions 含星号时视为全部权限。
多数业务调用只传单个权限,因此差异暂时不明显;复用时不要把多权限数组在两处互换。
## 4. 业务页面审计
### 4.1 接诊台
源码:
- D:\web\zyt\admin\src\views\patient\reception\index.vue
- D:\web\zyt\admin\src\api\patient.ts
- D:\web\zyt\admin\src\views\tcm\diagnosis\components\PatientInfoCard.vue
- D:\web\zyt\admin\src\views\tcm\diagnosis\components\PatientCaseCard.vue
- D:\web\zyt\admin\src\views\tcm\diagnosis\components\DailyMatrix.vue
- D:\web\zyt\admin\src\views\patient\reception\components\NoteTimeline.vue
页面行为:
- 默认显示当天 status=1 待接诊;可切到 status=4 已过号。
- 搜索字段 patient_name;分页 page_no/page_size,固定每页 15。
- 每 5 秒静默刷新队列和已选患者详情;页面隐藏时暂停,恢复可见后立即刷新。
- 队列使用无限滚动,并按 id 去重。
- 队列行主要字段:id、patient_id、patient_name、patient_phone、diagnosis_id、doctor_id/name、assistant_id/name、appointment_date/time、gender、age、status/status_desc、has_prescription、remark。
- 详情结构按源码使用为:
- appointment:挂号;
- diagnosis:诊单/病例;
- doctor_notes:医生备注、舌苔和报告。
- 日常记录不依赖 reception 响应完整下发,而由 DailyMatrix 继续按 diagnosis_id 调 trackingWindow/trackingNotes。
操作:
- 通知医助:POST /doctor.appointment/notifyAssistant,参数 id=挂号ID。
- 发起通话:先 POST /tcm.diagnosis/getCallSignature,参数 patient_id、diagnosis_id,再打开 ChatDialog。
- 备注:POST /doctor.appointment/addDoctorNote,参数 diagnosis_id、content,可追加 tongue_images、report_files。
- 编辑病历:复用 tcm/diagnosis/edit.vue。
- 完成接诊:POST /doctor.appointment/complete,参数 id=挂号ID;页面允许 status=1 或 4。
权限:
- doctor.appointment/addDoctorNote
- tcm.diagnosis/edit
- doctor.appointment/complete
源码中的“通知医助”和“发起通话”按钮没有 v-perms;只能依赖页面菜单权限和后端接口鉴权,桌面端若拆成独立入口应补显式能力判断。
### 4.2 我的处方库
源码:
- D:\web\zyt\admin\src\views\consumer\prescription\list.vue
- D:\web\zyt\admin\src\api\tcm.ts
- D:\web\zyt\admin\src\components\medicine-name-select\index.vue
模型与筛选:
- 查询:prescription_name、formula_type(主方/辅方)、is_public(0 仅自己、1 所有人)。
- 列表:id、prescription_name、formula_type、herbs、is_public、disable_edit、creator_id/name、create_time。
- herbs 项:medicine_id(可选)、name、dosage。
- 编辑:id、prescription_name、formula_type、herbs、is_public、disable_edit。
- disable_edit=1 表示导入模板后锁定整张处方的药材,不可增删改,只能再次导入覆盖。
接口:
- GET /tcm.prescriptionLibrary/lists
- POST /tcm.prescriptionLibrary/add
- POST /tcm.prescriptionLibrary/edit
- POST /tcm.prescriptionLibrary/delete,参数 id
- GET /tcm.prescriptionLibrary/detail,参数 id(API 已封装,但当前列表弹窗直接使用行数据)
权限:
- wcf.prescription/add
- wcf.prescription/read
- wcf.prescription/edit
- wcf.prescription/delete
所有权:
- 普通用户只可编辑/删除 creator_id 等于当前 userInfo.id 的模板。
- root=1 或 role_ids 包含 0、3 可管理全部模板。
- 诊间/已开处方导入模板时会额外传 prescribing_creator_id,通常取处方 creator_id,新增时取当前登录用户 id。
### 4.3 药品库(容易和处方库混淆)
源码:D:\web\zyt\admin\src\views\doctor\medicine.vue
接口:
- GET /doctor.medicine/lists
- POST /doctor.medicine/add
- POST /doctor.medicine/edit
- POST /doctor.medicine/delete
- GET /doctor.medicine/detail
模型:
- id、name、supplier、unit、settlement_price、retail_price、stock、image、status、remark。
- 图片上传直接 POST 到 VITE_APP_BASE_URL + /api/upload/image,并携带 token 头。
当前页面的增删改按钮没有 v-perms。它是药材主数据管理,不应直接当作“我的处方库”复刻。
### 4.4 已开处方/处方管理
源码:
- D:\web\zyt\admin\src\views\consumer\prescription\index.vue
- D:\web\zyt\admin\src\components\tcm-prescription\index.vue
- D:\web\zyt\admin\src\api\tcm.ts
列表筛选:
- sn:处方编号模糊查;
- patient_name
- creator_ids:开方医师多选;
- audit_filterall、pending、passed、not_passed、rejected
- source_filterall、manual、system
- start_time、end_time(按创建时间)。
列表核心字段:
- id、sn、prescription_type
- is_system_auto0 手工、1 空白处方/系统代开;
- patient_name、gender、age、phone
- audit_status、audit_remark、business_prescription_audit_rejected、business_prescription_audit_remark
- void_status、void_by_name、void_time
- doctor_name、creator_id、assistant_name、prescription_date、create_time
- has_prescription_order。
处方编辑/详情模型:
- 关联:id、diagnosis_id、creator_id。
- 患者:patient_name、gender、age、visit_no、prescription_date。
- 诊断:tongue、tongue_image、pulse、pulse_condition、clinical_diagnosis。
- 药材:herbs,每项 medicine_id、name、dosage、formula_type(主方/辅方)、locked。
- 剂型/用法:prescription_type、dosage_amount、dosage_unit、dosage_bag_count、need_decoction、bags_per_dose、dose_count、dose_unit、usage_days、times_per_day、usage_instruction、usage_time、usage_way、dietary_taboo、usage_notes。
- 辅方用法 aux_usagedosage_amount、dosage_bag_count、need_decoction、bags_per_dose、times_per_day、usage_days、prescription_name(部分页面保留模板名)。
- 医师:doctor_name、doctor_signaturePNG data URL,保存前必填)。
- 可见性/审核:is_shared、visible_role_ids、audit_status、audit_time、audit_by_name、audit_remark。
状态规则:
- audit_status0 待审核、1 已通过、2 已驳回。
- 驳回处方会同时作废。
- “已通过且未作废”的有效处方不能普通编辑/删除。
- 新增时前端强制 audit_status=0;编辑保存后提示重新进入待审核。
- 诊间开方组件会保存 case_record 病历快照,并在已有 appointment_id 处方时直接进入只读查看。
- 已存在业务订单时,诊间组件禁止作废处方。
主要接口:
- GET /tcm.prescription/lists
- GET /tcm.prescription/detail,参数 id
- POST /tcm.prescription/add
- POST /tcm.prescription/edit
- POST /tcm.prescription/delete,参数 id
- POST /tcm.prescription/patchPatient,参数 id、patient_name、phone、gender
- POST /tcm.prescription/audit,参数 id、action=approve|reject、remark
- POST /tcm.prescription/void,参数 id
- GET /tcm.prescription/listByDiagnosis,参数 diagnosis_id
- GET /tcm.prescription/getByAppointment,参数 appointment_id
权限:
- cf.prescription/add、read、edit、audit、del
- tcm.prescription/patchPatient
- tcm.prescriptionLibrary/lists
- tcm.prescriptionOrder/create、lists、setShipMode
- finance.account_log/lists
- tcm.prescriptionOrder/editRemarkExtra
角色补充:消费者处方页将 root 或 role_ids 0、3 视为可审核角色;仍应以后端和 cf.prescription/audit 为最终判定。
### 4.5 处方业务订单
源码:
- D:\web\zyt\admin\src\views\consumer\prescription\order_list.vue
- D:\web\zyt\admin\src\views\consumer\prescription\components\PrescriptionOrderDetailDrawer.vue
- D:\web\zyt\admin\src\views\consumer\prescription\components\prescription-order-utils.ts
此页面是已开处方的相邻履约域。核心字段:
- id、order_no、prescription_id、diagnosis_id
- recipient_name、recipient_phone、region、shipping_address
- fee_type、amount、internal_cost
- prescription_audit_status、payment_slip_audit_status
- fulfillment_status
- linked_pay_order_count、linked_pay_order_id、linked_pay_paid_total
- medication_days、service_channel、service_package
- express_company、tracking_number、ship_mode
- doctor_name、creator_id/name、assistant_id
- remark_extra、remark_assistant
- 药房提交号和状态。
审核状态统一为 0 待审核、1 已通过、2 已驳回。履约状态:
- 1 待双审通过
- 2 待发货
- 3 已完成
- 4 已取消
- 5 已发货
- 6 已签收
- 7 进行中
- 8 暂不制药
- 9 拒收
- 10 退款
- 11 保留药方
- 12 制药缓发
核心接口:
- GET /tcm.prescriptionOrder/lists、detail、paidPayOrders、logs、logisticsTrace、export
- POST /tcm.prescriptionOrder/create、edit、withdraw、ddcode
- POST /tcm.prescriptionOrder/auditPrescription、auditPayment、revokeRxAudit、revokePayAudit
- POST /tcm.prescriptionOrder/ship、complete、refund、requestCompletion
- POST /tcm.prescriptionOrder/addPayOrder、linkPayOrder
- POST /tcm.prescriptionOrder/patchPrescriptionPatient、patchPrescriptionUsage、updateAmount
- POST /tcm.prescriptionOrder/setShipMode、uploadToPharmacy
- POST /tcm.prescriptionOrder/submitGancaoRecipel、previewGancaoRecipel、confirmGancaoSubmission
- POST /tcm.prescriptionOrder/batchAssignAssistant、addLog
主要权限:
- tcm.prescriptionOrder/detail、edit、export、ddcode、ship、addPayOrder、complete、refund、withdraw
- tcm.prescriptionOrder/auditPrescription、auditPayment
- tcm.prescriptionOrder/setShipMode、uploadToPharmacy、editRemarkExtra
- finance.account_log/lists、prescription.order/finance
前端还存在角色级显示规则:
- role 2:医助;
- role 6:下单角色;
- role 3、8:下单筛选豁免;
- role 0、3、6:财务字段;
- role 0、3:可绕过双审后的创建人编辑锁、可批量改派;
- 业务订单处方审核角色在共享工具中为 0、3、6。
这些数字与服务端配置耦合,不宜在新客户端再次散落硬编码。
### 4.6 我的患者
首选医生端实现:
- D:\web\zyt\admin\src\views\first_visit\my_patients\index.vue
- D:\web\zyt\admin\src\api\first_visit.ts
页面结构:
- “患者列表”“订单管理”“面诊进度”三个工作区。
- 筛选 keyword、status_filter、start_date、end_date。
- status_filterunbooked 未预约、pending_interview 待面诊、completed 已完成、missed 已过号。
- 日期快捷:今天、明天、后天、近 7 天、近 30 天、自定义。
- extend.summary 返回 today/tomorrow/day_after 计数。
- extend.dates 返回对应日期。
- extend.scope.label 直接展示后端判定的数据范围。
列表使用字段:
- diagnosis_id 或 id、source_patient_id
- patient_name、gender_desc、age、phone_masked、has_id_card
- assistant_id/name
- appointment_id、appointment_doctor_id/name、appointment_status、appointment_status_text、appointment_time_text
- revisit_count、confirmed、confirmation_text、diagnosis_date_text。
操作与接口:
- GET /firstvisit.myPatient/lists
- GET /firstvisit.myPatient/assistants
- POST /firstvisit.myPatient/assignid、assistant_id、is_inherit=0|1
- POST /firstvisit.myPatient/fillIdCardid、id_card
- POST /firstvisit.myPatient/createAppointment:预约完整参数
- POST /firstvisit.myPatient/cancelAppointmentid=挂号ID
- 订单工作区另使用 /firstvisit.myPatient/orders、orderDetail、orderEdit 及双审/发货/退款等受限代理接口。
- 面诊进度使用 GET /firstvisit.myPatient/progress。
权限:
- tcm.diagnosis/edit
- tcm.diagnosis/readonlyDetail
- tcm.diagnosis/guahao
- tcm.diagnosis/assign
服务端按当前角色与部门范围裁剪数据;前端不自行拼接 doctor_id 或 department_id 来模拟数据权限。
平台用户列表 D:\web\zyt\admin\src\views\consumer\lists\index.vue 使用 GET /user.user/lists,字段是 avatar、nickname、account、mobile、channel、create_time,只适合账号管理,不适合医生患者列表。
### 4.7 问诊/挂号列表
源码:
- D:\web\zyt\admin\src\views\tcm\appointment\list.vue
- D:\web\zyt\admin\src\api\doctor.ts
默认条件:
- status=1 待接诊;
- start_date=end_date=今天;
- date_preset=today
- 20 秒静默轮询;
- include_status_counts=1 时从 extend.status_count 一次返回各状态角标。
状态:
- 1 待接诊/已预约
- 2 已取消
- 3 已完成
- 4 已过号
筛选:
- patient_name、doctor_name
- status
- start_date、end_date、date_preset
- diagnosis_confirmed
- assistant_dept_id(选父部门含子级)。
行字段:
- id、patient_id、diagnosis_id
- patient_name、patient_phone、gender、age、height、weight
- doctor_id/name、assistant_name
- appointment_date、appointment_time、period
- diagnosis_confirmed
- has_prescription、prescription_is_system_auto、prescription_audit_status、prescription_void_status
- status/status_desc、remark。
操作:
- 编辑患者:复用诊单编辑抽屉。
- 视频二维码:生成小程序码。
- 通话:获取签名并打开 ChatDialog。
- 完成:POST /doctor.appointment/complete,可同时 POST addDoctorNote。
- 开方/查看:复用 TcmPrescription;有效已审核处方显示“查看”。
- 取消:POST /doctor.appointment/cancel。
权限:
- tcm.diagnosis/edit
- tcm.diagnosis/videoQr
- doctor.appointment/prescription
- doctor.appointment/complete
- tcm.diagnosis/kaifang
- doctor.appointment/cancel
- doctor.appointment/addDoctorNote(完成时备注能力)
角色判断:role_id 为 1 医生、2 医助;两者之外才显示医生姓名筛选。此处同时兼容 role_id 单值或数组,但其他页面多使用 role_ids,说明 user 模型尚未完全统一。
### 4.8 诊单列表
源码:
- D:\web\zyt\admin\src\views\tcm\diagnosis\index.vue
- D:\web\zyt\admin\src\views\tcm\diagnosis\edit.vue
- D:\web\zyt\admin\src\views\tcm\diagnosis\readonly.vue
列表筛选字段:
- keyword、diagnosis_type、syndrome_type、assistant_id
- diagnosis_confirmed、appointment_date、has_appointment
- latest_appointment_start_date/end_date/channel_source
- latest_assign_start_date/end_date
- pending_booking、completed_appointment、pending_assign
- pending_assign_order_month、pending_assign_keyword
- sort_unserved_days。
列表使用字段:
- id、patient_name、gender_desc、age
- assistant_id/assistant、assign_read_at
- appointments 或聚合的 appointment_doctor_name、appointment_time_text、appointment_status
- has_appointment、diagnosis_confirmed
- has_prescription、followup_time_text、followup_doctor_name、followup_rx_voided
- unserved_days、last_blood_record_at
- video_call_hint。
video_call_hint
- statenone、pending_room、live 等;
- label
- start_time、end_time。
操作权限:
- tcm.diagnosis/add、edit、delete、readonlyDetail
- tcm.diagnosis/assign
- tcm.diagnosis/kaifang
- tcm.diagnosis/guahao、guahaoLogList
- tcm.diagnosis/videoQr
- tcm.diagnosis/order
- tcm.diagnosis/watchCall
诊单编辑模型的核心字段:
- 标识:id、patient_id。
- 患者:patient_name、id_card、phone、gender、age、marital_status、height、weight、region。
- 诊断:diagnosis_date、diagnosis_type、syndrome_type、diabetes_type、diabetes_discovery_year、local_hospital_diagnosis、local_hospital_name。
- 指标:systolic_pressure、diastolic_pressure、fasting_blood_sugar。
- 现病史多选:appetite、water_intake、diet_condition、weight_change、body_feeling、sleep_condition、eye_condition、head_feeling、sweat_condition、skin_condition、urine_condition、stool_condition、kidney_condition、fatty_liver_degree。
- 既往史:past_history、trauma_history、surgery_history、allergy_history、family_history、pregnancy_history。
- 医疗内容:symptoms、tongue_coating、pulse、treatment_principle、prescription、doctor_advice、remark、current_medications。
- 归属与来源:assistant_id、status、create_source、show_card、external_userid。
详情响应还使用 patient_basic_locked、can_edit_patient_basic、latest_prescription_order。手机号/身份证是否显示明文由 tcm.diagnosis/phonePlain 控制;已有身份证通常只有明文权限才能修改。
诊单详情 Tab 权限:
- tcm.diagnosis/chufang:处方
- tcm.diagnosis/patientOrders:业务订单
- tcm.diagnosis/huifang:视频回放
- tcm.diagnosis/chat:聊天记录
- tcm.diagnosis/assign 或 detail:指派记录
- doctor.appointment/lists:挂号记录
- tcm.diagnosis/dailyRecord:日常记录
## 5. 视频问诊完整链路
### 5.1 预约
源码:D:\web\zyt\admin\src\views\tcm\diagnosis\appointment.vue
目前预约类型只有 video。请求字段:
- patient_id
- doctor_id
- appointment_date
- period=all
- appointment_time
- appointment_type=video
- remark
- channel_source
- channel_source_detail
普通入口 POST /doctor.appointment/create;“我的患者”入口 POST /firstvisit.myPatient/createAppointment。可用时段来自 GET /doctor.appointment/availableSlots,字段 doctor_id、appointment_date、period=all,响应使用 slots[].time、slots[].available。页面还读取医生排班并限制不能重复预约当天 status=1/4 的号。
### 5.2 医生发起通话
生产主组件:D:\web\zyt\admin\src\components\chat-dialog\index.vue
1. 页面调用 open({ patientId, patientName, diagnosisId })。
2. POST /tcm.diagnosis/getCallSignature,请求 patient_id、diagnosis_id。
3. 响应实际使用:
- sdkAppId
- userId(医生 IM/TRTC user ID
- userSig
- patientUserId,缺省回退 patient_加患者ID
- assistant_id(群视频邀请)
- isLochostVod(是否启用浏览器本地录制)
4. Chat UIKit 登录并创建与 patientUserId 的 C2C 会话。
5. TUICallKitServer.init 初始化通话能力;只有成功后才显示 AudioCallPicker、VideoCallPicker 和群视频按钮。
6. beforeCalling 时 POST /tcm.diagnosis/startCall
- diagnosis_id
- patient_id
- call_type=2(视频)
7. 呼叫状态进入 calling/connected 后从 TUIStore 或 TUICallEngine 捕获 roomID/strRoomID,再 POST /tcm.diagnosis/bindCallRoom
- diagnosis_id
- room_id(字符串)
8. bindCallRoom 的响应可带 cloud_recording.started、task_id、message;源码注释说明后端在这里触发腾讯云 CreateCloudRecording,混流模式由后端负责。
9. 接通后,若 isLochostVod=true,前端从 TUICallKit 视频元素启动 MediaRecorder/Canvas 本地录制。
10. 通话结束、挂断、IM 自定义挂断消息或用户关闭窗口时先 POST /tcm.diagnosis/endCall,再完成本地视频上传并 POST attachLocalCallRecording。
群视频调用 TUICallKitServer.callsuserIDList=[patientUserId, assistant_id]type=VIDEO_CALL。
### 5.3 截屏、录制与回放
关键文件:
- D:\web\zyt\admin\src\utils\call-local-recorder.ts
- D:\web\zyt\admin\src\utils\call-video-screenshot.ts
- D:\web\zyt\admin\src\views\tcm\diagnosis\components\CallRecordPanel.vue
- D:\web\zyt\admin\src\views\tcm\diagnosis\components\RecordingPlaybackBlock.vue
视频浮窗“截屏”会:
1. 抓取当前 video frame
2. 上传图片;
3. POST /doctor.appointment/addDoctorNote,把路径追加到 tongue_images。
通话记录字段:
- id、call_type1 语音、其他视为视频)
- room_id
- status:1 进行中、2 已结束、3 未接听、4 已取消
- recording_status_text
- recording_urls_list
- start_time_text、end_time_text、duration_text
接口:
- GET /tcm.diagnosis/getCallRecordsdiagnosis_id
- POST /tcm.diagnosis/attachLocalCallRecordingdiagnosis_id、file_url、可选 call_record_id
- POST /tcm.diagnosis/createManualCallRecorddiagnosis_id
- POST /tcm.diagnosis/startCloudRecordingdiagnosis_idAPI 有封装,主组件当前通过 bindCallRoom 的后端联动启动)
### 5.4 医助旁观
入口在诊单列表。只有同时满足:
- 当前 userInfo.id 等于该诊单 assistant_id
- 拥有 tcm.diagnosis/watchCall
- video_call_hint.state=live
才可真正进入。
GET /tcm.diagnosis/watchCall,参数 diagnosis_id,响应使用:
- sdkAppId
- userId
- userSig
- roomId 或 strRoomId
- patientName
旁观组件直接使用 trtc-sdk-v5 进入房间,只调用 startRemoteVideo,不开启本地摄像头或麦克风。pending_room 时显示入口提示但点击会阻止进入,等待房间号同步。
### 5.5 视频二维码
页面通过 POST /tcm.diagnosis/generateMiniProgramQrcode 生成 qrcode_url,常用字段:
- diagnosis_id
- patient_id
- doctor_id(部分入口)
- share_user_id
- mini_program_path=pages/login/login(问诊列表入口)
调用前先 GET 小程序配置并校验 app_id。
## 6. API 总表
所有 URL 会被请求层加上 baseUrl 和 adminapi 前缀;下表写的是 API 封装中的业务路径。
### 6.1 认证
| 方法 | 路径 | 关键请求/响应 |
|---|---|---|
| POST | /login/account | account、password、terminal;返回 token、is_paw、need_bind_work_wechat |
| POST | /login/workWechatLogin | code、terminal;返回同登录结果 |
| GET | /login/workWechatConfig | enabled、corp_id、agent_id |
| GET | /auth.admin/mySelf | 返回 user、permissions、menu |
| POST | /login/logout | 退出 |
| POST | /login/changeFirstPassword | password、password_confirm |
| POST | /auth.admin/bindWorkWechat | code |
### 6.2 挂号与接诊
| 方法 | 路径 | 关键字段 |
|---|---|---|
| GET | /doctor.appointment/lists | status、start_date、end_date、patient_name、doctor_name、diagnosis_confirmed、assistant_dept_id、page_no、page_size |
| GET | /doctor.appointment/reception | id=挂号ID;返回 appointment、diagnosis、doctor_notes |
| GET | /doctor.appointment/detail | id |
| GET | /doctor.appointment/availableSlots | doctor_id、appointment_date、period |
| POST | /doctor.appointment/create | patient_id、doctor_id、appointment_date/time、appointment_type、渠道等 |
| POST | /doctor.appointment/cancel | id |
| POST | /doctor.appointment/complete | id |
| POST | /doctor.appointment/notifyAssistant | id |
| POST | /doctor.appointment/addDoctorNote | diagnosis_id、content、tongue_images、report_files |
| GET | /doctor.appointment/doctorNotes | diagnosis_id |
| POST | /doctor.appointment/deleteDoctorNoteImage | note_id、image_type、image_path |
### 6.3 诊单
| 方法 | 路径 | 关键字段 |
|---|---|---|
| GET | /tcm.diagnosis/lists | 诊单列表全部筛选 + page_no/page_size;返回 lists/count/extend |
| GET | /tcm.diagnosis/detail | id |
| GET | /tcm.diagnosis/readonlyDetail | id;返回 appointment、diagnosis、unserved_days、last_blood_record_at、doctor_notes |
| POST | /tcm.diagnosis/add | 完整诊单模型 |
| POST | /tcm.diagnosis/edit | 完整诊单模型 |
| POST | /tcm.diagnosis/delete | id |
| POST | /tcm.diagnosis/assign | id、assistant_id、可选 is_inherit;批量场景由前端逐条调用 |
| GET | /tcm.diagnosis/getAssistants | 医助选项 |
| GET | /tcm.diagnosis/getDoctors | 医生选项 |
| POST | /tcm.diagnosis/checkPhone | phone 及排除 id |
| POST | /tcm.diagnosis/checkIdCard | id_card 及排除 id |
| POST | /tcm.diagnosis/fillIdCard | id、id_card |
| GET | /tcm.diagnosis/trackingWindow | id、start_date、end_date |
| GET | /tcm.diagnosis/trackingNotes | diagnosis_id |
| POST | /tcm.diagnosis/addTrackingNote | diagnosis_id、tracking_content |
### 6.4 处方与业务订单
处方、处方库、业务订单接口已在 4.2、4.4、4.5 分节完整列出。实现时必须保留三个资源命名空间,不要把 prescription、prescriptionLibrary、prescriptionOrder 合并成一个“处方”接口。
### 6.5 视频
| 方法 | 路径 | 关键字段 |
|---|---|---|
| POST | /tcm.diagnosis/getCallSignature | patient_id、diagnosis_id;返回 sdkAppId、userId、userSig、patientUserId、assistant_id、isLochostVod |
| POST | /tcm.diagnosis/startCall | diagnosis_id、patient_id、call_type |
| POST | /tcm.diagnosis/bindCallRoom | diagnosis_id、room_id |
| POST | /tcm.diagnosis/startCloudRecording | diagnosis_id |
| POST | /tcm.diagnosis/endCall | diagnosis_id |
| GET | /tcm.diagnosis/getCallRecords | diagnosis_id |
| POST | /tcm.diagnosis/attachLocalCallRecording | diagnosis_id、file_url、可选 call_record_id |
| POST | /tcm.diagnosis/createManualCallRecord | diagnosis_id |
| GET | /tcm.diagnosis/watchCall | diagnosis_id |
| POST | /tcm.diagnosis/generateMiniProgramQrcode | diagnosis_id、patient_id、doctor_id、share_user_id 等 |
## 7. 可复用约定
1. 请求协议
- baseURL 来自 VITE_APP_BASE_URL,统一 URL 前缀 adminapi。
- token 放在名为 token 的请求头,不是 Bearer Authorization。
- POST 默认把 params 转为 bodyGET 使用 params。
- 标准成功响应是 code=1,业务数据自动解包为 data。
- GET 网络失败默认最多重试 2 次,POST 不自动重试。
2. 列表协议
- 请求 page_no、page_size。
- 响应 lists、count、extend。
- 定时刷新使用 getLists({ silent: true }),避免表格白屏闪烁。
3. 标识约定
- diagnosis_id 是诊单主键。
- appointment.id 是挂号主键。
- prescription.id 是处方主键。
- prescriptionOrder.id 是处方业务订单主键。
- patientUserId 是腾讯云 IM/TRTC 用户名,通常 patient_加患者标识。
4. 隐私
- 默认手机号 3-4-4 脱敏,身份证保留前 6 后 4。
- tcm.diagnosis/phonePlain 控制诊单编辑中的明文能力。
- 数据范围由后端按角色、部门、归属医助裁剪,前端只做 UI 能力门控。
5. 复用组件
- 患者摘要/病例:PatientInfoCard、PatientCaseCard。
- 日常记录:DailyMatrix。
- 医生备注:NoteTimeline。
- 诊单编辑和只读:tcm/diagnosis/edit.vue 的 open、openViewOnly。
- 处方开立/查看:TcmPrescription 的 open、openById。
- 视频通讯:ChatDialog 的 open。
- 业务订单详情:PrescriptionOrderDetailDrawer。
6. 状态文本
- 不建议在新客户端重复定义状态映射。优先抽取 D:\web\zyt\admin\src\views\consumer\prescription\components\prescription-order-utils.ts 中的审核、履约、支付、供货和物流格式化逻辑为共享领域模块。
## 8. 未知点、歧义与风险
1. 动态菜单缺口:admin 前端仓库没有生产环境 /auth.admin/mySelf 的 menu 数据,因此接诊台、处方库、患者、问诊列表的精确 URL、菜单标题和页面级 route.meta.perms 仍未知。
2. API 类型不足:tcm.ts、doctor.ts 多数参数和返回值是 any;本文列出的响应字段来自实际页面读取,不等于完整服务端 schema。后续实现应抓取真实响应或检查服务端 DTO。
3. patient_id 语义有重载:
- 挂号行中 patient_id 常被当作诊单/患者标识;
- 我的患者 openAppointment 又把 diagnosis_id 或 id 同时写进 id 和 patient_id
- ChatDialog 则把它转换为 patient_前缀的腾讯云用户。
新客户端必须先确认数据库实体关系,不能只按字段名推断。
4. 接诊台发起通话使用 diagnosis_id || row.idrow.id 本身是挂号 ID。若后端要求真正诊单 ID,这个回退可能只在特定历史数据下成立。
5. 视频二维码参数疑点:tcm/appointment/list.vue 的一个入口把 diagnosis_id 赋为 row.doctor_id,而其他入口使用真正诊单 ID;这很可能是历史兼容或缺陷,应向后端核实后再复用。
6. 权限命名不统一:
- 处方库用 wcf.prescription/*
- 已开处方用 cf.prescription/*
- 新增能力又混用 tcm.prescription/* 与 tcm.prescriptionOrder/*。
不能按字符串前缀自动推导资源。
7. 角色配置存在差异:
- 消费者处方审核页面写死 0、3
- 业务订单共享工具写死 0、3、6
- 多处注释都声称与服务端配置一致。
最终角色应由服务端下发 capability,避免继续硬编码。
8. 权限 UI 不是安全边界:部分接诊、药品和通话按钮没有 v-perms;所有写接口必须继续依赖服务端鉴权。
9. 双 SDK 并存:
- 实际 ChatDialog 使用 @tencentcloud/call-uikit-vue
- 未引用的 video-call/index.vue 使用 @trtc/calls-uikit-vue
- 医助旁观直接使用 trtc-sdk-v5。
新项目应明确只保留一套主叫/被叫 UI SDK,并将纯 TRTC 旁观作为独立只拉流能力。
10. src/components/video-call/index.vue 当前没有被任何 Vue/TS 源码引用,不应误认为生产主链。
11. PatientCaseCard 的 caseTypeLabel 无论 consultation_type 都返回“复诊”,属于明显展示逻辑疑点。
12. 录制启动/停止部分依赖 TUICallKit 内部 store、引擎属性和方法包装,升级腾讯云 SDK 时风险较高,必须用真实双端通话、拒接、对端挂断、网络中断和房间号延迟场景回归。
13. 处方业务订单大量前端角色规则与 server/config/project.php 注释耦合;当前审计范围只有 admin 前端,无法验证服务端配置是否已同步。
## 9. 面向新医生端的建议映射
若新项目要复刻医生工作流,建议按领域而不是按现有目录命名:
- /login:复用认证协议和企业微信登录。
- /reception:复用接诊台队列、详情、5 秒静默刷新与 ChatDialog。
- /prescription-library:复用 prescriptionLibrary 模板及所有权规则。
- /prescriptions:复用 tcm.prescription 列表、审核、作废、打印/下载。
- /patients:优先复用 firstvisit.myPatient,而不是 user.user/lists。
- /consultations:复用 doctor.appointment/lists 的今天待接诊视图。
- /diagnoses:复用 tcm.diagnosis/lists 的完整诊单工作台。
- /video-consultation:主叫链路复用 ChatDialog/TUICallKit;医助旁观保持独立 TRTC 只拉流组件。
这些建议 URL 是新端的信息架构建议,不是对 admin 当前动态 URL 的断言。