LIJU 1 month ago
parent
commit
1d5dcdf912
1 changed files with 1437 additions and 0 deletions
  1. 1437 0
      江苏工伤联网接口数据库设计文档.md

+ 1437 - 0
江苏工伤联网接口数据库设计文档.md

@@ -0,0 +1,1437 @@
+# 工伤联网接口数据库设计文档
+
+## 版本信息
+
+| 版本号 | 修改内容 | 修改日期 | 修改人 |
+|--------|----------|----------|--------|
+| V1.0 | 初始版本设计 | 2024.12.19 | 系统架构师 |
+
+## 目录
+
+- [1 设计概述](#1-设计概述)
+- [2 数据库表设计](#2-数据库表设计)
+- [3 表关联关系](#3-表关联关系)
+- [4 使用案例](#4-使用案例)
+- [5 前端示例代码](#5-前端示例代码)
+- [6 后端示例代码](#6-后端示例代码)
+
+---
+
+## 1 设计概述
+
+### 1.1 业务需求
+
+1. **工伤病人流程**:先调用工伤接口 → 存储调用记录 → 再调用HIS接口 → 存储HIS数据
+2. **非工伤病人流程**:只调用HIS接口 → 存储HIS数据  
+3. **接口类型支持**:认证类、业务类、体检类、转院类、对账类、下载类
+4. **设计原则**:简单、实用、可靠、通用、不为每个接口单独设计
+
+### 1.2 设计思路
+
+采用**3表设计**方案,通过通用化设计支持所有工伤接口类型:
+
+- **工伤接口调用记录表**:记录所有工伤接口的调用情况
+- **工伤病人关联信息表**:管理HIS病人与工伤系统的对应关系
+- **工伤业务数据记录表**:存储具体的业务数据和结果
+
+---
+
+## 2 数据库表设计
+
+### 2.1 工伤接口调用记录表 (WorkInjury_Interface_Log)
+
+> **作用**:记录每一次工伤接口的调用情况,包括请求参数、响应结果、调用状态等
+> **应用场景**:所有工伤接口调用都要记录,用于日志追踪、问题排查、数据分析
+
+```sql
+CREATE TABLE WorkInjury_Interface_Log (
+    -- 主键信息
+    LogId BIGINT IDENTITY(1,1) PRIMARY KEY,
+    
+    -- 业务关联信息(用于关联HIS系统的病人和就诊)
+    HisPatientId VARCHAR(50),                    -- HIS系统病人ID(病人表主键)
+    HisVisitNo VARCHAR(50),                      -- HIS系统就诊流水号/住院号
+    WorkInjuryTransactionId VARCHAR(50),         -- 工伤系统交易流水号
+    
+    -- 接口调用信息(标识调用的是哪个工伤接口)
+    InterfaceCode VARCHAR(10) NOT NULL,          -- 接口编号:9001签到,2201登记,2207结算等
+    InterfaceName VARCHAR(100),                  -- 接口名称:签到,门诊登记,费用结算等
+    InterfaceCategory VARCHAR(20),               -- 接口分类:认证类,业务类,体检类,对账类,下载类
+    
+    -- 调用参数记录(完整保存调用的入参和返回参数)
+    RequestData NTEXT,                           -- 请求参数JSON:调用工伤接口时的完整入参
+    ResponseData NTEXT,                          -- 响应参数JSON:工伤接口返回的完整数据
+    
+    -- 调用结果信息(判断接口调用是否成功)
+    CallResult BIT NOT NULL DEFAULT 0,           -- 调用结果:0失败,1成功
+    ResultCode VARCHAR(20),                      -- 结果编码:工伤接口返回的错误码
+    ResultMessage NVARCHAR(500),                 -- 结果描述:错误信息或成功提示
+    
+    -- 工伤系统返回的关键信息(用于后续业务关联)
+    WorkInjuryMsgId VARCHAR(50),                 -- 工伤系统报文ID:用于冲正等操作
+    WorkInjurySignNo VARCHAR(50),                -- 工伤系统签到流水号:业务操作必需
+    WorkInjuryQualificationId VARCHAR(50),       -- 工伤资格审核ID:登记时返回的资格ID
+    
+    -- 时间和操作信息(记录操作过程信息)
+    CallTime DATETIME NOT NULL DEFAULT GETDATE(), -- 调用时间:接口实际调用的时间
+    OperatorId VARCHAR(50),                      -- 操作员ID:谁操作的
+    OperatorName NVARCHAR(50),                   -- 操作员姓名:操作员中文名
+    TerminalId VARCHAR(50),                      -- 终端ID:哪台机器操作的
+    
+    -- 扩展字段(用于存储特殊数据)
+    Remark NVARCHAR(500),                        -- 备注:额外说明信息
+    ExtendData NTEXT,                            -- 扩展数据JSON:特殊业务数据
+    
+    -- 创建和修改信息
+    CreateTime DATETIME NOT NULL DEFAULT GETDATE(),
+    UpdateTime DATETIME NOT NULL DEFAULT GETDATE()
+);
+
+-- 创建索引(提高查询性能)
+CREATE INDEX IX_WorkInjury_Interface_Log_Patient ON WorkInjury_Interface_Log(HisPatientId, CallTime);
+CREATE INDEX IX_WorkInjury_Interface_Log_Visit ON WorkInjury_Interface_Log(HisVisitNo, InterfaceCode);
+CREATE INDEX IX_WorkInjury_Interface_Log_Interface ON WorkInjury_Interface_Log(InterfaceCode, CallTime);
+CREATE INDEX IX_WorkInjury_Interface_Log_MsgId ON WorkInjury_Interface_Log(WorkInjuryMsgId);
+```
+
+### 2.2 工伤病人关联信息表 (WorkInjury_Patient_Relation)
+
+> **作用**:管理HIS系统病人与工伤系统的对应关系,判断病人是否为工伤性质
+> **应用场景**:病人登记时判断是否需要调用工伤接口,读卡时建立关联关系
+
+```sql
+CREATE TABLE WorkInjury_Patient_Relation (
+    -- 主键信息
+    RelationId BIGINT IDENTITY(1,1) PRIMARY KEY,
+    
+    -- HIS系统病人信息(关联HIS病人表)
+    HisPatientId VARCHAR(50) NOT NULL,           -- HIS系统病人ID:HIS病人表主键
+    HisCardNo VARCHAR(50),                       -- HIS病人卡号:院内就诊卡号
+    HisPatientName NVARCHAR(50),                 -- HIS病人姓名:在HIS中的姓名
+    HisIdCard VARCHAR(30),                       -- HIS身份证号:HIS中的身份证
+    
+    -- 工伤系统病人信息(来自工伤读卡接口返回数据)
+    WorkInjuryCardNo VARCHAR(50),                -- 工伤社保卡号:工伤系统的卡号
+    WorkInjuryPsnNo VARCHAR(50),                 -- 工伤个人唯一识别码:工伤系统病人标识
+    WorkInjuryPsnName NVARCHAR(50),              -- 工伤系统病人姓名:工伤系统中的姓名
+    WorkInjuryIdCard VARCHAR(30),                -- 工伤系统身份证号:可能与HIS不完全一致
+    WorkInjuryInsuranceArea VARCHAR(20),         -- 工伤保险统筹区:如"宿迁市"
+    
+    -- 工伤资格信息(判断病人工伤性质和资格)
+    IsWorkInjuryPatient BIT NOT NULL DEFAULT 0,  -- 是否工伤病人:0否,1是
+    WorkInjuryType VARCHAR(20),                  -- 工伤类型:门诊,住院,体检等
+    QualificationId VARCHAR(50),                 -- 工伤医疗费资格审核信息ID
+    QualificationStatus VARCHAR(20),             -- 资格审核状态:有效,过期,暂停等
+    QualificationExpireDate DATETIME,            -- 资格有效期:过期需重新审核
+    
+    -- 最近读卡信息(记录最新的工伤读卡数据)
+    LastReadCardTime DATETIME,                   -- 最后读卡时间:最近一次成功读卡时间
+    LastReadCardData NTEXT,                      -- 最后读卡返回数据JSON:完整的读卡结果
+    
+    -- 状态信息
+    Status CHAR(1) NOT NULL DEFAULT '1',         -- 状态:1有效,0无效,2暂停
+    
+    -- 扩展字段
+    Remark NVARCHAR(500),                        -- 备注:特殊说明
+    ExtendData NTEXT,                            -- 扩展数据JSON:其他相关数据
+    
+    -- 创建和修改信息
+    CreateTime DATETIME NOT NULL DEFAULT GETDATE(),
+    UpdateTime DATETIME NOT NULL DEFAULT GETDATE()
+);
+
+-- 创建索引和约束
+CREATE UNIQUE INDEX IX_WorkInjury_Patient_Relation_HisPatient ON WorkInjury_Patient_Relation(HisPatientId);
+CREATE INDEX IX_WorkInjury_Patient_Relation_WorkInjury ON WorkInjury_Patient_Relation(WorkInjuryPsnNo, WorkInjuryCardNo);
+CREATE INDEX IX_WorkInjury_Patient_Relation_IdCard ON WorkInjury_Patient_Relation(WorkInjuryIdCard);
+``` 
+
+### 2.3 工伤业务数据记录表 (WorkInjury_Business_Data)
+
+> **作用**:存储具体的工伤业务数据,如登记信息、结算信息、处方明细、体检数据等
+> **应用场景**:保存业务办理的详细数据,用于业务查询、数据统计、单据打印等
+
+```sql
+CREATE TABLE WorkInjury_Business_Data (
+    -- 主键信息
+    BusinessId BIGINT IDENTITY(1,1) PRIMARY KEY,
+    
+    -- 关联信息(与前两个表关联)
+    LogId BIGINT,                                -- 关联接口调用记录表ID:哪次接口调用产生的数据
+    HisPatientId VARCHAR(50),                    -- HIS系统病人ID:对应病人表
+    HisVisitNo VARCHAR(50),                      -- HIS系统就诊号:门诊号或住院号
+    
+    -- 业务类型信息(标识业务类型)
+    BusinessType VARCHAR(20) NOT NULL,           -- 业务类型:登记,结算,处方,体检,对账,下载等
+    BusinessCode VARCHAR(10),                    -- 业务编码:2201,2207,2204,8104,1320等
+    BusinessStatus VARCHAR(20),                  -- 业务状态:成功,失败,撤销,已冲正等
+    
+    -- 工伤系统业务关键信息(来自工伤接口返回)
+    WorkInjuryRegisterNo VARCHAR(50),            -- 工伤登记流水号:登记成功后返回
+    WorkInjurySettleNo VARCHAR(50),              -- 工伤结算流水号:结算成功后返回
+    WorkInjuryPreSettleId VARCHAR(50),           -- 工伤预结算ID:预结算返回的ID
+    
+    -- 费用信息(结算相关业务使用)
+    TotalFee DECIMAL(15,2),                      -- 总费用:本次业务涉及的总金额
+    WorkInjuryFee DECIMAL(15,2),                 -- 工伤基金支付:工伤保险支付金额
+    PersonalFee DECIMAL(15,2),                   -- 个人支付:病人自付金额
+    HospitalFee DECIMAL(15,2),                   -- 医院垫付:医院需要垫付的金额
+    
+    -- 业务详细数据(JSON格式存储复杂数据)
+    BusinessDetailData NTEXT,                    -- 业务明细数据JSON:处方明细,费用明细,体检项目等
+    HisBusinessData NTEXT,                       -- HIS系统业务数据JSON:HIS相关的业务数据
+    WorkInjuryResponseData NTEXT,                -- 工伤接口完整返回JSON:完整的工伤接口返回数据
+    
+    -- 相关单据信息(用于单据管理)
+    HisReceiptNo VARCHAR(50),                    -- HIS发票号:HIS系统生成的发票号
+    WorkInjuryReceiptNo VARCHAR(50),             -- 工伤结算单号:工伤系统的结算单号
+    HisPrescriptionNo VARCHAR(50),               -- HIS处方号:处方相关业务使用
+    
+    -- 时间信息
+    BusinessTime DATETIME,                       -- 业务发生时间:实际业务办理时间
+    
+    -- 撤销和冲正信息(业务可能需要撤销)
+    IsReversed BIT DEFAULT 0,                    -- 是否已冲正:0否,1是
+    ReversedLogId BIGINT,                        -- 冲正操作的日志ID:关联到冲正接口调用记录
+    ReversedTime DATETIME,                       -- 冲正时间:什么时候冲正的
+    ReversedReason NVARCHAR(200),                -- 冲正原因:为什么要冲正
+    
+    -- 扩展字段
+    Remark NVARCHAR(500),                        -- 备注:业务特殊说明
+    ExtendData NTEXT,                            -- 扩展数据JSON:其他业务数据
+    
+    -- 创建和修改信息
+    CreateTime DATETIME NOT NULL DEFAULT GETDATE(),
+    UpdateTime DATETIME NOT NULL DEFAULT GETDATE()
+);
+
+-- 创建索引
+CREATE INDEX IX_WorkInjury_Business_Data_LogId ON WorkInjury_Business_Data(LogId);
+CREATE INDEX IX_WorkInjury_Business_Data_Patient ON WorkInjury_Business_Data(HisPatientId, BusinessTime);
+CREATE INDEX IX_WorkInjury_Business_Data_Visit ON WorkInjury_Business_Data(HisVisitNo, BusinessType);
+CREATE INDEX IX_WorkInjury_Business_Data_WorkInjury ON WorkInjury_Business_Data(WorkInjuryRegisterNo, WorkInjurySettleNo);
+CREATE INDEX IX_WorkInjury_Business_Data_Business ON WorkInjury_Business_Data(BusinessType, BusinessStatus, BusinessTime);
+```
+
+---
+
+## 3 表关联关系
+
+### 3.1 表关系图
+
+```
+HIS病人表 (His_Patient)
+     ↓ (1:1)
+工伤病人关联表 (WorkInjury_Patient_Relation)  
+     ↓ (1:N)
+工伤接口调用记录表 (WorkInjury_Interface_Log)
+     ↓ (1:N)  
+工伤业务数据记录表 (WorkInjury_Business_Data)
+```
+
+### 3.2 关联说明
+
+1. **HIS病人表 ← → 工伤病人关联表**
+   - 关联字段:`HisPatientId`
+   - 关系:一对一,一个HIS病人对应一条工伤关联记录
+   - 用途:判断病人是否为工伤性质
+
+2. **工伤病人关联表 → 工伤接口调用记录表**
+   - 关联字段:`HisPatientId`
+   - 关系:一对多,一个病人可以有多次接口调用
+   - 用途:追踪病人的所有工伤接口调用历史
+
+3. **工伤接口调用记录表 → 工伤业务数据记录表**
+   - 关联字段:`LogId`
+   - 关系:一对多,一次接口调用可能产生多条业务数据
+   - 用途:存储接口调用产生的具体业务数据
+
+### 3.3 数据流向
+
+```
+病人挂号/就诊
+       ↓
+判断是否工伤病人 (查询WorkInjury_Patient_Relation)
+       ↓ (是工伤)
+调用工伤接口 → 记录到WorkInjury_Interface_Log
+       ↓ (成功)
+解析业务数据 → 存储到WorkInjury_Business_Data
+       ↓
+调用HIS接口 → 存储HIS业务数据
+```
+
+---
+
+## 4 使用案例
+
+### 4.1 典型业务场景案例
+
+#### 4.1.1 工伤病人门诊登记流程
+
+**场景描述**:工伤病人来医院看门诊,需要先在工伤系统登记,再在HIS系统登记
+
+**数据操作流程**:
+
+```sql
+-- 1. 判断是否工伤病人
+SELECT IsWorkInjuryPatient, WorkInjuryPsnNo, QualificationId 
+FROM WorkInjury_Patient_Relation 
+WHERE HisPatientId = 'P12345' AND Status = '1';
+
+-- 如果是工伤病人,继续以下步骤:
+
+-- 2. 调用工伤登记接口后,记录接口调用日志
+INSERT INTO WorkInjury_Interface_Log (
+    HisPatientId, HisVisitNo, InterfaceCode, InterfaceName, InterfaceCategory,
+    RequestData, ResponseData, CallResult, ResultCode, ResultMessage,
+    WorkInjuryMsgId, WorkInjuryQualificationId, CallTime, OperatorId, OperatorName
+) VALUES (
+    'P12345', 'MZ2024120100001', '2201', '门诊/住院登记', '业务类',
+    '{"infno":"2201","psn_no":"32123456789","med_type":"11",...}',
+    '{"infcode":"0","output":{"ipt_otp_no":"WS2024120100001"},...}',
+    1, '0', '登记成功',
+    'SQ201348202412011030001', 'WS2024120100001', GETDATE(), 'DOC001', '张医生'
+);
+
+-- 3. 记录业务数据
+INSERT INTO WorkInjury_Business_Data (
+    LogId, HisPatientId, HisVisitNo, BusinessType, BusinessCode, BusinessStatus,
+    WorkInjuryRegisterNo, BusinessDetailData, BusinessTime
+) VALUES (
+    @@IDENTITY, 'P12345', 'MZ2024120100001', '登记', '2201', '成功',
+    'WS2024120100001', '{"med_type":"11","adm_dept":"内科",...}', GETDATE()
+);
+```
+
+#### 4.1.2 工伤费用结算流程
+
+**场景描述**:工伤病人看完病,需要先在工伤系统结算,确定报销金额,再在HIS收费
+
+```sql
+-- 1. 处方明细上传
+INSERT INTO WorkInjury_Interface_Log (...) VALUES (...); -- 接口调用日志
+INSERT INTO WorkInjury_Business_Data (
+    LogId, HisPatientId, HisVisitNo, BusinessType, BusinessCode,
+    BusinessDetailData, BusinessTime
+) VALUES (
+    @@IDENTITY, 'P12345', 'MZ2024120100001', '处方', '2204',
+    '{"feedetail":[{"med_list_codg":"A01.01.001","med_name":"阿莫西林",...}]}',
+    GETDATE()
+);
+
+-- 2. 费用预结算
+INSERT INTO WorkInjury_Interface_Log (...) VALUES (...);
+INSERT INTO WorkInjury_Business_Data (
+    LogId, HisPatientId, HisVisitNo, BusinessType, BusinessCode,
+    WorkInjuryPreSettleId, TotalFee, WorkInjuryFee, PersonalFee,
+    BusinessDetailData, BusinessTime
+) VALUES (
+    @@IDENTITY, 'P12345', 'MZ2024120100001', '预结算', '2206',
+    'PRE20241201001', 150.00, 120.00, 30.00,
+    '{"pre_settle_data":{"psn_part_amt":30.00,"fund_pay_amt":120.00}}',
+    GETDATE()
+);
+
+-- 3. 正式结算
+INSERT INTO WorkInjury_Interface_Log (...) VALUES (...);
+INSERT INTO WorkInjury_Business_Data (
+    LogId, HisPatientId, HisVisitNo, BusinessType, BusinessCode,
+    WorkInjurySettleNo, TotalFee, WorkInjuryFee, PersonalFee,
+    WorkInjuryReceiptNo, BusinessTime
+) VALUES (
+    @@IDENTITY, 'P12345', 'MZ2024120100001', '结算', '2207',
+    'SET20241201001', 150.00, 120.00, 30.00,
+    'WS2024120100001', GETDATE()
+);
+```
+
+#### 4.1.3 对账类接口使用
+
+**场景描述**:每日对账,下载工伤系统的结算汇总数据
+
+```sql
+-- 总额对账接口调用
+INSERT INTO WorkInjury_Interface_Log (
+    InterfaceCode, InterfaceName, InterfaceCategory,
+    RequestData, ResponseData, CallResult,
+    BusinessDetailData, CallTime, OperatorId
+) VALUES (
+    '1320', '总额对账', '对账类',
+    '{"stmt_begndate":"20241201","stmt_enddate":"20241201"}',
+    '{"infcode":"0","output":{"total_cnt":15,"total_amt":2250.00}}',
+    1,
+    '{"account_date":"20241201","total_count":15,"total_amount":2250.00}',
+    GETDATE(), 'SYS001'
+);
+
+-- 对账业务数据记录
+INSERT INTO WorkInjury_Business_Data (
+    LogId, BusinessType, BusinessCode, BusinessStatus,
+    TotalFee, BusinessDetailData, BusinessTime
+) VALUES (
+    @@IDENTITY, '对账', '1320', '成功',
+    2250.00, '{"account_date":"20241201","detail_count":15}', GETDATE()
+);
+```
+
+#### 4.1.4 下载类接口使用
+
+**场景描述**:下载费用明细数据,用于对账核实
+
+```sql
+-- 费用明细下载
+INSERT INTO WorkInjury_Interface_Log (
+    InterfaceCode, InterfaceName, InterfaceCategory,
+    RequestData, ResponseData, CallResult,
+    BusinessDetailData, CallTime
+) VALUES (
+    '9103', '费用明细详细信息下载', '下载类',
+    '{"queryCond":{"stmt_begndate":"20241201","stmt_enddate":"20241201"}}',
+    '{"infcode":"0","output":{"feedetail":[...]}}',
+    1,
+    '{"download_date":"20241201","record_count":156}',
+    GETDATE()
+);
+```
+
+---
+
+## 5 前端示例代码
+
+### 5.1 jQuery 示例 - 工伤病人登记
+
+```html
+<!DOCTYPE html>
+<html>
+<head>
+    <title>工伤病人登记</title>
+    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+</head>
+<body>
+    <div class="patient-register">
+        <h3>工伤病人登记</h3>
+        
+        <!-- 病人信息 -->
+        <div class="patient-info">
+            <label>病人ID: <input type="text" id="patientId" value="P12345"></label>
+            <label>就诊卡号: <input type="text" id="cardNo"></label>
+            <label>病人姓名: <input type="text" id="patientName"></label>
+            <button id="checkWorkInjury">检查工伤性质</button>
+        </div>
+
+        <!-- 工伤信息显示 -->
+        <div id="workInjuryInfo" style="display:none;">
+            <h4>工伤信息</h4>
+            <div id="workInjuryDetail"></div>
+            <button id="registerWorkInjury">工伤登记</button>
+        </div>
+
+        <!-- HIS登记 -->
+        <div class="his-register">
+            <h4>HIS系统登记</h4>
+            <label>科室: <select id="department"><option value="001">内科</option></select></label>
+            <label>医生: <select id="doctor"><option value="DOC001">张医生</option></select></label>
+            <button id="registerHis">HIS登记</button>
+        </div>
+
+        <!-- 结果显示 -->
+        <div id="result"></div>
+    </div>
+
+<script>
+$(document).ready(function() {
+    // 检查工伤性质
+    $('#checkWorkInjury').click(function() {
+        const patientId = $('#patientId').val();
+        
+        $.ajax({
+            url: '/api/workinjury/checkPatient',
+            method: 'POST',
+            contentType: 'application/json',
+            data: JSON.stringify({ patientId: patientId }),
+            success: function(response) {
+                if (response.success && response.data.isWorkInjuryPatient) {
+                    // 是工伤病人,显示工伤信息
+                    $('#workInjuryDetail').html(`
+                        <p>工伤卡号: ${response.data.workInjuryCardNo}</p>
+                        <p>个人识别码: ${response.data.workInjuryPsnNo}</p>
+                        <p>资格状态: ${response.data.qualificationStatus}</p>
+                        <p>有效期: ${response.data.qualificationExpireDate}</p>
+                    `);
+                    $('#workInjuryInfo').show();
+                } else {
+                    // 非工伤病人,直接显示HIS登记
+                    $('#result').html('<div class="info">该病人非工伤性质,直接进行HIS登记</div>');
+                }
+            },
+            error: function(xhr, status, error) {
+                $('#result').html('<div class="error">检查失败: ' + error + '</div>');
+            }
+        });
+    });
+
+    // 工伤登记
+    $('#registerWorkInjury').click(function() {
+        const patientId = $('#patientId').val();
+        const visitNo = 'MZ' + new Date().getFullYear() + 
+                       (new Date().getMonth() + 1).toString().padStart(2, '0') + 
+                       new Date().getDate().toString().padStart(2, '0') + '00001';
+        
+        const registerData = {
+            action: "RegisterPatient",
+            businessParams: {
+                ipt_otp_no: visitNo,
+                med_type: "11", // 门诊
+                adm_time: new Date().toISOString().replace(/[-:]/g, '').slice(0, 14),
+                adm_dept_codg: $('#department').val(),
+                atddr_no: $('#doctor').val()
+            },
+            identifyMode: "1"
+        };
+
+        $.ajax({
+            url: '/api/workinjury/transaction',
+            method: 'POST',
+            contentType: 'application/json',
+            data: JSON.stringify(registerData),
+            success: function(response) {
+                if (response.success) {
+                    $('#result').html('<div class="success">工伤登记成功,登记号: ' + 
+                                    response.data.ipt_otp_no + '</div>');
+                    
+                    // 工伤登记成功后,自动进行HIS登记
+                    $('#registerHis').click();
+                } else {
+                    $('#result').html('<div class="error">工伤登记失败: ' + response.message + '</div>');
+                }
+            }
+        });
+    });
+
+    // HIS登记
+    $('#registerHis').click(function() {
+        const hisRegisterData = {
+            patientId: $('#patientId').val(),
+            patientName: $('#patientName').val(),
+            department: $('#department').val(),
+            doctor: $('#doctor').val(),
+            visitType: '门诊'
+        };
+
+        $.ajax({
+            url: '/api/his/register',
+            method: 'POST',
+            contentType: 'application/json',
+            data: JSON.stringify(hisRegisterData),
+            success: function(response) {
+                if (response.success) {
+                    $('#result').append('<div class="success">HIS登记成功,就诊号: ' + 
+                                      response.data.visitNo + '</div>');
+                } else {
+                    $('#result').append('<div class="error">HIS登记失败: ' + response.message + '</div>');
+                }
+            }
+        });
+    });
+});
+</script>
+
+<style>
+.patient-register { padding: 20px; }
+.patient-info, .his-register { margin: 15px 0; padding: 10px; border: 1px solid #ddd; }
+label { display: block; margin: 5px 0; }
+input, select { margin-left: 10px; padding: 5px; }
+button { margin: 10px 5px; padding: 8px 15px; background: #007cba; color: white; border: none; cursor: pointer; }
+.success { color: green; font-weight: bold; }
+.error { color: red; font-weight: bold; }
+.info { color: blue; font-weight: bold; }
+</style>
+</body>
+</html>
+```
+
+### 5.2 Vue 3.0 示例 - 工伤费用结算
+
+```vue
+<template>
+  <div class="work-injury-settlement">
+    <h3>工伤费用结算</h3>
+    
+    <!-- 病人选择 -->
+    <div class="patient-select">
+      <el-form :model="patientForm" inline>
+        <el-form-item label="就诊号">
+          <el-input v-model="patientForm.visitNo" placeholder="请输入就诊号"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadPatientInfo">加载病人信息</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 病人信息显示 -->
+    <div v-if="patientInfo.patientId" class="patient-info">
+      <h4>病人信息</h4>
+      <el-descriptions :column="3" border>
+        <el-descriptions-item label="病人姓名">{{ patientInfo.patientName }}</el-descriptions-item>
+        <el-descriptions-item label="就诊卡号">{{ patientInfo.cardNo }}</el-descriptions-item>
+        <el-descriptions-item label="工伤性质">
+          <el-tag :type="patientInfo.isWorkInjury ? 'success' : 'info'">
+            {{ patientInfo.isWorkInjury ? '工伤病人' : '普通病人' }}
+          </el-tag>
+        </el-descriptions-item>
+      </el-descriptions>
+    </div>
+
+    <!-- 处方明细 -->
+    <div class="prescription-detail">
+      <h4>处方明细</h4>
+      <el-table :data="prescriptionList" border>
+        <el-table-column prop="medName" label="药品名称"></el-table-column>
+        <el-table-column prop="quantity" label="数量"></el-table-column>
+        <el-table-column prop="unitPrice" label="单价"></el-table-column>
+        <el-table-column prop="totalPrice" label="小计"></el-table-column>
+      </el-table>
+      <div class="total-fee">
+        <strong>总金额: ¥{{ totalFee.toFixed(2) }}</strong>
+      </div>
+    </div>
+
+    <!-- 结算操作 -->
+    <div class="settlement-actions">
+      <el-button v-if="patientInfo.isWorkInjury" 
+                 type="warning" 
+                 @click="uploadPrescription"
+                 :loading="uploading">
+        上传处方明细
+      </el-button>
+      
+      <el-button v-if="patientInfo.isWorkInjury" 
+                 type="info" 
+                 @click="preSettle"
+                 :loading="preSettling"
+                 :disabled="!prescriptionUploaded">
+        工伤预结算
+      </el-button>
+      
+      <el-button type="success" 
+                 @click="finalSettle"
+                 :loading="settling">
+        {{ patientInfo.isWorkInjury ? '工伤正式结算' : 'HIS收费结算' }}
+      </el-button>
+    </div>
+
+    <!-- 结算结果 -->
+    <div v-if="settlementResult" class="settlement-result">
+      <h4>结算结果</h4>
+      <el-card>
+        <div v-if="patientInfo.isWorkInjury">
+          <p><strong>工伤结算单号:</strong> {{ settlementResult.workInjurySettleNo }}</p>
+          <p><strong>总费用:</strong> ¥{{ settlementResult.totalFee }}</p>
+          <p><strong>工伤基金支付:</strong> ¥{{ settlementResult.workInjuryFee }}</p>
+          <p><strong>个人支付:</strong> ¥{{ settlementResult.personalFee }}</p>
+        </div>
+        <div v-else>
+          <p><strong>HIS收费单号:</strong> {{ settlementResult.hisReceiptNo }}</p>
+          <p><strong>应收金额:</strong> ¥{{ settlementResult.totalFee }}</p>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 操作记录 -->
+    <div class="operation-log">
+      <h4>操作记录</h4>
+      <el-timeline>
+        <el-timeline-item 
+          v-for="log in operationLogs" 
+          :key="log.id"
+          :timestamp="log.time"
+          :type="log.success ? 'success' : 'danger'">
+          {{ log.operation }}: {{ log.message }}
+        </el-timeline-item>
+      </el-timeline>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+
+// 响应式数据
+const patientForm = reactive({
+  visitNo: ''
+})
+
+const patientInfo = reactive({
+  patientId: '',
+  patientName: '',
+  cardNo: '',
+  isWorkInjury: false,
+  workInjuryPsnNo: '',
+  qualificationId: ''
+})
+
+const prescriptionList = ref([
+  { medName: '阿莫西林胶囊', quantity: 2, unitPrice: 25.00, totalPrice: 50.00 },
+  { medName: '布洛芬片', quantity: 1, unitPrice: 18.50, totalPrice: 18.50 },
+  { medName: '维生素C片', quantity: 1, unitPrice: 12.80, totalPrice: 12.80 }
+])
+
+const uploading = ref(false)
+const preSettling = ref(false)
+const settling = ref(false)
+const prescriptionUploaded = ref(false)
+const settlementResult = ref(null)
+const operationLogs = ref([])
+
+// 计算属性
+const totalFee = computed(() => {
+  return prescriptionList.value.reduce((sum, item) => sum + item.totalPrice, 0)
+})
+
+// 方法
+const loadPatientInfo = async () => {
+  try {
+    const response = await fetch('/api/workinjury/getPatientInfo', {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify({ visitNo: patientForm.visitNo })
+    })
+    
+    const result = await response.json()
+    if (result.success) {
+      Object.assign(patientInfo, result.data)
+      addOperationLog('加载病人信息', '成功', true)
+    } else {
+      ElMessage.error('加载病人信息失败: ' + result.message)
+      addOperationLog('加载病人信息', result.message, false)
+    }
+  } catch (error) {
+    ElMessage.error('加载病人信息异常: ' + error.message)
+    addOperationLog('加载病人信息', error.message, false)
+  }
+}
+
+const uploadPrescription = async () => {
+  uploading.value = true
+  try {
+    const prescriptionData = {
+      action: "UploadPrescription",
+      businessParams: {
+        feedetail: prescriptionList.value.map(item => ({
+          med_list_codg: item.medCode || 'A01.01.001',
+          med_name: item.medName,
+          med_qty: item.quantity,
+          pric: item.unitPrice,
+          det_item_fee_sumamt: item.totalPrice
+        }))
+      }
+    }
+
+    const response = await fetch('/api/workinjury/transaction', {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(prescriptionData)
+    })
+
+    const result = await response.json()
+    if (result.success) {
+      prescriptionUploaded.value = true
+      ElMessage.success('处方明细上传成功')
+      addOperationLog('上传处方明细', '成功', true)
+    } else {
+      ElMessage.error('处方明细上传失败: ' + result.message)
+      addOperationLog('上传处方明细', result.message, false)
+    }
+  } catch (error) {
+    ElMessage.error('处方明细上传异常: ' + error.message)
+    addOperationLog('上传处方明细', error.message, false)
+  } finally {
+    uploading.value = false
+  }
+}
+
+const preSettle = async () => {
+  preSettling.value = true
+  try {
+    const preSettleData = {
+      action: "PreSettle",
+      businessParams: {
+        ipt_otp_no: patientForm.visitNo,
+        psn_no: patientInfo.workInjuryPsnNo,
+        total_amt: totalFee.value
+      }
+    }
+
+    const response = await fetch('/api/workinjury/transaction', {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(preSettleData)
+    })
+
+    const result = await response.json()
+    if (result.success) {
+      ElMessage.success('工伤预结算成功')
+      addOperationLog('工伤预结算', 
+        `个人支付: ¥${result.data.psn_part_amt}, 基金支付: ¥${result.data.fund_pay_amt}`, 
+        true)
+    } else {
+      ElMessage.error('工伤预结算失败: ' + result.message)
+      addOperationLog('工伤预结算', result.message, false)
+    }
+  } catch (error) {
+    ElMessage.error('工伤预结算异常: ' + error.message)
+    addOperationLog('工伤预结算', error.message, false)
+  } finally {
+    preSettling.value = false
+  }
+}
+
+const finalSettle = async () => {
+  settling.value = true
+  try {
+    if (patientInfo.isWorkInjury) {
+      // 工伤正式结算
+      const settleData = {
+        action: "Settle",
+        businessParams: {
+          ipt_otp_no: patientForm.visitNo,
+          psn_no: patientInfo.workInjuryPsnNo
+        }
+      }
+
+      const response = await fetch('/api/workinjury/transaction', {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/json' },
+        body: JSON.stringify(settleData)
+      })
+
+      const result = await response.json()
+      if (result.success) {
+        settlementResult.value = {
+          workInjurySettleNo: result.data.setl_id,
+          totalFee: result.data.medfee_sumamt,
+          workInjuryFee: result.data.fund_pay_amt,
+          personalFee: result.data.psn_part_amt
+        }
+        ElMessage.success('工伤结算成功')
+        addOperationLog('工伤正式结算', '成功', true)
+
+        // 工伤结算成功后,调用HIS收费
+        await hisSettle()
+      } else {
+        ElMessage.error('工伤结算失败: ' + result.message)
+        addOperationLog('工伤正式结算', result.message, false)
+      }
+    } else {
+      // 直接HIS收费
+      await hisSettle()
+    }
+  } catch (error) {
+    ElMessage.error('结算异常: ' + error.message)
+    addOperationLog('结算操作', error.message, false)
+  } finally {
+    settling.value = false
+  }
+}
+
+const hisSettle = async () => {
+  try {
+    const hisSettleData = {
+      visitNo: patientForm.visitNo,
+      totalFee: patientInfo.isWorkInjury ? settlementResult.value?.personalFee : totalFee.value,
+      paymentMethod: '现金'
+    }
+
+    const response = await fetch('/api/his/settle', {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(hisSettleData)
+    })
+
+    const result = await response.json()
+    if (result.success) {
+      if (!settlementResult.value) {
+        settlementResult.value = {}
+      }
+      settlementResult.value.hisReceiptNo = result.data.receiptNo
+      if (!patientInfo.isWorkInjury) {
+        settlementResult.value.totalFee = totalFee.value
+      }
+      
+      ElMessage.success('HIS收费成功')
+      addOperationLog('HIS收费', '成功', true)
+    } else {
+      ElMessage.error('HIS收费失败: ' + result.message)
+      addOperationLog('HIS收费', result.message, false)
+    }
+  } catch (error) {
+    ElMessage.error('HIS收费异常: ' + error.message)
+    addOperationLog('HIS收费', error.message, false)
+  }
+}
+
+const addOperationLog = (operation, message, success) => {
+  operationLogs.value.unshift({
+    id: Date.now(),
+    operation,
+    message,
+    success,
+    time: new Date().toLocaleString()
+  })
+}
+</script>
+
+<style scoped>
+.work-injury-settlement {
+  padding: 20px;
+}
+
+.patient-select, .patient-info, .prescription-detail, 
+.settlement-actions, .settlement-result, .operation-log {
+  margin: 20px 0;
+}
+
+.total-fee {
+  text-align: right;
+  margin: 10px 0;
+  font-size: 16px;
+}
+
+.settlement-actions {
+  text-align: center;
+}
+
+.settlement-actions .el-button {
+  margin: 0 10px;
+}
+</style>
+```
+
+---
+
+## 6 后端示例代码
+
+### 6.1 Spring Boot 示例 - 工伤接口服务
+
+```java
+package com.hospital.workinjury.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.hospital.workinjury.entity.*;
+import com.hospital.workinjury.repository.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 工伤联网接口服务类
+ * 负责工伤接口调用和数据存储的核心业务逻辑
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WorkInjuryService {
+
+    private final WorkInjuryInterfaceLogRepository logRepository;
+    private final WorkInjuryPatientRelationRepository relationRepository;
+    private final WorkInjuryBusinessDataRepository businessRepository;
+    private final RestTemplate restTemplate;
+    private final ObjectMapper objectMapper;
+    
+    // 工伤接口地址配置
+    private static final String WORK_INJURY_API_URL = "http://localhost:8321/api/workinjury/transaction";
+
+    /**
+     * 检查病人工伤性质
+     * @param patientId HIS病人ID
+     * @return 工伤病人信息
+     */
+    public WorkInjuryPatientInfo checkWorkInjuryPatient(String patientId) {
+        log.info("检查病人工伤性质, patientId: {}", patientId);
+        
+        WorkInjuryPatientRelation relation = relationRepository.findByHisPatientId(patientId);
+        
+        WorkInjuryPatientInfo info = new WorkInjuryPatientInfo();
+        info.setPatientId(patientId);
+        
+        if (relation != null && relation.getIsWorkInjuryPatient()) {
+            info.setWorkInjuryPatient(true);
+            info.setWorkInjuryCardNo(relation.getWorkInjuryCardNo());
+            info.setWorkInjuryPsnNo(relation.getWorkInjuryPsnNo());
+            info.setQualificationId(relation.getQualificationId());
+            info.setQualificationStatus(relation.getQualificationStatus());
+            info.setQualificationExpireDate(relation.getQualificationExpireDate());
+        } else {
+            info.setWorkInjuryPatient(false);
+        }
+        
+        return info;
+    }
+
+    /**
+     * 工伤病人登记流程
+     * 先调用工伤接口,成功后记录数据,再调用HIS接口
+     */
+    @Transactional
+    public WorkInjuryRegisterResult registerWorkInjuryPatient(WorkInjuryRegisterRequest request) {
+        log.info("开始工伤病人登记流程, patientId: {}, visitNo: {}", 
+                request.getPatientId(), request.getVisitNo());
+        
+        WorkInjuryRegisterResult result = new WorkInjuryRegisterResult();
+        
+        try {
+            // 1. 检查是否工伤病人
+            WorkInjuryPatientRelation relation = relationRepository.findByHisPatientId(request.getPatientId());
+            if (relation == null || !relation.getIsWorkInjuryPatient()) {
+                // 非工伤病人,直接调用HIS登记
+                return registerHisPatientOnly(request);
+            }
+
+            // 2. 调用工伤登记接口
+            WorkInjuryApiResult workInjuryResult = callWorkInjuryRegisterApi(request, relation);
+            
+            // 3. 记录工伤接口调用日志
+            Long logId = saveInterfaceLog(request, workInjuryResult, "2201", "门诊/住院登记", "业务类");
+            
+            if (workInjuryResult.isSuccess()) {
+                // 4. 记录工伤业务数据
+                saveBusinessData(logId, request, workInjuryResult, "登记", "2201");
+                
+                // 5. 调用HIS登记接口
+                HisRegisterResult hisResult = callHisRegisterApi(request);
+                
+                // 6. 组装返回结果
+                result.setSuccess(true);
+                result.setMessage("工伤病人登记成功");
+                result.setWorkInjuryRegisterNo(workInjuryResult.getData().get("ipt_otp_no").toString());
+                result.setHisVisitNo(hisResult.getVisitNo());
+                result.setQualificationId(workInjuryResult.getData().get("qualification_id").toString());
+                
+                log.info("工伤病人登记成功, 工伤登记号: {}, HIS就诊号: {}", 
+                        result.getWorkInjuryRegisterNo(), result.getHisVisitNo());
+            } else {
+                result.setSuccess(false);
+                result.setMessage("工伤登记失败: " + workInjuryResult.getMessage());
+                log.error("工伤登记失败: {}", workInjuryResult.getMessage());
+            }
+            
+        } catch (Exception e) {
+            log.error("工伤病人登记异常", e);
+            result.setSuccess(false);
+            result.setMessage("登记异常: " + e.getMessage());
+        }
+        
+        return result;
+    }
+
+    /**
+     * 工伤费用结算流程
+     * 处方上传 -> 预结算 -> 正式结算 -> HIS收费
+     */
+    @Transactional
+    public WorkInjurySettlementResult settleWorkInjuryFee(WorkInjurySettlementRequest request) {
+        log.info("开始工伤费用结算流程, visitNo: {}", request.getVisitNo());
+        
+        WorkInjurySettlementResult result = new WorkInjurySettlementResult();
+        
+        try {
+            // 1. 检查病人工伤性质
+            WorkInjuryPatientRelation relation = relationRepository.findByHisPatientId(request.getPatientId());
+            if (relation == null || !relation.getIsWorkInjuryPatient()) {
+                // 非工伤病人,直接HIS收费
+                return settleHisFeeOnly(request);
+            }
+
+            // 2. 上传处方明细
+            WorkInjuryApiResult uploadResult = uploadPrescriptionDetail(request);
+            if (!uploadResult.isSuccess()) {
+                result.setSuccess(false);
+                result.setMessage("处方上传失败: " + uploadResult.getMessage());
+                return result;
+            }
+
+            // 3. 费用预结算
+            WorkInjuryApiResult preSettleResult = preSettleFee(request);
+            if (!preSettleResult.isSuccess()) {
+                result.setSuccess(false);
+                result.setMessage("预结算失败: " + preSettleResult.getMessage());
+                return result;
+            }
+
+            // 4. 正式结算
+            WorkInjuryApiResult settleResult = settleFee(request);
+            if (!settleResult.isSuccess()) {
+                result.setSuccess(false);
+                result.setMessage("工伤结算失败: " + settleResult.getMessage());
+                return result;
+            }
+
+            // 5. 解析结算结果
+            Map<String, Object> settleData = settleResult.getData();
+            BigDecimal totalFee = new BigDecimal(settleData.get("medfee_sumamt").toString());
+            BigDecimal workInjuryFee = new BigDecimal(settleData.get("fund_pay_amt").toString());
+            BigDecimal personalFee = new BigDecimal(settleData.get("psn_part_amt").toString());
+
+            // 6. 记录结算业务数据
+            Long logId = saveInterfaceLog(request, settleResult, "2207", "费用结算", "业务类");
+            saveSettlementBusinessData(logId, request, settleResult, totalFee, workInjuryFee, personalFee);
+
+            // 7. HIS收费(只收个人支付部分)
+            HisSettlementResult hisResult = callHisSettlementApi(request, personalFee);
+
+            // 8. 组装返回结果
+            result.setSuccess(true);
+            result.setMessage("工伤费用结算成功");
+            result.setWorkInjurySettleNo(settleData.get("setl_id").toString());
+            result.setTotalFee(totalFee);
+            result.setWorkInjuryFee(workInjuryFee);
+            result.setPersonalFee(personalFee);
+            result.setHisReceiptNo(hisResult.getReceiptNo());
+
+            log.info("工伤费用结算成功, 结算号: {}, 总费用: {}, 个人支付: {}", 
+                    result.getWorkInjurySettleNo(), totalFee, personalFee);
+
+        } catch (Exception e) {
+            log.error("工伤费用结算异常", e);
+            result.setSuccess(false);
+            result.setMessage("结算异常: " + e.getMessage());
+        }
+        
+        return result;
+    }
+
+    /**
+     * 对账接口调用
+     * 用于每日对账核对数据
+     */
+    public WorkInjuryAccountResult dailyAccount(String accountDate) {
+        log.info("开始工伤对账, 对账日期: {}", accountDate);
+        
+        WorkInjuryAccountResult result = new WorkInjuryAccountResult();
+        
+        try {
+            // 1. 构造对账请求参数
+            Map<String, Object> accountParams = new HashMap<>();
+            accountParams.put("stmt_begndate", accountDate);
+            accountParams.put("stmt_enddate", accountDate);
+
+            WorkInjuryApiRequest apiRequest = new WorkInjuryApiRequest();
+            apiRequest.setAction("TotalAccount");
+            apiRequest.setBusinessParams(accountParams);
+
+            // 2. 调用工伤总额对账接口
+            WorkInjuryApiResult apiResult = callWorkInjuryApi(apiRequest);
+            
+            // 3. 记录接口调用日志
+            Long logId = saveAccountInterfaceLog(apiRequest, apiResult, "1320", "总额对账", "对账类");
+            
+            if (apiResult.isSuccess()) {
+                // 4. 解析对账结果
+                Map<String, Object> accountData = apiResult.getData();
+                int totalCount = Integer.parseInt(accountData.get("total_cnt").toString());
+                BigDecimal totalAmount = new BigDecimal(accountData.get("total_amt").toString());
+                
+                // 5. 记录对账业务数据
+                saveAccountBusinessData(logId, accountDate, totalCount, totalAmount);
+                
+                // 6. 组装返回结果
+                result.setSuccess(true);
+                result.setMessage("对账成功");
+                result.setAccountDate(accountDate);
+                result.setTotalCount(totalCount);
+                result.setTotalAmount(totalAmount);
+                
+                log.info("工伤对账成功, 日期: {}, 笔数: {}, 金额: {}", accountDate, totalCount, totalAmount);
+            } else {
+                result.setSuccess(false);
+                result.setMessage("对账失败: " + apiResult.getMessage());
+                log.error("工伤对账失败: {}", apiResult.getMessage());
+            }
+            
+        } catch (Exception e) {
+            log.error("工伤对账异常", e);
+            result.setSuccess(false);
+            result.setMessage("对账异常: " + e.getMessage());
+        }
+        
+        return result;
+    }
+
+    /**
+     * 下载费用明细数据
+     * 用于对账核实和数据分析
+     */
+    public WorkInjuryDownloadResult downloadFeeDetail(String beginDate, String endDate) {
+        log.info("开始下载工伤费用明细, 开始日期: {}, 结束日期: {}", beginDate, endDate);
+        
+        WorkInjuryDownloadResult result = new WorkInjuryDownloadResult();
+        
+        try {
+            // 1. 构造下载请求参数
+            Map<String, Object> queryCondition = new HashMap<>();
+            queryCondition.put("stmt_begndate", beginDate);
+            queryCondition.put("stmt_enddate", endDate);
+            
+            Map<String, Object> downloadParams = new HashMap<>();
+            downloadParams.put("queryCond", queryCondition);
+
+            WorkInjuryApiRequest apiRequest = new WorkInjuryApiRequest();
+            apiRequest.setAction("QueryFeeDetail");
+            apiRequest.setBusinessParams(downloadParams);
+
+            // 2. 调用工伤费用明细下载接口
+            WorkInjuryApiResult apiResult = callWorkInjuryApi(apiRequest);
+            
+            // 3. 记录接口调用日志
+            Long logId = saveDownloadInterfaceLog(apiRequest, apiResult, "9103", "费用明细详细信息下载", "下载类");
+            
+            if (apiResult.isSuccess()) {
+                // 4. 解析下载结果
+                Map<String, Object> downloadData = apiResult.getData();
+                @SuppressWarnings("unchecked")
+                java.util.List<Map<String, Object>> feeDetailList = 
+                    (java.util.List<Map<String, Object>>) downloadData.get("feedetail");
+                
+                int recordCount = feeDetailList != null ? feeDetailList.size() : 0;
+                
+                // 5. 记录下载业务数据
+                saveDownloadBusinessData(logId, beginDate, endDate, recordCount, feeDetailList);
+                
+                // 6. 组装返回结果
+                result.setSuccess(true);
+                result.setMessage("下载成功");
+                result.setBeginDate(beginDate);
+                result.setEndDate(endDate);
+                result.setRecordCount(recordCount);
+                result.setFeeDetailList(feeDetailList);
+                
+                log.info("工伤费用明细下载成功, 记录数: {}", recordCount);
+            } else {
+                result.setSuccess(false);
+                result.setMessage("下载失败: " + apiResult.getMessage());
+                log.error("工伤费用明细下载失败: {}", apiResult.getMessage());
+            }
+            
+        } catch (Exception e) {
+            log.error("工伤费用明细下载异常", e);
+            result.setSuccess(false);
+            result.setMessage("下载异常: " + e.getMessage());
+        }
+        
+        return result;
+    }
+
+    // ==================== 私有辅助方法 ====================
+
+    /**
+     * 调用工伤登记接口
+     */
+    private WorkInjuryApiResult callWorkInjuryRegisterApi(
+            WorkInjuryRegisterRequest request, 
+            WorkInjuryPatientRelation relation) throws Exception {
+        
+        Map<String, Object> businessParams = new HashMap<>();
+        businessParams.put("ipt_otp_no", request.getVisitNo());
+        businessParams.put("med_type", "11"); // 门诊
+        businessParams.put("adm_time", LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
+        businessParams.put("adm_dept_codg", request.getDepartmentCode());
+        businessParams.put("atddr_no", request.getDoctorCode());
+        businessParams.put("psn_no", relation.getWorkInjuryPsnNo());
+        businessParams.put("qualification_id", relation.getQualificationId());
+
+        WorkInjuryApiRequest apiRequest = new WorkInjuryApiRequest();
+        apiRequest.setAction("RegisterPatient");
+        apiRequest.setBusinessParams(businessParams);
+        apiRequest.setIdentifyMode("1");
+
+        return callWorkInjuryApi(apiRequest);
+    }
+
+    /**
+     * 统一的工伤接口调用方法
+     */
+    private WorkInjuryApiResult callWorkInjuryApi(WorkInjuryApiRequest request) throws Exception {
+        log.debug("调用工伤接口, action: {}", request.getAction());
+        
+        ResponseEntity<Map> response = restTemplate.postForEntity(
+            WORK_INJURY_API_URL, 
+            request, 
+            Map.class
+        );
+        
+        Map<String, Object> responseBody = response.getBody();
+        
+        WorkInjuryApiResult result = new WorkInjuryApiResult();
+        result.setSuccess((Boolean) responseBody.get("success"));
+        result.setCode((String) responseBody.get("code"));
+        result.setMessage((String) responseBody.get("message"));
+        
+        if (result.isSuccess()) {
+            @SuppressWarnings("unchecked")
+            Map<String, Object> data = (Map<String, Object>) responseBody.get("data");
+            result.setData(data);
+        }
+        
+        return result;
+    }
+
+    /**
+     * 保存接口调用日志
+     */
+    private Long saveInterfaceLog(
+            Object request, 
+            WorkInjuryApiResult apiResult, 
+            String interfaceCode,
+            String interfaceName,
+            String interfaceCategory) {
+        
+        try {
+            WorkInjuryInterfaceLog log = new WorkInjuryInterfaceLog();
+            
+            // 设置基本信息
+            if (request instanceof WorkInjuryRegisterRequest) {
+                WorkInjuryRegisterRequest registerRequest = (WorkInjuryRegisterRequest) request;
+                log.setHisPatientId(registerRequest.getPatientId());
+                log.setHisVisitNo(registerRequest.getVisitNo());
+            } else if (request instanceof WorkInjurySettlementRequest) {
+                WorkInjurySettlementRequest settlementRequest = (WorkInjurySettlementRequest) request;
+                log.setHisPatientId(settlementRequest.getPatientId());
+                log.setHisVisitNo(settlementRequest.getVisitNo());
+            }
+            
+            log.setInterfaceCode(interfaceCode);
+            log.setInterfaceName(interfaceName);
+            log.setInterfaceCategory(interfaceCategory);
+            
+            // 设置请求和响应数据
+            log.setRequestData(objectMapper.writeValueAsString(request));
+            log.setResponseData(objectMapper.writeValueAsString(apiResult));
+            
+            // 设置调用结果
+            log.setCallResult(apiResult.isSuccess());
+            log.setResultCode(apiResult.getCode());
+            log.setResultMessage(apiResult.getMessage());
+            
+            // 设置工伤系统关键信息
+            if (apiResult.isSuccess() && apiResult.getData() != null) {
+                Map<String, Object> data = apiResult.getData();
+                log.setWorkInjuryMsgId((String) data.get("inf_refmsgid"));
+                log.setWorkInjuryQualificationId((String) data.get("qualification_id"));
+            }
+            
+            // 设置时间和操作信息
+            log.setCallTime(LocalDateTime.now());
+            log.setOperatorId("SYSTEM");
+            log.setOperatorName("系统自动");
+            
+            WorkInjuryInterfaceLog savedLog = logRepository.save(log);
+            return savedLog.getLogId();
+            
+        } catch (Exception e) {
+            log.error("保存接口调用日志失败", e);
+            return null;
+        }
+    }
+
+    /**
+     * 保存业务数据
+     */
+    private void saveBusinessData(
+            Long logId,
+            WorkInjuryRegisterRequest request,
+            WorkInjuryApiResult apiResult,
+            String businessType,
+            String businessCode) {
+        
+        try {
+            WorkInjuryBusinessData businessData = new WorkInjuryBusinessData();
+            
+            businessData.setLogId(logId);
+            businessData.setHisPatientId(request.getPatientId());
+            businessData.setHisVisitNo(request.getVisitNo());
+            businessData.setBusinessType(businessType);
+            businessData.setBusinessCode(businessCode);
+            businessData.setBusinessStatus("成功");
+            
+            if (apiResult.getData() != null) {
+                Map<String, Object> data = apiResult.getData();
+                businessData.setWorkInjuryRegisterNo((String) data.get("ipt_otp_no"));
+                businessData.setBusinessDetailData(objectMapper.writeValueAsString(data));
+            }
+            
+            businessData.setBusinessTime(LocalDateTime.now());
+            
+            businessRepository.save(businessData);
+            
+        } catch (Exception e) {
+            log.error("保存业务数据失败", e);
+        }
+    }
+
+    /**
+     * 保存结算业务数据
+     */
+    private void saveSettlementBusinessData(
+            Long logId,
+            WorkInjurySettlementRequest request,
+            WorkInjuryApiResult apiResult,
+            BigDecimal totalFee,
+            BigDecimal workInjuryFee,
+            BigDecimal personalFee) {
+        
+        try {
+            WorkInjuryBusinessData businessData = new WorkInjuryBusinessData();
+            
+            businessData.setLogId(logId);
+            businessData.setHisPatientId(request.getPatientId());
+            businessData.setHisVisitNo(request.getVisitNo());
+            businessData.setBusinessType("结算");
+            businessData.setBusinessCode("2207");
+            businessData.setBusinessStatus("成功");
+            
+            // 设置费用信息
+            businessData.setTotalFee(totalFee);
+            businessData.setWorkInjuryFee(workInjuryFee);
+            businessData.setPersonalFee(personalFee);
+            
+            if (apiResult.getData() != null) {
+                Map<String, Object> data = apiResult.getData();
+                businessData.setWorkInjurySettleNo((String) data.get("setl_id"));
+                businessData.setWorkInjuryReceiptNo((String) data.get("setl_detail_id"));
+                businessData.setBusinessDetailData(objectMapper.writeValueAsString(data));
+            }
+            
+            businessData.setBusinessTime(LocalDateTime.now());
+            
+            businessRepository.save(businessData);
+            
+        } catch (Exception e) {
+            log.error("保存结算业务数据失败", e);
+        }
+    }
+
+    // 其他辅助方法... (uploadPrescriptionDetail, preSettleFee, settleFee, callHisApi等)
+    // 为了节省篇幅,这里省略了部分辅助方法的实现
+}
+```
+
+这个完整的文档涵盖了:
+
+1. **数据库表设计**:3个通用表支持所有工伤接口类型
+2. **详细注释说明**:每个字段都有明确的用途说明
+3. **表关联关系**:清晰的关联逻辑和数据流向
+4. **使用案例**:典型业务场景的数据操作示例
+5. **前端代码**:jQuery和Vue 3.0的完整实现示例
+6. **后端代码**:Spring Boot的服务层实现
+
+这套设计方案能够完美实现您的需求:**工伤病人先调用工伤接口存储数据,再调用HIS接口;非工伤病人直接调用HIS接口**,同时通过通用化设计支持所有类型的工伤接口,简单实用可靠。