| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- 基于对 PHP 项目的代码分析,我为您整理了 report/details 接口的完整实现逻辑:
- ---
- 1. 接口路由和调用链
- 路由: report/details
- 调用链: ReportController::details() → ReportService::getReportDetail() → ReportDao → ReportModel
- ---
- 2. 参数验证(ReportValidate::check)
- 验证规则:
- - exam_id:必填,检查ID
- - is_remote:必填,枚举值 1 或 2
- - 1 = 远程申请报告
- - 2 = 本地检查报告
- - ra_id:可选,远程申请ID(当 is_remote=1 时使用)
- ---
- 3. 核心业务逻辑(ReportService::getReportDetail,第64-162行)
- 3.1 查询报告基础信息
- 分支判断:根据 ra_id 是否为空,决定查询本地报告还是远程报告
- 本地报告查询(ra_id 为空):
- SELECT
- -- 检查信息(exams表)
- e.patient_num, e.exam_class, e.exam_datetime, e.exam_status,
- e.name, e.sex, e.age, e.phone, e.exam_project,
- e.hopitalized_no, e.accession_num, e.write_report,
- CONCAT(study_id,'&node_type=',node_type) as study_id,
- e.node_type, e.institution_id,
- -- 报告信息(report表,type=1表示本地报告)
- r.id as report_id, r.impression, r.description,
- r.report_result, r.report_doctor_id, r.report_doctor_name,
- r.report_datetime, r.review_doctor_id, r.review_doctor_name,
- r.review_datetime, r.confirm_doctor_id, r.confirm_doctor_name,
- r.confirm_datetime, r.remote_application_id, r.qr_code,
- -- 登记信息(register表)
- re.body_part, re.exam_sub_class, re.hr_status,
- -- 医生签名信息(doctors表,三次关联)
- dp.is_use_autograph as report_use_autograph,
- dp.autograph as report_autograph,
- dp.autograph_type as report_autograph_type,
- dv.is_use_autograph as review_use_autograph,
- dv.autograph as review_autograph,
- dv.autograph_type as review_autograph_type,
- dc.is_use_autograph as confirm_use_autograph,
- dc.autograph as confirm_autograph,
- dc.autograph_type as confirm_autograph_type
- FROM exams e
- LEFT JOIN register re ON re.exam_id = e.id
- LEFT JOIN report r ON e.id = r.exam_id AND r.type = 1
- LEFT JOIN doctors dp ON dp.id = r.report_doctor_id
- LEFT JOIN doctors dv ON dv.id = r.review_doctor_id
- LEFT JOIN doctors dc ON dc.id = r.confirm_doctor_id
- WHERE e.id = $examId
- 远程报告查询(ra_id 不为空):
- SELECT
- -- 远程申请信息(remote_application表)
- e.patient_num, e.exam_class, e.exam_datetime, e.body_part,
- e.study_id, e.hopitalized_no, e.name, e.sex, e.age, e.phone,
- e.report_status, e.local_institution_name, e.req_doctor_name,
- e.remote_department, e.exam_project, e.accession_num,
- e.local_institution_id as institution_id,
- -- 报告信息(type=2表示远程报告)
- r.id as report_id, r.impression, r.description,
- r.report_result, r.report_doctor_id, r.report_doctor_name,
- r.report_datetime, r.review_doctor_id, r.review_doctor_name,
- r.review_datetime, r.confirm_doctor_id, r.confirm_doctor_name,
- r.confirm_datetime, r.remote_application_id, r.qr_code,
- -- 医生签名信息
- dp.is_use_autograph as report_use_autograph,
- dp.autograph as report_autograph,
- dp.autograph_type as report_autograph_type,
- dv.is_use_autograph as review_use_autograph,
- dv.autograph as review_autograph,
- dv.autograph_type as review_autograph_type,
- dc.is_use_autograph as confirm_use_autograph,
- dc.autograph as confirm_autograph,
- dc.autograph_type as confirm_autograph_type
- FROM remote_application e
- LEFT JOIN report r ON r.remote_application_id = e.id
- LEFT JOIN doctors dp ON dp.id = r.report_doctor_id
- LEFT JOIN doctors dv ON dv.id = r.review_doctor_id
- LEFT JOIN doctors dc ON dc.id = r.confirm_doctor_id
- WHERE e.id = $ra_id
- 自动创建报告记录(第70-81行):
- - 如果本地检查没有报告记录(report_id 为空),则自动创建一条:
- INSERT INTO report (id, exam_id, createdAt, type)
- VALUES (UUID(), $examId, NOW(), 1)
- ---
- 3.2 补充机构信息(第86-89行)
- SELECT report_subtitle, report_title, hr_info
- FROM institution
- WHERE id = $detail['institution_id']
- 字段说明:
- - report_title:报告标题
- - report_subtitle:报告副标题
- - hr_info:医院简介信息
- ---
- 3.3 获取 DICOM 文件路径(第90-99行)
- SELECT dcm_path, dcm_type
- FROM dcm_path
- WHERE effective_date > NOW()
- AND study_id = $detail['study_id']
- 字段说明:
- - dcm_path:DICOM 文件路径
- - dcm_type:存储类型(1=本地路径,其他=云存储)
- - effective_date:有效期(只查询未过期的)
- 路径处理:
- - 如果 dcm_type != 1,调用 makeFileUrl() 生成云存储访问URL
- ---
- 3.4 处理医生签名(第101-117行)
- // 三个医生的签名处理逻辑相同
- $detail['report_autograph'] = ($detail['report_use_autograph'] == 1)
- ? (empty($detail['report_autograph'])
- ? ''
- : $this->makeFileUrl($detail['report_autograph'], $detail['report_autograph_type']))
- : '';
- 逻辑:
- 1. 检查医生是否启用签名(is_use_autograph = 1)
- 2. 如果启用且有签名文件,则生成访问URL
- 3. 否则返回空字符串
- ---
- 3.5 查询医生所属机构(第119-126行)
- -- 根据报告医生ID查询
- SELECT i.name, d.introduce
- FROM doctors d
- LEFT JOIN institution i ON d.institution_id = i.id
- WHERE d.id = $detail['report_doctor_id']
- 返回字段:
- - institution:医生所属机构名称
- - introduce:医生简介
- ---
- 3.6 获取操作痕迹(第129-138行)
- SELECT
- r.impression, -- 印象(诊断结论)
- r.description, -- 描述(报告内容)
- r.report_result, -- 报告结果
- r.createdAt as handle_time, -- 操作时间
- d.realname, -- 操作医生姓名
- r.type -- 操作类型
- FROM report_record r
- LEFT JOIN doctors d ON r.doctor_id = d.id
- WHERE r.report_id = $detail['report_id']
- ORDER BY r.createdAt ASC
- 字段说明:
- - report_record 表记录报告的每次修改历史
- - type 可能值:1=书写,2=审核,3=确认等
- ---
- 3.7 获取草稿内容(第139-160行)
- 逻辑:
- 1. 如果报告已完成(exam_status = 9 或 report_status = 9),不加载草稿
- 2. 从缓存中读取当前医生的草稿:
- $userId = getUserId($token);
- $cacheToken = getStageKey($report_id, $userId);
- $stage = getCache($cacheToken);
- 3. 如果存在草稿,用草稿内容覆盖数据库内容:
- $detail['impression'] = $stage['impression']; // 诊断结论
- $detail['description'] = $stage['description']; // 报告描述
- ---
- 4. 数据表结构
- 涉及的主要数据表:
- | 表名 | 作用 |
- |--------------------|--------------------|
- | exams | 检查信息(患者、检查项目、状态等) |
- | report | 报告信息(印象、描述、医生、时间等) |
- | register | 登记信息(检查部位、检查子类等) |
- | remote_application | 远程申请信息 |
- | doctors | 医生信息(姓名、签名、所属机构等) |
- | institution | 机构信息(报告标题、副标题等) |
- | dcm_path | DICOM文件路径 |
- | report_record | 报告操作记录(历史痕迹) |
- ---
- 5. 返回数据结构
- {
- // 检查基础信息
- exam_id: "检查ID",
- is_remote: "1=远程 2=本地",
- patient_num: "病历号",
- name: "患者姓名",
- sex: "性别",
- age: "年龄",
- phone: "手机号",
- exam_class: "检查类别",
- exam_datetime: "检查时间",
- exam_status: "检查状态",
- exam_project: "检查项目",
- accession_num: "检查号",
- body_part: "检查部位",
- // 报告信息
- report_id: "报告ID",
- impression: "印象(诊断结论)",
- description: "描述(报告内容)",
- report_result: "报告结果",
- // 医生信息
- report_doctor_id: "报告医生ID",
- report_doctor_name: "报告医生姓名",
- report_datetime: "报告时间",
- review_doctor_id: "审核医生ID",
- review_doctor_name: "审核医生姓名",
- review_datetime: "审核时间",
- confirm_doctor_id: "确认医生ID",
- confirm_doctor_name: "确认医生姓名",
- confirm_datetime: "确认时间",
- // 医生签名
- report_use_autograph: "报告医生是否使用签名",
- report_autograph: "报告医生签名URL",
- review_use_autograph: "审核医生是否使用签名",
- review_autograph: "审核医生签名URL",
- confirm_use_autograph: "确认医生是否使用签名",
- confirm_autograph: "确认医生签名URL",
- // 机构信息
- institution_id: "机构ID",
- institution: "报告医生所属机构名称",
- introduce: "医生简介",
- report_title: "报告标题",
- report_subtitle: "报告副标题",
- hr_info: "医院简介",
- // DICOM信息
- study_id: "StudyID",
- dcm_path: "DICOM文件路径",
- dcm_type: "存储类型",
- // 操作痕迹
- trace: [
- {
- impression: "印象",
- description: "描述",
- report_result: "结果",
- handle_time: "操作时间",
- realname: "操作医生",
- type: "操作类型"
- }
- ],
- // 其他
- qr_code: "二维码",
- remote_application_id: "远程申请ID"
- }
- ---
- 6. 核心特性
- 1. 自动创建报告:首次打开报告详情时,如果不存在报告记录,自动创建
- 2. 草稿机制:未完成的报告优先显示缓存中的草稿内容
- 3. 医生签名:支持三个医生(报告、审核、确认)的电子签名
- 4. 操作痕迹:记录报告的所有修改历史
- 5. DICOM路径:支持本地路径和云存储,且有有效期校验
- 6. 远程报告:支持本地报告和远程申请报告两种模式
- ---
- 这就是 report/details 接口的完整实现逻辑。该接口是报告书写页面的核心数据接口,提供了报告编写所需的所有信息。
- 无论本地还是远程报告,获取基础信息后,都会执行相同的补充逻辑:
- 1. ✅ 查询机构信息(报告标题、副标题)
- 2. ✅ 获取 DICOM 文件路径
- 3. ✅ 处理医生签名(报告/审核/确认医生)
- 4. ✅ 查询医生所属机构
- 5. ✅ 获取操作痕迹
- 6. ✅ 加载草稿内容
|