基于对 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. ✅ 加载草稿内容