LIJU 1 月之前
父节点
当前提交
b0f7d82a42

+ 206 - 23
ThCardReader/EntryController.cs

@@ -1,4 +1,5 @@
-using Newtonsoft.Json.Linq;
+using System;
+using Newtonsoft.Json.Linq;
 using System.Web.Http;
 
 namespace ThCardReader
@@ -533,47 +534,117 @@ namespace ThCardReader
         /// </summary>
         [HttpPost]
         [Route("api/entry/workinjury")]
+        [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
+        [System.Security.SecurityCritical]
         public JObject PostWorkInjury([FromBody] JObject request)
         {
+            // 立即创建基础响应,确保总是有返回值
             JObject result = new JObject();
+            result["debug_entry_time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
+            result["debug_method_entered"] = true;
+            result["debug_stage"] = "方法入口";
 
             try
             {
+                // 添加调试信息确保响应不为空
+                result["debug_timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
+                result["debug_step"] = "Controller方法开始执行";
+                result["debug_stage"] = "开始处理";
+                
                 // 检查请求体
                 if (request == null)
                 {
-                    result.Add("success", false);
-                    result.Add("code", 1001);
-                    result.Add("message", "请求体不能为空");
-                    result.Add("device", "江苏工伤联网接口");
+                    result["success"] = false;
+                    result["code"] = 1001;
+                    result["message"] = "请求体不能为空";
+                    result["device"] = "江苏工伤联网接口";
+                    result["debug_step"] = "请求体为空";
                     return result;
                 }
+                
+                result["debug_step"] = "请求体检查通过";
+                result["debug_request"] = request;
 
                 // 获取操作类型
                 string action = request["action"]?.ToString()?.ToLower() ?? "";
+                result["debug_action"] = action;
+                result["debug_step"] = "解析action参数";
                 
                 if (string.IsNullOrEmpty(action))
                 {
-                    result.Add("success", false);
-                    result.Add("code", 1002);
-                    result.Add("message", "action参数不能为空");
-                    result.Add("device", "江苏工伤联网接口");
+                    result["success"] = false;
+                    result["code"] = 1002;
+                    result["message"] = "action参数不能为空";
+                    result["device"] = "江苏工伤联网接口";
+                    result["debug_step"] = "action参数为空";
                     return result;
                 }
 
+                result["debug_step"] = $"准备执行action: {action}";
+                
                 // 根据操作类型处理不同的请求
                 switch (action)
                 {
                     case "init":
-                        result = HandleWorkInjuryInit(request);
+                        result["debug_step"] = "执行初始化操作";
+                        result["debug_stage"] = "准备调用HandleWorkInjuryInit";
+                        
+                        // 添加立即返回测试 - 如果问题在DLL调用,我们先确保基础流程正常
+                        if (request["test_mode"] != null && request["test_mode"].ToString() == "immediate_return")
+                        {
+                            result["success"] = true;
+                            result["code"] = 200;
+                            result["message"] = "测试模式:立即返回成功";
+                            result["device"] = "江苏工伤联网接口";
+                            result["debug_step"] = "测试模式立即返回";
+                            result["test_config"] = request["config"];
+                            break;
+                        }
+                        
+                        try
+                        {
+                            var initResult = HandleWorkInjuryInit(request);
+                            if (initResult != null)
+                            {
+                                result = initResult;
+                                result["debug_controller_step"] = "初始化操作完成";
+                            }
+                            else
+                            {
+                                result["success"] = false;
+                                result["code"] = 1007;
+                                result["message"] = "HandleWorkInjuryInit返回null";
+                                result["device"] = "江苏工伤联网接口";
+                                result["debug_step"] = "HandleWorkInjuryInit返回null";
+                            }
+                        }
+                        catch (System.Exception initEx)
+                        {
+                            result["success"] = false;
+                            result["code"] = 1008;
+                            result["message"] = $"调用HandleWorkInjuryInit异常: {initEx.Message}";
+                            result["device"] = "江苏工伤联网接口";
+                            result["debug_step"] = "HandleWorkInjuryInit调用异常";
+                            result["debug_error"] = initEx.Message;
+                        }
                         break;
 
                     case "transaction":
+                        result["debug_step"] = "执行交易操作";
                         result = HandleWorkInjuryTransaction(request);
+                        if (result != null)
+                        {
+                            result["debug_controller_step"] = "交易操作完成";
+                        }
                         break;
 
                     case "health":
+                        result["debug_step"] = "执行健康检查";
                         result = JiangSuWorkInjuryBusiness.HealthCheck();
+                        if (result != null)
+                        {
+                            result["debug_controller_step"] = "健康检查完成";
+                        }
                         break;
 
                     case "stats":
@@ -609,15 +680,84 @@ namespace ThCardReader
                         break;
                 }
             }
+            catch (System.AccessViolationException avEx)
+            {
+                result = new JObject(); // 重新创建以确保不为空
+                result["success"] = false;
+                result["code"] = 9001;
+                result["message"] = "DLL访问冲突异常 - 可能是JSSiInterface.dll问题";
+                result["device"] = "江苏工伤联网接口";
+                result["exception"] = "AccessViolationException";
+                result["debug_step"] = "Controller捕获访问冲突异常";
+                result["debug_error"] = avEx.Message;
+                result["debug_stacktrace"] = avEx.StackTrace;
+            }
+            catch (System.Runtime.InteropServices.SEHException sehEx)
+            {
+                result = new JObject(); // 重新创建以确保不为空
+                result["success"] = false;
+                result["code"] = 9002;
+                result["message"] = "结构化异常处理错误 - DLL调用失败";
+                result["device"] = "江苏工伤联网接口";
+                result["exception"] = "SEHException";
+                result["debug_step"] = "Controller捕获SEH异常";
+                result["debug_error"] = sehEx.Message;
+                result["debug_stacktrace"] = sehEx.StackTrace;
+            }
             catch (System.Exception ex)
             {
-                result.Add("success", false);
-                result.Add("code", 1000);
-                result.Add("message", $"工伤联网接口处理异常: {ex.Message}");
-                result.Add("device", "江苏工伤联网接口");
-                result.Add("exception", ex.GetType().Name);
+                result = new JObject(); // 重新创建以确保不为空
+                result["success"] = false;
+                result["code"] = 1000;
+                result["message"] = $"工伤联网接口处理异常: {ex.Message}";
+                result["device"] = "江苏工伤联网接口";
+                result["exception"] = ex.GetType().Name;
+                result["debug_step"] = "Controller捕获一般异常";
+                result["debug_error"] = ex.Message;
+                result["debug_stacktrace"] = ex.StackTrace;
+                result["debug_exception_details"] = ex.ToString();
+            }
+
+            // 确保返回的result不为null并且有基本结构
+            if (result == null)
+            {
+                result = new JObject();
+                result["success"] = false;
+                result["code"] = 9999;
+                result["message"] = "未知错误 - result为null";
+                result["device"] = "江苏工伤联网接口";
+                result["debug_step"] = "result为null保护";
+            }
+
+            // 强制确保必要字段存在
+            if (result["success"] == null)
+            {
+                result["success"] = false;
+                result["debug_forced_success"] = "强制添加success字段";
+            }
+            
+            if (result["code"] == null)
+            {
+                result["code"] = 8000;
+                result["debug_forced_code"] = "强制添加code字段";
+            }
+            
+            if (result["device"] == null)
+            {
+                result["device"] = "江苏工伤联网接口";
+                result["debug_forced_device"] = "强制添加device字段";
+            }
+
+            // 确保有时间戳
+            if (result["debug_timestamp"] == null)
+            {
+                result["debug_final_timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
             }
 
+            // 添加最终保护标记
+            result["debug_method_exit"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
+            result["debug_return_confirmed"] = true;
+
             return result;
         }
 
@@ -626,11 +766,20 @@ namespace ThCardReader
         /// </summary>
         private JObject HandleWorkInjuryInit(JObject request)
         {
+            // 立即创建基础响应,确保总是有返回值
+            JObject result = new JObject();
+            result["debug_handler_entry"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
+            result["debug_handler_stage"] = "HandleWorkInjuryInit进入";
+
             try
             {
+                result["debug_handler_stage"] = "解析配置参数";
                 var configObj = request["config"];
+                
+                JObject initResult = null;
                 if (configObj != null)
                 {
+                    result["debug_handler_stage"] = "使用自定义配置";
                     // 使用自定义配置
                     var config = new JiangSuWorkInjuryBusiness.WorkInjuryConfig
                     {
@@ -643,21 +792,55 @@ namespace ThCardReader
                         DefaultOperatorName = configObj["defaultOperatorName"]?.ToString() ?? "系统管理员",
                         LogPath = configObj["logPath"]?.ToString() ?? "logs/workinjury/"
                     };
-                    return JiangSuWorkInjuryBusiness.Initialize(config);
+                    result["debug_handler_stage"] = "准备调用Initialize(config)";
+                    initResult = JiangSuWorkInjuryBusiness.Initialize(config);
                 }
                 else
                 {
-                    // 使用默认配置
-                    return JiangSuWorkInjuryBusiness.Initialize();
+                    result["debug_handler_stage"] = "使用默认配置";
+                    initResult = JiangSuWorkInjuryBusiness.Initialize();
                 }
+                
+                result["debug_handler_stage"] = "Initialize调用完成";
+                
+                // 确保返回的结果不为空
+                if (initResult == null)
+                {
+                    result["success"] = false;
+                    result["code"] = 1005;
+                    result["message"] = "初始化返回结果为null";
+                    result["device"] = "江苏工伤联网接口";
+                    result["debug_handler_stage"] = "初始化结果为null";
+                    return result;
+                }
+                
+                // 将调试信息合并到初始化结果中
+                initResult["debug_handler_complete"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
+                initResult["debug_handler_stage"] = "成功返回";
+                
+                return initResult;
+            }
+            catch (System.AccessViolationException avEx)
+            {
+                result["success"] = false;
+                result["code"] = 1006;
+                result["message"] = $"工伤联网初始化访问冲突异常: {avEx.Message}";
+                result["device"] = "江苏工伤联网接口";
+                result["exception"] = "AccessViolationException";
+                result["debug_handler_stage"] = "HandleWorkInjuryInit捕获访问冲突";
+                result["debug_error"] = avEx.Message;
+                return result;
             }
             catch (System.Exception ex)
             {
-                var result = new JObject();
-                result.Add("success", false);
-                result.Add("code", 1004);
-                result.Add("message", $"工伤联网初始化处理异常: {ex.Message}");
-                result.Add("device", "江苏工伤联网接口");
+                result["success"] = false;
+                result["code"] = 1004;
+                result["message"] = $"工伤联网初始化处理异常: {ex.Message}";
+                result["device"] = "江苏工伤联网接口";
+                result["exception"] = ex.GetType().Name;
+                result["debug_handler_stage"] = "HandleWorkInjuryInit捕获一般异常";
+                result["debug_error"] = ex.Message;
+                result["debug_stacktrace"] = ex.StackTrace;
                 return result;
             }
         }

+ 210 - 17
ThCardReader/JiangSuWorkInjuryBusiness.cs

@@ -24,7 +24,7 @@ namespace ThCardReader
         /// </summary>
         /// <param name="pErrMsg">错误信息</param>
         /// <returns>成功:0,失败:-1</returns>
-        [DllImport("JSSiInterface.dll", EntryPoint = "Si_INIT", CharSet = CharSet.Ansi)]
+        [DllImport("JSSiInterface.dll", EntryPoint = "Si_INIT", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
         private extern static int Si_INIT(StringBuilder pErrMsg);
         
         /// <summary>
@@ -33,7 +33,7 @@ namespace ThCardReader
         /// <param name="inputdata">输入参数JSON字符串</param>
         /// <param name="outputdata">输出参数JSON字符串</param>
         /// <returns>成功:0,失败:<0</returns>
-        [DllImport("JSSiInterface.dll", EntryPoint = "Si_Busi", CharSet = CharSet.Ansi)]
+        [DllImport("JSSiInterface.dll", EntryPoint = "Si_Busi", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
         private extern static int Si_Busi(string inputdata, StringBuilder outputdata);
         
         #endregion
@@ -235,34 +235,129 @@ namespace ThCardReader
         /// </summary>
         /// <param name="config">配置参数</param>
         /// <returns>初始化结果</returns>
+        [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
+        [System.Security.SecurityCritical]
         public static JObject Initialize(WorkInjuryConfig config = null)
         {
             var result = new JObject();
             
             try
             {
+                // 添加调试信息
+                result["debug_init_step"] = "开始初始化";
+                
                 // 使用默认配置或传入配置
                 if (config == null)
                 {
                     config = new WorkInjuryConfig();
                 }
+                result["debug_init_step"] = "配置准备完成";
                 
                 // 检查DLL文件存在性
                 var dllCheckResult = CheckDllExists();
+                result["debug_dll_check"] = dllCheckResult;
                 if (!(bool)dllCheckResult["success"])
                 {
                     return dllCheckResult;
                 }
+                result["debug_init_step"] = "DLL检查通过";
                 
                 // 确保日志目录存在
                 if (!Directory.Exists(config.LogPath))
                 {
                     Directory.CreateDirectory(config.LogPath);
                 }
+                result["debug_init_step"] = "日志目录准备完成";
                 
-                // 调用底层初始化函数
-                StringBuilder errMsg = new StringBuilder(1024);
-                int initResult = Si_INIT(errMsg);
+                // 调用底层初始化函数 - 增加缓冲区大小并添加调试信息
+                StringBuilder errMsg = new StringBuilder(4096); // 增加缓冲区大小
+                result["debug_init_step"] = "准备调用Si_INIT";
+                
+                // 添加DLL调用前的最后检查
+                try
+                {
+                    // 测试DLL是否可以加载(不调用函数)
+                    result["debug_init_step"] = "检查DLL加载状态";
+                    var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JSSiInterface.dll");
+                    if (!File.Exists(dllPath))
+                    {
+                        result["success"] = false;
+                        result["code"] = 2004;
+                        result["message"] = $"DLL文件不存在: {dllPath}";
+                        result["device"] = "江苏工伤联网接口";
+                        result["debug_init_step"] = "DLL文件不存在";
+                        return result;
+                    }
+                    
+                    result["debug_dll_path"] = dllPath;
+                    result["debug_dll_size"] = new FileInfo(dllPath).Length;
+                    result["debug_init_step"] = "DLL文件检查通过,准备调用Si_INIT";
+                }
+                catch (Exception dllCheckEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2005;
+                    result["message"] = $"DLL文件检查异常: {dllCheckEx.Message}";
+                    result["device"] = "江苏工伤联网接口";
+                    result["debug_init_step"] = "DLL文件检查异常";
+                    result["debug_error"] = dllCheckEx.Message;
+                    return result;
+                }
+                
+                int initResult;
+                try
+                {
+                    // 在调用前添加更多保护
+                    result["debug_init_step"] = "即将调用Si_INIT - 这里可能发生异常";
+                    
+                    // 设置一个标记,如果DLL调用导致进程崩溃,至少我们知道问题在这里
+                    var beforeCallTime = DateTime.Now;
+                    result["debug_si_init_call_time"] = beforeCallTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
+                    
+                    initResult = Si_INIT(errMsg);
+                    
+                    var afterCallTime = DateTime.Now;
+                    var callDuration = (afterCallTime - beforeCallTime).TotalMilliseconds;
+                    
+                    result["debug_init_step"] = "Si_INIT调用完成";
+                    result["debug_dll_result"] = initResult;
+                    result["debug_dll_errmsg"] = errMsg.ToString();
+                    result["debug_si_init_duration"] = $"{callDuration}ms";
+                    result["debug_si_init_return_time"] = afterCallTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
+                }
+                catch (System.AccessViolationException avEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2001;
+                    result["message"] = "DLL访问冲突异常 - 可能是DLL版本不匹配或依赖缺失";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "AccessViolationException";
+                    result["debug_init_step"] = "Si_INIT调用发生访问冲突";
+                    result["debug_error"] = avEx.Message;
+                    return result;
+                }
+                catch (System.DllNotFoundException dllEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2002;
+                    result["message"] = "找不到JSSiInterface.dll或其依赖库";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "DllNotFoundException";
+                    result["debug_init_step"] = "Si_INIT调用时DLL未找到";
+                    result["debug_error"] = dllEx.Message;
+                    return result;
+                }
+                catch (System.EntryPointNotFoundException epEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2003;
+                    result["message"] = "DLL中找不到Si_INIT函数入口点";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "EntryPointNotFoundException";
+                    result["debug_init_step"] = "Si_INIT函数入口点未找到";
+                    result["debug_error"] = epEx.Message;
+                    return result;
+                }
                 
                 if (initResult == 0)
                 {
@@ -276,6 +371,13 @@ namespace ThCardReader
                     result["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                     result["version"] = config.InterfaceVersion;
                     result["dllErrorMsg"] = errMsg.ToString();
+                    result["debug_init_step"] = "初始化成功";
+                    result["config"] = new JObject
+                    {
+                        ["fixmedinsCode"] = config.FixmedinsCode,
+                        ["fixmedinsName"] = config.FixmedinsName,
+                        ["interfaceVersion"] = config.InterfaceVersion
+                    };
                     
                     LogInfo($"系统初始化成功,版本: {config.InterfaceVersion}");
                 }
@@ -288,6 +390,7 @@ namespace ThCardReader
                     result["device"] = "江苏工伤联网接口";
                     result["errorCode"] = initResult;
                     result["dllErrorMsg"] = errorMsg;
+                    result["debug_init_step"] = "初始化失败";
                     
                     LogError($"系统初始化失败,错误码: {initResult}, 错误信息: {errorMsg}");
                 }
@@ -299,8 +402,10 @@ namespace ThCardReader
                 result["message"] = $"江苏工伤联网系统初始化异常: {ex.Message}";
                 result["device"] = "江苏工伤联网接口";
                 result["exception"] = ex.GetType().Name;
+                result["debug_init_step"] = "捕获到异常";
+                result["debug_exception_details"] = ex.ToString();
                 
-                LogError($"系统初始化异常: {ex.Message}");
+                LogError($"系统初始化异常: {ex}");
             }
             
             return result;
@@ -321,6 +426,8 @@ namespace ThCardReader
         /// <param name="operatorId">经办人编号(可选)</param>
         /// <param name="operatorName">经办人姓名(可选)</param>
         /// <returns>交易处理结果</returns>
+        [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
+        [System.Security.SecurityCritical]
         public static JObject ProcessWorkInjuryTransaction(
             string transactionName,
             object businessParams = null,
@@ -378,12 +485,58 @@ namespace ThCardReader
                 var inputData = BuildTransactionInput(transactionCode, businessParams, identifyMode, qrCodeInfo, operatorId, operatorName);
                 string inputJson = JsonConvert.SerializeObject(inputData, Formatting.None);
                 
-                // 5. 调用底层DLL交易函数
+                // 5. 调用底层DLL交易函数 - 增强异常处理
                 StringBuilder outputBuffer = new StringBuilder(40000);
-                int dllResult = Si_Busi(inputJson, outputBuffer);
+                result["debug_input_json"] = inputJson;
+                result["debug_transaction_step"] = "准备调用Si_Busi";
+                
+                int dllResult;
+                try
+                {
+                    dllResult = Si_Busi(inputJson, outputBuffer);
+                    result["debug_transaction_step"] = "Si_Busi调用完成";
+                    result["debug_dll_result"] = dllResult;
+                }
+                catch (System.AccessViolationException avEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2011;
+                    result["message"] = $"交易{transactionName} DLL访问冲突异常";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "AccessViolationException";
+                    result["debug_transaction_step"] = "Si_Busi调用发生访问冲突";
+                    result["debug_error"] = avEx.Message;
+                    result["transactionCode"] = transactionCode;
+                    return result;
+                }
+                catch (System.DllNotFoundException dllEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2012;
+                    result["message"] = $"交易{transactionName} 找不到JSSiInterface.dll";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "DllNotFoundException";
+                    result["debug_transaction_step"] = "Si_Busi调用时DLL未找到";
+                    result["debug_error"] = dllEx.Message;
+                    result["transactionCode"] = transactionCode;
+                    return result;
+                }
+                catch (System.EntryPointNotFoundException epEx)
+                {
+                    result["success"] = false;
+                    result["code"] = 2013;
+                    result["message"] = $"交易{transactionName} DLL中找不到Si_Busi函数入口点";
+                    result["device"] = "江苏工伤联网接口";
+                    result["exception"] = "EntryPointNotFoundException";
+                    result["debug_transaction_step"] = "Si_Busi函数入口点未找到";
+                    result["debug_error"] = epEx.Message;
+                    result["transactionCode"] = transactionCode;
+                    return result;
+                }
                 
                 // 6. 解析和处理返回结果
                 string outputJson = outputBuffer.ToString();
+                result["debug_output_json"] = outputJson;
                 result = ParseTransactionOutput(outputJson, dllResult, transactionCode);
                 
                 // 7. 特殊交易后处理
@@ -757,7 +910,7 @@ namespace ThCardReader
         }
         
         /// <summary>
-        /// 检查DLL文件是否存在
+        /// 确保DLL文件在正确位置(参考医保代码的成功实现)
         /// </summary>
         private static JObject CheckDllExists()
         {
@@ -766,35 +919,75 @@ namespace ThCardReader
             try
             {
                 string programDir = AppDomain.CurrentDomain.BaseDirectory;
-                string dllPath = Path.Combine(programDir, "JSSiInterface.dll");
+                string targetDllPath = Path.Combine(programDir, "JSSiInterface.dll");
                 
-                if (File.Exists(dllPath))
+                // 如果目标位置已经有DLL文件,直接返回成功
+                if (File.Exists(targetDllPath))
                 {
-                    FileInfo fileInfo = new FileInfo(dllPath);
-                    
+                    FileInfo fileInfo = new FileInfo(targetDllPath);
                     result["success"] = true;
                     result["code"] = 200;
                     result["message"] = "JSSiInterface.dll文件检查通过";
                     result["device"] = "江苏工伤联网接口";
                     result["data"] = new JObject
                     {
-                        ["dllPath"] = dllPath,
+                        ["dllPath"] = targetDllPath,
                         ["fileSize"] = fileInfo.Length,
                         ["lastModified"] = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"),
                         ["programDirectory"] = programDir
                     };
+                    return result;
+                }
+                
+                // 如果目标位置没有DLL,尝试从其他位置查找并复制(参考医保代码)
+                string[] possiblePaths = {
+                    Path.Combine(programDir, "bin", "x86", "Release", "JSSiInterface.dll"),
+                    Path.Combine(programDir, "bin", "Debug", "JSSiInterface.dll"),
+                    Path.Combine(programDir, "bin", "Release", "JSSiInterface.dll"),
+                    Path.Combine(programDir, "ThCardReader", "bin", "x86", "Release", "JSSiInterface.dll"),
+                    Path.Combine(programDir, "ThCardReader", "bin", "Debug", "JSSiInterface.dll"),
+                    Path.Combine(programDir, "..", "ThCardReader", "bin", "x86", "Release", "JSSiInterface.dll")
+                };
+                
+                string sourcePath = null;
+                foreach (string path in possiblePaths)
+                {
+                    if (File.Exists(path))
+                    {
+                        sourcePath = path;
+                        break;
+                    }
+                }
+                
+                if (sourcePath != null)
+                {
+                    // 复制DLL文件到程序目录
+                    File.Copy(sourcePath, targetDllPath, true);
+                    
+                    FileInfo fileInfo = new FileInfo(targetDllPath);
+                    result["success"] = true;
+                    result["code"] = 200;
+                    result["message"] = "JSSiInterface.dll文件已复制到位";
+                    result["device"] = "江苏工伤联网接口";
+                    result["data"] = new JObject
+                    {
+                        ["sourcePath"] = sourcePath,
+                        ["targetPath"] = targetDllPath,
+                        ["fileSize"] = fileInfo.Length,
+                        ["lastModified"] = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")
+                    };
                 }
                 else
                 {
                     result["success"] = false;
                     result["code"] = 8001;
-                    result["message"] = "JSSiInterface.dll文件不存在";
+                    result["message"] = "找不到JSSiInterface.dll文件";
                     result["device"] = "江苏工伤联网接口";
                     result["data"] = new JObject
                     {
-                        ["expectedPath"] = dllPath,
+                        ["searchedPaths"] = string.Join("; ", possiblePaths),
                         ["programDirectory"] = programDir,
-                        ["suggestion"] = "请将JSSiInterface.dll文件复制到程序目录"
+                        ["suggestion"] = "请确保JSSiInterface.dll文件在程序目录或bin/x86/Release目录中"
                     };
                 }
             }

+ 205 - 0
dll_test.html

@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title>DLL问题诊断工具</title>
+    <style>
+        body { font-family: Arial, sans-serif; margin: 20px; }
+        .test-btn { padding: 10px 20px; margin: 10px; font-size: 16px; background: #dc3545; color: white; border: none; border-radius: 5px; }
+        .test-btn:hover { background: #c82333; }
+        .result { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
+        .success { background: #d4edda; border-color: #c3e6cb; }
+        .error { background: #f8d7da; border-color: #f5c6cb; }
+        .warning { background: #fff3cd; border-color: #ffeaa7; }
+        pre { white-space: pre-wrap; word-break: break-all; font-size: 12px; }
+    </style>
+</head>
+<body>
+    <h1>🔧 DLL问题专项诊断</h1>
+    <p>基于前面的测试,我们已经确认问题出现在DLL调用阶段。</p>
+    
+    <div class="result warning">
+        <h3>📋 已确认的信息</h3>
+        <ul>
+            <li>✅ HTTP通信正常</li>
+            <li>✅ C#基础代码正常</li>
+            <li>✅ JSON序列化正常</li>
+            <li>❌ DLL调用导致连接中断</li>
+        </ul>
+    </div>
+    
+    <h2>🚨 危险测试(可能导致进程崩溃)</h2>
+    <button class="test-btn" onclick="testDllCall()">测试DLL调用(带增强保护)</button>
+    <button class="test-btn" onclick="clearResults()">清空结果</button>
+    
+    <div id="results"></div>
+
+    <script>
+        const API_URL = 'http://localhost:8321/api/entry/workinjury';
+        
+        function clearResults() {
+            document.getElementById('results').innerHTML = '';
+        }
+        
+        function showResult(title, status, data, time) {
+            const resultsDiv = document.getElementById('results');
+            const resultDiv = document.createElement('div');
+            resultDiv.className = `result ${status === 200 ? 'success' : 'error'}`;
+            
+            resultDiv.innerHTML = `
+                <h3>${title}</h3>
+                <p><strong>HTTP状态:</strong> ${status}</p>
+                <p><strong>时间:</strong> ${time}</p>
+                <p><strong>响应数据:</strong></p>
+                <pre>${JSON.stringify(data, null, 2)}</pre>
+            `;
+            
+            resultsDiv.appendChild(resultDiv);
+        }
+        
+        async function makeRequest(title, requestData) {
+            const startTime = new Date();
+            
+            try {
+                console.log(`发送请求: ${title}`, requestData);
+                
+                // 设置较短的超时时间,避免长时间等待
+                const controller = new AbortController();
+                const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
+                
+                const response = await fetch(API_URL, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                    body: JSON.stringify(requestData),
+                    signal: controller.signal
+                });
+                
+                clearTimeout(timeoutId);
+                const endTime = new Date();
+                const duration = endTime - startTime;
+                
+                console.log(`收到响应: ${response.status}`, response);
+                
+                let responseData = null;
+                const contentType = response.headers.get('content-type');
+                
+                if (contentType && contentType.includes('application/json')) {
+                    try {
+                        responseData = await response.json();
+                        console.log('解析JSON成功:', responseData);
+                    } catch (jsonError) {
+                        responseData = {
+                            error: 'JSON解析失败',
+                            details: jsonError.message,
+                            contentType: contentType
+                        };
+                        console.error('JSON解析失败:', jsonError);
+                    }
+                } else {
+                    const text = await response.text();
+                    responseData = {
+                        error: '非JSON响应',
+                        contentType: contentType,
+                        text: text
+                    };
+                    console.log('非JSON响应:', text);
+                }
+                
+                showResult(title, response.status, responseData, `${duration}ms`);
+                
+                // 分析DLL相关的错误信息
+                if (responseData && responseData.debug_init_step) {
+                    showResult('🔍 DLL调用分析', 'INFO', {
+                        最后执行步骤: responseData.debug_init_step,
+                        DLL路径: responseData.debug_dll_path,
+                        DLL大小: responseData.debug_dll_size,
+                        调用时间: responseData.debug_si_init_call_time,
+                        完成时间: responseData.debug_si_init_return_time,
+                        调用耗时: responseData.debug_si_init_duration,
+                        分析: getDllAnalysis(responseData)
+                    }, '');
+                }
+                
+            } catch (networkError) {
+                const endTime = new Date();
+                const duration = endTime - startTime;
+                
+                console.error('网络错误:', networkError);
+                
+                let errorType = '未知错误';
+                let suggestion = '';
+                
+                if (networkError.name === 'AbortError') {
+                    errorType = '请求超时(10秒)';
+                    suggestion = 'DLL调用可能导致进程阻塞或崩溃';
+                } else if (networkError.message.includes('fetch')) {
+                    errorType = '连接中断';
+                    suggestion = 'DLL调用可能导致ThCardReader.exe进程崩溃';
+                }
+                
+                showResult(`❌ ${title} - ${errorType}`, 'ERROR', {
+                    error: networkError.message,
+                    type: networkError.name,
+                    duration: `${duration}ms`,
+                    suggestion: suggestion,
+                    '可能原因': [
+                        'JSSiInterface.dll版本不兼容',
+                        'DLL依赖库缺失',
+                        'DLL内存访问冲突',
+                        'DLL需要特定的运行环境'
+                    ]
+                }, `${duration}ms`);
+            }
+        }
+        
+        function getDllAnalysis(responseData) {
+            if (responseData.debug_init_step === 'Si_INIT调用完成') {
+                return 'DLL调用成功完成';
+            } else if (responseData.debug_init_step === '即将调用Si_INIT - 这里可能发生异常') {
+                return 'DLL调用时发生异常,进程可能崩溃';
+            } else if (responseData.debug_init_step.includes('DLL文件')) {
+                return 'DLL文件相关问题';
+            } else {
+                return '未知状态';
+            }
+        }
+        
+        function testDllCall() {
+            showResult('⚠️ 警告', 'WARNING', {
+                说明: '即将测试DLL调用,这可能导致ThCardReader.exe进程崩溃',
+                建议: '如果进程崩溃,请重启ThCardReader.exe后继续测试',
+                '预期行为': '如果看到请求超时或连接中断,说明DLL调用有问题'
+            }, '');
+            
+            setTimeout(() => {
+                makeRequest('DLL调用测试(增强保护)', {
+                    action: 'init',
+                    config: {
+                        fixmedinsCode: 'SQ201348',
+                        fixmedinsName: '沭阳铭和医院',
+                        interfaceVersion: 'V2.1'
+                    }
+                });
+            }, 2000); // 2秒后执行,给用户时间看到警告
+        }
+        
+        // 页面加载完成后的说明
+        document.addEventListener('DOMContentLoaded', function() {
+            showResult('📋 DLL问题诊断说明', 'INFO', {
+                '问题确认': '前面的测试已经确认问题出现在DLL调用阶段',
+                '当前状态': 'HTTP通信正常,C#基础代码正常',
+                '问题位置': 'JiangSuWorkInjuryBusiness.Initialize() 中的 Si_INIT() 调用',
+                '预期结果': '点击测试按钮后,如果出现超时或连接中断,确认是DLL问题',
+                '解决方向': [
+                    '检查JSSiInterface.dll是否完整',
+                    '检查DLL依赖项(如VC++运行库)',
+                    '尝试在其他环境测试DLL',
+                    '联系DLL提供方获取支持'
+                ]
+            }, '');
+        });
+    </script>
+</body>
+</html> 

+ 148 - 0
simple_test.html

@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title>工伤接口简单测试</title>
+    <style>
+        body { font-family: Arial, sans-serif; margin: 20px; }
+        button { padding: 10px 20px; margin: 10px; font-size: 16px; }
+        .test-btn { background: #007bff; color: white; border: none; border-radius: 5px; }
+        .test-btn:hover { background: #0056b3; }
+        .result { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
+        .success { background: #d4edda; border-color: #c3e6cb; }
+        .error { background: #f8d7da; border-color: #f5c6cb; }
+        pre { white-space: pre-wrap; word-break: break-all; }
+    </style>
+</head>
+<body>
+    <h1>🔧 工伤接口Status 200无响应体问题测试</h1>
+    
+    <h2>测试步骤</h2>
+    <button class="test-btn" onclick="testMode()">1️⃣ 测试模式(跳过DLL调用)</button>
+    <button class="test-btn" onclick="normalMode()">2️⃣ 正常模式(调用DLL)</button>
+    <button class="test-btn" onclick="clearResults()">🗑️ 清空结果</button>
+    
+    <div id="results"></div>
+
+    <script>
+        const API_URL = 'http://localhost:8321/api/entry/workinjury';
+        
+        function clearResults() {
+            document.getElementById('results').innerHTML = '';
+        }
+        
+        function showResult(title, status, data, time) {
+            const resultsDiv = document.getElementById('results');
+            const resultDiv = document.createElement('div');
+            resultDiv.className = `result ${status === 200 ? 'success' : 'error'}`;
+            
+            resultDiv.innerHTML = `
+                <h3>${title}</h3>
+                <p><strong>HTTP状态:</strong> ${status}</p>
+                <p><strong>时间:</strong> ${time}</p>
+                <p><strong>响应数据:</strong></p>
+                <pre>${JSON.stringify(data, null, 2)}</pre>
+            `;
+            
+            resultsDiv.appendChild(resultDiv);
+        }
+        
+        async function makeRequest(title, requestData) {
+            const startTime = new Date();
+            
+            try {
+                console.log(`发送请求: ${title}`, requestData);
+                
+                const response = await fetch(API_URL, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                    body: JSON.stringify(requestData)
+                });
+                
+                const endTime = new Date();
+                const duration = endTime - startTime;
+                
+                console.log(`收到响应: ${response.status}`, response);
+                
+                let responseData = null;
+                const contentType = response.headers.get('content-type');
+                
+                if (contentType && contentType.includes('application/json')) {
+                    try {
+                        responseData = await response.json();
+                        console.log('解析JSON成功:', responseData);
+                    } catch (jsonError) {
+                        responseData = {
+                            error: 'JSON解析失败',
+                            details: jsonError.message,
+                            contentType: contentType
+                        };
+                        console.error('JSON解析失败:', jsonError);
+                    }
+                } else {
+                    const text = await response.text();
+                    responseData = {
+                        error: '非JSON响应',
+                        contentType: contentType,
+                        text: text
+                    };
+                    console.log('非JSON响应:', text);
+                }
+                
+                showResult(title, response.status, responseData, `${duration}ms`);
+                
+                // 特殊处理Status 200但无响应体的情况
+                if (response.status === 200 && (!responseData || Object.keys(responseData).length === 0)) {
+                    showResult(`❌ ${title} - 发现Status 200无响应体问题!`, 'ERROR', {
+                        problem: 'HTTP 200 成功但响应体为空或无效',
+                        suggestion: '这通常表示C#代码执行过程中发生未捕获异常'
+                    }, '');
+                }
+                
+            } catch (networkError) {
+                console.error('网络错误:', networkError);
+                showResult(`❌ ${title} - 网络错误`, 'ERROR', {
+                    error: networkError.message,
+                    type: 'NetworkError'
+                }, '');
+            }
+        }
+        
+        function testMode() {
+            makeRequest('测试模式(跳过DLL)', {
+                action: 'init',
+                test_mode: 'immediate_return',
+                config: {
+                    fixmedinsCode: 'SQ201348',
+                    fixmedinsName: '沭阳铭和医院',
+                    interfaceVersion: 'V2.1'
+                }
+            });
+        }
+        
+        function normalMode() {
+            makeRequest('正常模式(调用DLL)', {
+                action: 'init',
+                config: {
+                    fixmedinsCode: 'SQ201348',
+                    fixmedinsName: '沭阳铭和医院',
+                    interfaceVersion: 'V2.1'
+                }
+            });
+        }
+        
+        // 页面加载完成后的提示
+        document.addEventListener('DOMContentLoaded', function() {
+            showResult('📋 测试说明', 'INFO', {
+                '步骤1': '先点击"测试模式"按钮,验证基础HTTP通信是否正常',
+                '步骤2': '如果测试模式正常,再点击"正常模式"测试DLL调用',
+                '预期结果': '测试模式应该立即返回成功,正常模式可能会有DLL相关错误',
+                '问题定位': '如果测试模式也返回Status 200无响应体,说明问题在HTTP层面',
+                '注意': '确保ThCardReader.exe正在运行并监听8321端口'
+            }, '');
+        });
+    </script>
+</body>
+</html> 

+ 14 - 5
test_workinjury_interface.html

@@ -145,7 +145,7 @@
             <button class="btn" onclick="loadStatsParams()" title="获取系统统计信息">统计信息</button>
             
                                   <!-- 执行按钮 -->
-             <button class="btn" onclick="callWorkInjuryAPI()" title="调用工伤联网接口" style="background: #28A745; font-weight: bold;">🚀 调用接口</button>
+             <button class="btn" onclick="callWorkInjuryAPI()" title="调用工伤联网接口" style="background: #28A745; font-weight: bold;">🚀 调用接口1</button>
              
              <!-- 工具按钮 -->
              <button class="btn clear" onclick="clearAll()" title="清空入参和出参">清屏</button>
@@ -234,14 +234,18 @@
             signin: {
                 action: "transaction",
                 transactionName: "SignIn",
+                identifyMode: "1",
                 operatorId: "001",
-                operatorName: "收费员张三"
+                operatorName: "收费员张三",
+                businessParams: {}
             },
             signout: {
                 action: "transaction",
                 transactionName: "SignOut",
+                identifyMode: "1",
                 operatorId: "001",
-                operatorName: "收费员张三"
+                operatorName: "收费员张三",
+                businessParams: {}
             },
             business: {
                 action: "transaction",
@@ -425,8 +429,10 @@
         
         // 调用接口(当前只是模拟,需要连接实际接口)
         async function callWorkInjuryAPI() {
+            console.log("11111111111111111111111111111111")
             try {
                 const inputText = inputArea.value.trim();
+                console.log("inputText111111111111111111111111",inputText)
                 if (!inputText) {
                     updateStatus('请先输入参数', true);
                     return;
@@ -442,7 +448,7 @@
                     },
                     body: JSON.stringify(params)
                 });
-                
+                console.log("response111111111111111",response)
                 const result = await response.json();
                 outputArea.value = JSON.stringify(result, null, 2);
                 
@@ -453,6 +459,7 @@
                 }
                 
             } catch (error) {
+                console.log("22222222222222222222222")
                 outputArea.value = JSON.stringify({
                     success: false,
                     error: error.message,
@@ -503,8 +510,10 @@
 {
   "action": "transaction",
   "transactionName": "SignIn",
+  "identifyMode": "1",                  // 识别方式(保持一致性)
   "operatorId": "001",                  // 当前操作员编号
-  "operatorName": "收费员张三"           // 当前操作员姓名
+  "operatorName": "收费员张三",           // 当前操作员姓名
+  "businessParams": {}                  // 空的业务参数对象(必需)
 }
 
 🏥 3. 工伤患者读卡

+ 250 - 0
workinjury_test_debug.html

@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>工伤接口调试工具</title>
+    <style>
+        body { font-family: 'Microsoft YaHei', sans-serif; margin: 20px; background: #f5f5f5; }
+        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
+        .debug-section { margin: 15px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
+        .debug-section h3 { margin-top: 0; color: #333; }
+        button { padding: 10px 20px; margin: 5px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; }
+        .btn-test { background: #007bff; color: white; }
+        .btn-test:hover { background: #0056b3; }
+        textarea { width: 100%; height: 200px; font-family: 'Consolas', monospace; font-size: 12px; border: 1px solid #ddd; border-radius: 4px; padding: 10px; }
+        .status-success { background-color: #d4edda; border-color: #c3e6cb; color: #155724; }
+        .status-error { background-color: #f8d7da; border-color: #f5c6cb; color: #721c24; }
+        .status-warning { background-color: #fff3cd; border-color: #ffeaa7; color: #856404; }
+        .info-box { padding: 10px; margin: 10px 0; border-radius: 4px; border: 1px solid; }
+        .timestamp { font-size: 12px; color: #666; float: right; }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h1>🔧 江苏工伤联网接口调试工具</h1>
+        <p>专门用于诊断Status 200但无响应体的问题</p>
+
+        <div class="debug-section">
+            <h3>🚀 快速测试</h3>
+            <button class="btn-test" onclick="testInit()">测试初始化</button>
+            <button class="btn-test" onclick="testHealth()">测试健康检查</button>
+            <button class="btn-test" onclick="testSignIn()">测试签到</button>
+            <button class="btn-test" onclick="testSignOut()">测试签退</button>
+            <button class="btn-test" onclick="clearLogs()">清空日志</button>
+        </div>
+
+        <div class="debug-section">
+            <h3>📡 请求信息</h3>
+            <div>
+                <strong>请求URL:</strong> <span id="requestUrl">等待请求...</span>
+                <span class="timestamp" id="requestTime"></span>
+            </div>
+            <div><strong>请求方法:</strong> POST</div>
+            <div><strong>Content-Type:</strong> application/json</div>
+            <div><strong>请求体:</strong></div>
+            <textarea id="requestBody" readonly></textarea>
+        </div>
+
+        <div class="debug-section">
+            <h3>📊 响应信息</h3>
+            <div class="info-box" id="statusBox">
+                <strong>状态:</strong> <span id="httpStatus">等待响应...</span>
+                <span class="timestamp" id="responseTime"></span>
+            </div>
+            <div><strong>响应头:</strong></div>
+            <textarea id="responseHeaders" readonly></textarea>
+            <div><strong>响应体:</strong></div>
+            <textarea id="responseBody" readonly></textarea>
+        </div>
+
+        <div class="debug-section">
+            <h3>🔍 执行路径追踪</h3>
+            <div id="executionPath"></div>
+        </div>
+
+        <div class="debug-section">
+            <h3>📝 调试日志</h3>
+            <div id="debugLogs"></div>
+        </div>
+    </div>
+
+    <script>
+        const BASE_URL = 'http://localhost:8321/api/entry/workinjury';
+
+        function logMessage(message, type = 'info') {
+            const logs = document.getElementById('debugLogs');
+            const timestamp = new Date().toLocaleString();
+            const logEntry = document.createElement('div');
+            logEntry.className = `info-box status-${type === 'error' ? 'error' : type === 'warning' ? 'warning' : 'success'}`;
+            logEntry.innerHTML = `<strong>[${timestamp}]</strong> ${message}`;
+            logs.appendChild(logEntry);
+            logs.scrollTop = logs.scrollHeight;
+        }
+
+        function clearLogs() {
+            document.getElementById('debugLogs').innerHTML = '';
+            document.getElementById('requestBody').value = '';
+            document.getElementById('responseBody').value = '';
+            document.getElementById('responseHeaders').value = '';
+            document.getElementById('httpStatus').textContent = '等待响应...';
+            document.getElementById('executionPath').innerHTML = '';
+        }
+
+        function updateRequestInfo(url, body) {
+            document.getElementById('requestUrl').textContent = url;
+            document.getElementById('requestTime').textContent = new Date().toLocaleString();
+            document.getElementById('requestBody').value = JSON.stringify(body, null, 2);
+        }
+
+        function updateResponseInfo(status, headers, body, responseTime) {
+            const statusBox = document.getElementById('statusBox');
+            const statusSpan = document.getElementById('httpStatus');
+            
+            statusSpan.textContent = `${status}`;
+            document.getElementById('responseTime').textContent = new Date(responseTime).toLocaleString();
+            
+            // 设置状态颜色
+            statusBox.className = 'info-box ' + (status === 200 ? 'status-success' : 'status-error');
+            
+            // 显示响应头
+            let headersText = '';
+            if (headers) {
+                for (let [key, value] of headers.entries()) {
+                    headersText += `${key}: ${value}\n`;
+                }
+            }
+            document.getElementById('responseHeaders').value = headersText;
+            
+            // 显示响应体
+            if (body) {
+                document.getElementById('responseBody').value = JSON.stringify(body, null, 2);
+                
+                // 追踪执行路径
+                updateExecutionPath(body);
+            } else {
+                document.getElementById('responseBody').value = '(无响应体或响应体为空)';
+                logMessage('⚠️ 关键问题:Status 200但响应体为空!', 'error');
+            }
+        }
+
+        function updateExecutionPath(responseBody) {
+            const pathDiv = document.getElementById('executionPath');
+            pathDiv.innerHTML = '';
+            
+            if (responseBody && typeof responseBody === 'object') {
+                const steps = [];
+                
+                // 收集所有debug_step信息
+                for (let key in responseBody) {
+                    if (key.startsWith('debug_')) {
+                        steps.push(`<strong>${key}:</strong> ${responseBody[key]}`);
+                    }
+                }
+                
+                if (steps.length > 0) {
+                    pathDiv.innerHTML = '<div class="info-box status-success">' + steps.join('<br>') + '</div>';
+                } else {
+                    pathDiv.innerHTML = '<div class="info-box status-warning">响应中无调试信息</div>';
+                }
+            } else {
+                pathDiv.innerHTML = '<div class="info-box status-error">无法解析响应体</div>';
+            }
+        }
+
+        async function makeRequest(action, additionalParams = {}) {
+            const requestTime = Date.now();
+            const requestBody = {
+                action: action,
+                timestamp: new Date().toISOString(),
+                ...additionalParams
+            };
+
+            updateRequestInfo(BASE_URL, requestBody);
+            logMessage(`🚀 发送请求: ${action}`, 'info');
+
+            try {
+                const response = await fetch(BASE_URL, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                        'Accept': 'application/json'
+                    },
+                    body: JSON.stringify(requestBody)
+                });
+
+                const responseTime = Date.now();
+                logMessage(`📡 收到响应: ${response.status} ${response.statusText}`, response.ok ? 'success' : 'error');
+
+                let responseBody = null;
+                const contentType = response.headers.get('content-type');
+                
+                if (contentType && contentType.includes('application/json')) {
+                    try {
+                        responseBody = await response.json();
+                        logMessage('✅ 响应体解析成功', 'success');
+                    } catch (jsonError) {
+                        logMessage(`❌ JSON解析失败: ${jsonError.message}`, 'error');
+                        responseBody = { error: 'JSON解析失败', details: jsonError.message };
+                    }
+                } else {
+                    const text = await response.text();
+                    logMessage(`⚠️ 响应不是JSON格式,Content-Type: ${contentType}`, 'warning');
+                    responseBody = { error: '非JSON响应', contentType: contentType, text: text };
+                }
+
+                updateResponseInfo(response.status, response.headers, responseBody, responseTime);
+
+                // 特殊处理Status 200但无响应体的情况
+                if (response.status === 200 && (!responseBody || Object.keys(responseBody).length === 0)) {
+                    logMessage('🔥 发现关键问题:HTTP 200成功但响应体为空!', 'error');
+                    logMessage('这通常表示C#代码执行过程中发生了未捕获的异常或DLL访问冲突', 'error');
+                }
+
+            } catch (networkError) {
+                logMessage(`🚫 网络错误: ${networkError.message}`, 'error');
+                updateResponseInfo('Network Error', null, { error: networkError.message }, Date.now());
+            }
+        }
+
+        // 测试函数
+        function testInit() {
+            makeRequest('init', {
+                config: {
+                    fixmedinsCode: 'SQ201348',
+                    fixmedinsName: '沭阳铭和医院',
+                    interfaceVersion: 'V2.1'
+                }
+            });
+        }
+
+        function testHealth() {
+            makeRequest('health');
+        }
+
+        function testSignIn() {
+            makeRequest('transaction', {
+                transactionName: 'SignIn',
+                identifyMode: '1',
+                operatorId: '001',
+                operatorName: '系统管理员'
+            });
+        }
+
+        function testSignOut() {
+            makeRequest('transaction', {
+                transactionName: 'SignOut',
+                identifyMode: '1',
+                operatorId: '001',
+                operatorName: '系统管理员'
+            });
+        }
+
+        // 页面加载时的初始化
+        document.addEventListener('DOMContentLoaded', function() {
+            logMessage('🔧 调试工具已加载,可以开始测试', 'success');
+            logMessage('如果看到Status 200但无响应体,请检查ThCardReader.exe进程是否正常运行', 'warning');
+        });
+    </script>
+</body>
+</html> 

+ 1245 - 0
workinjury_test_interface.html

@@ -0,0 +1,1245 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>江苏工伤联网结算接口测试平台</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+        }
+        
+        body {
+            font-family: 'Microsoft YaHei', Arial, sans-serif;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            min-height: 100vh;
+            padding: 20px;
+        }
+        
+        .container {
+            max-width: 1200px;
+            margin: 0 auto;
+            background: white;
+            border-radius: 12px;
+            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
+            overflow: hidden;
+        }
+        
+        .header {
+            background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
+            color: white;
+            padding: 20px;
+            text-align: center;
+        }
+        
+        .header h1 {
+            font-size: 24px;
+            margin-bottom: 10px;
+        }
+        
+        .header p {
+            opacity: 0.9;
+            font-size: 14px;
+        }
+        
+        .main-content {
+            display: grid;
+            grid-template-columns: 300px 1fr;
+            min-height: 600px;
+        }
+        
+        .sidebar {
+            background: #f8f9fa;
+            border-right: 1px solid #dee2e6;
+            padding: 20px;
+        }
+        
+        .function-group {
+            margin-bottom: 20px;
+        }
+        
+        .function-group h3 {
+            font-size: 14px;
+            color: #666;
+            margin-bottom: 10px;
+            padding-bottom: 5px;
+            border-bottom: 1px solid #e0e0e0;
+        }
+        
+        .function-btn {
+            display: block;
+            width: 100%;
+            padding: 10px 15px;
+            margin: 5px 0;
+            background: white;
+            border: 1px solid #ddd;
+            border-radius: 6px;
+            color: #333;
+            text-decoration: none;
+            font-size: 13px;
+            cursor: pointer;
+            transition: all 0.2s;
+        }
+        
+        .function-btn:hover {
+            background: #f0f0f0;
+            border-color: #999;
+        }
+        
+        .function-btn.active {
+            background: #4CAF50;
+            color: white;
+            border-color: #4CAF50;
+        }
+        
+        .content-area {
+            padding: 20px;
+        }
+        
+        .action-bar {
+            display: flex;
+            gap: 10px;
+            margin-bottom: 20px;
+            align-items: center;
+        }
+        
+        .execute-btn {
+            background: #4CAF50;
+            color: white;
+            border: none;
+            padding: 10px 20px;
+            border-radius: 6px;
+            cursor: pointer;
+            font-weight: bold;
+            transition: background 0.2s;
+        }
+        
+        .execute-btn:hover {
+            background: #45a049;
+        }
+        
+        .execute-btn:disabled {
+            background: #ccc;
+            cursor: not-allowed;
+        }
+        
+        .clear-btn {
+            background: #f44336;
+            color: white;
+            border: none;
+            padding: 10px 15px;
+            border-radius: 6px;
+            cursor: pointer;
+        }
+        
+        .clear-btn:hover {
+            background: #da190b;
+        }
+        
+        .status-indicator {
+            display: flex;
+            align-items: center;
+            margin-left: auto;
+            font-size: 14px;
+        }
+        
+        .status-dot {
+            width: 10px;
+            height: 10px;
+            border-radius: 50%;
+            margin-right: 8px;
+        }
+        
+        .status-dot.success { background: #4CAF50; }
+        .status-dot.error { background: #f44336; }
+        .status-dot.warning { background: #ff9800; }
+        .status-dot.info { background: #2196f3; }
+        
+        .params-section {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+        
+        .params-panel {
+            background: #f8f9fa;
+            border: 1px solid #dee2e6;
+            border-radius: 8px;
+            overflow: hidden;
+        }
+        
+        .params-panel-header {
+            background: #e9ecef;
+            padding: 15px;
+            font-weight: bold;
+            color: #495057;
+            border-bottom: 1px solid #dee2e6;
+        }
+        
+        .params-panel-content {
+            padding: 15px;
+        }
+        
+        .params-textarea {
+            width: 100%;
+            height: 300px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            padding: 10px;
+            font-family: 'Courier New', monospace;
+            font-size: 12px;
+            resize: vertical;
+            background: white;
+        }
+        
+        .params-textarea:focus {
+            outline: none;
+            border-color: #4CAF50;
+        }
+        
+        .result-textarea {
+            background: #f5f5f5;
+            color: #333;
+        }
+        
+        .log-section {
+            background: #f8f9fa;
+            border: 1px solid #dee2e6;
+            border-radius: 8px;
+            overflow: hidden;
+        }
+        
+        .log-header {
+            background: #e9ecef;
+            padding: 15px;
+            font-weight: bold;
+            color: #495057;
+            border-bottom: 1px solid #dee2e6;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+        }
+        
+        .log-content {
+            padding: 15px;
+            max-height: 200px;
+            overflow-y: auto;
+            background: #1e1e1e;
+            color: #f8f8f2;
+            font-family: 'Courier New', monospace;
+            font-size: 12px;
+        }
+        
+        .log-entry {
+            margin: 2px 0;
+            padding: 2px 0;
+        }
+        
+        .log-entry.info { color: #a6e22e; }
+        .log-entry.error { color: #f92672; }
+        .log-entry.warning { color: #fd971f; }
+        .log-entry.success { color: #66d9ef; }
+        
+        .help-panel {
+            background: #e7f3ff;
+            border: 1px solid #b3d9ff;
+            border-radius: 6px;
+            padding: 15px;
+            margin-top: 20px;
+        }
+        
+        .help-panel h4 {
+            color: #0066cc;
+            margin-bottom: 10px;
+        }
+        
+        .help-panel ul {
+            margin-left: 20px;
+        }
+        
+        .help-panel li {
+            margin: 5px 0;
+            font-size: 13px;
+            color: #333;
+        }
+        
+        .config-modal {
+            display: none;
+            position: fixed;
+            top: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            background: rgba(0,0,0,0.5);
+            z-index: 1000;
+        }
+        
+        .modal-content {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            background: white;
+            border-radius: 8px;
+            padding: 20px;
+            width: 90%;
+            max-width: 500px;
+        }
+        
+        .modal-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 20px;
+            padding-bottom: 10px;
+            border-bottom: 1px solid #eee;
+        }
+        
+        .close-btn {
+            background: none;
+            border: none;
+            font-size: 20px;
+            cursor: pointer;
+            color: #999;
+        }
+        
+        .form-group {
+            margin-bottom: 15px;
+        }
+        
+        .form-group label {
+            display: block;
+            margin-bottom: 5px;
+            font-weight: bold;
+            color: #333;
+        }
+        
+        .form-group input {
+            width: 100%;
+            padding: 8px 12px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            font-size: 14px;
+        }
+        
+        .form-group input:focus {
+            outline: none;
+            border-color: #4CAF50;
+        }
+        
+        .modal-footer {
+            display: flex;
+            gap: 10px;
+            justify-content: flex-end;
+            margin-top: 20px;
+        }
+        
+        .btn-primary {
+            background: #4CAF50;
+            color: white;
+            border: none;
+            padding: 8px 16px;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+        
+        .btn-secondary {
+            background: #6c757d;
+            color: white;
+            border: none;
+            padding: 8px 16px;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="header">
+            <h1>🏥 江苏工伤联网结算接口测试平台</h1>
+            <p>基于JSSiInterface.dll的标准工伤联网接口 | 版本 V2.1 | 医院编号:SQ201348</p>
+        </div>
+        
+        <div class="main-content">
+            <div class="sidebar">
+                <div class="function-group">
+                    <h3>🔧 系统管理</h3>
+                    <button class="function-btn" onclick="loadFunction('init', event)">系统初始化</button>
+                    <button class="function-btn" onclick="loadFunction('health', event)">健康检查</button>
+                    <button class="function-btn" onclick="loadFunction('stats', event)">统计信息</button>
+                    <button class="function-btn" onclick="showConfigModal()">配置设置</button>
+                    <button class="function-btn" onclick="runDiagnostics()" style="background: #ff9800; color: white;">🔍 系统诊断</button>
+                </div>
+                
+                <div class="function-group">
+                    <h3>👤 认证类</h3>
+                    <button class="function-btn" onclick="loadFunction('signin', event)">操作员签到</button>
+                    <button class="function-btn" onclick="loadFunction('signout', event)">操作员签退</button>
+                    <button class="function-btn" onclick="loadFunction('signin_status', event)">签到状态</button>
+                </div>
+                
+                <div class="function-group">
+                    <h3>🏥 业务类</h3>
+                    <button class="function-btn" onclick="loadFunction('readcard', event)">工伤读卡</button>
+                    <button class="function-btn" onclick="loadFunction('register', event)">患者登记</button>
+                    <button class="function-btn" onclick="loadFunction('presettle', event)">费用预结算</button>
+                    <button class="function-btn" onclick="loadFunction('settle', event)">费用结算</button>
+                    <button class="function-btn" onclick="loadFunction('cancel_settle', event)">结算撤销</button>
+                </div>
+                
+                <div class="function-group">
+                    <h3>📄 处方类</h3>
+                    <button class="function-btn" onclick="loadFunction('upload_prescription', event)">处方上报</button>
+                    <button class="function-btn" onclick="loadFunction('cancel_prescription', event)">处方撤销</button>
+                    <button class="function-btn" onclick="loadFunction('batch_upload', event)">批量上传</button>
+                </div>
+                
+                <div class="function-group">
+                    <h3>🔄 其他</h3>
+                    <button class="function-btn" onclick="loadFunction('complete_process', event)">完整流程</button>
+                    <button class="function-btn" onclick="loadFunction('retry', event)">智能重试</button>
+                    <button class="function-btn" onclick="loadFunction('reverse', event)">交易冲正</button>
+                </div>
+            </div>
+            
+            <div class="content-area">
+                <div class="action-bar">
+                    <button class="execute-btn" onclick="executeAPI()" id="executeBtn">🚀 执行接口</button>
+                    <button class="clear-btn" onclick="clearAll()">🗑️ 清空</button>
+                    <div class="status-indicator">
+                        <div class="status-dot info" id="statusDot"></div>
+                        <span id="statusText">就绪</span>
+                    </div>
+                </div>
+                
+                <div class="params-section">
+                    <div class="params-panel">
+                        <div class="params-panel-header">📝 请求参数</div>
+                        <div class="params-panel-content">
+                            <textarea id="inputParams" class="params-textarea" placeholder="请选择左侧功能按钮加载默认参数..."></textarea>
+                        </div>
+                    </div>
+                    
+                    <div class="params-panel">
+                        <div class="params-panel-header">📊 响应结果</div>
+                        <div class="params-panel-content">
+                            <textarea id="outputParams" class="params-textarea result-textarea" readonly placeholder="执行接口后,返回结果将显示在这里..."></textarea>
+                        </div>
+                    </div>
+                </div>
+                
+                <div class="log-section">
+                    <div class="log-header">
+                        📋 执行日志
+                        <button class="clear-btn" onclick="clearLogs()" style="font-size: 12px; padding: 5px 10px;">清空日志</button>
+                    </div>
+                    <div class="log-content" id="logContent">
+                        <div class="log-entry info">[INFO] 江苏工伤联网测试平台已就绪</div>
+                    </div>
+                </div>
+                
+                <div class="help-panel" id="helpPanel">
+                    <h4>📚 使用说明</h4>
+                    <ul>
+                        <li>首次使用请先点击"系统初始化"</li>
+                        <li>业务交易前需要先"操作员签到"</li>
+                        <li>完整的工伤就医流程:读卡 → 登记 → 预结算 → 结算</li>
+                        <li>可以使用"健康检查"监控系统状态</li>
+                        <li>支持快捷键:Ctrl+Enter 执行接口,Ctrl+D 清空</li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+    <!-- 配置模态框 -->
+    <div class="config-modal" id="configModal">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h3>⚙️ 系统配置</h3>
+                <button class="close-btn" onclick="closeConfigModal()">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>医院编号 (fixmedinsCode)</label>
+                    <input type="text" id="fixmedinsCode" value="SQ201348">
+                </div>
+                <div class="form-group">
+                    <label>医院名称 (fixmedinsName)</label>
+                    <input type="text" id="fixmedinsName" value="沭阳铭和医院">
+                </div>
+                <div class="form-group">
+                    <label>接口版本 (interfaceVersion)</label>
+                    <input type="text" id="interfaceVersion" value="V2.1">
+                </div>
+                <div class="form-group">
+                    <label>操作员编号 (operatorId)</label>
+                    <input type="text" id="operatorId" value="001">
+                </div>
+                <div class="form-group">
+                    <label>操作员姓名 (operatorName)</label>
+                    <input type="text" id="operatorName" value="收费员张三">
+                </div>
+                <div class="form-group">
+                    <label>服务地址 (baseUrl)</label>
+                    <input type="text" id="baseUrl" value="http://localhost:8321">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button class="btn-primary" onclick="saveConfig()">保存</button>
+                <button class="btn-secondary" onclick="closeConfigModal()">取消</button>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        // 全局配置
+        let config = {
+            fixmedinsCode: "SQ201348",
+            fixmedinsName: "沭阳铭和医院",
+            interfaceVersion: "V2.1",
+            operatorId: "001",
+            operatorName: "收费员张三",
+            baseUrl: "http://localhost:8321"
+        };
+        
+        let currentFunction = null;
+        
+        // DOM 元素
+        const inputParams = document.getElementById('inputParams');
+        const outputParams = document.getElementById('outputParams');
+        const executeBtn = document.getElementById('executeBtn');
+        const statusDot = document.getElementById('statusDot');
+        const statusText = document.getElementById('statusText');
+        const logContent = document.getElementById('logContent');
+        
+        // 参数模板
+        const paramTemplates = {
+            init: {
+                action: "init",
+                config: {
+                    fixmedinsCode: "SQ201348",
+                    fixmedinsName: "沭阳铭和医院",
+                    receiverSysCode: "JSYTH",
+                    interfaceVersion: "V2.1",
+                    operatorType: "1",
+                    defaultOperator: "001",
+                    defaultOperatorName: "收费员张三",
+                    logPath: "logs/workinjury/"
+                }
+            },
+            signin: {
+                action: "transaction",
+                transactionName: "SignIn",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {}
+            },
+            signout: {
+                action: "transaction",
+                transactionName: "SignOut",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {}
+            },
+            readcard: {
+                action: "transaction",
+                transactionName: "ReadCard",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {}
+            },
+            register: {
+                action: "transaction",
+                transactionName: "RegisterPatient",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    psn_no: "32010219800101001X",
+                    visit_type: "1",
+                    dept_code: "001",
+                    dept_name: "骨科",
+                    doctor_code: "DOC001",
+                    doctor_name: "张主任",
+                    diag_code: "M79.900",
+                    diag_name: "骨折",
+                    visit_time: "2024-12-19 10:30:00"
+                }
+            },
+            presettle: {
+                action: "transaction",
+                transactionName: "PreSettle",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    visit_no: "V20241219001",
+                    fee_details: [
+                        {
+                            fee_ocur_time: "2024-12-19 10:30:00",
+                            med_list_codg: "001",
+                            med_list_name: "X光片检查",
+                            med_chrgitm_type: "4",
+                            fee_amt: 120.00,
+                            cnt: 1,
+                            pric: 120.00,
+                            spec: "胸部X光",
+                            dept_code: "001",
+                            dept_name: "骨科"
+                        }
+                    ]
+                }
+            },
+            settle: {
+                action: "transaction",
+                transactionName: "Settle",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    visit_no: "V20241219001",
+                    pre_settle_id: "PS20241219001"
+                }
+            },
+            cancel_settle: {
+                action: "transaction",
+                transactionName: "CancelSettle",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    original_settle_id: "ST20241219001",
+                    cancel_reason: "系统撤销"
+                }
+            },
+            upload_prescription: {
+                action: "transaction",
+                transactionName: "UploadPrescription",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    visit_no: "V20241219001",
+                    prescriptions: [
+                        {
+                            med_list_codg: "001",
+                            med_list_name: "阿莫西林胶囊",
+                            med_chrgitm_type: "1",
+                            fee_amt: 15.60,
+                            cnt: 1,
+                            pric: 15.60,
+                            spec: "0.25g*24粒",
+                            usage: "口服",
+                            dosage: "一次2粒,一日3次"
+                        }
+                    ]
+                }
+            },
+            cancel_prescription: {
+                action: "transaction",
+                transactionName: "CancelPrescription",
+                identifyMode: "1",
+                operatorId: "001",
+                operatorName: "收费员张三",
+                businessParams: {
+                    original_prescription_id: "RX20241219001",
+                    cancel_reason: "处方错误"
+                }
+            },
+            health: {
+                action: "health"
+            },
+            stats: {
+                action: "stats"
+            },
+            signin_status: {
+                action: "signin_status"
+            },
+            batch_upload: {
+                action: "batch_upload",
+                patientId: "32010219800101001X",
+                visitNo: "V20241219001",
+                prescriptions: [
+                    {
+                        med_list_codg: "001",
+                        med_list_name: "阿莫西林胶囊",
+                        med_chrgitm_type: "1",
+                        fee_amt: 15.60,
+                        cnt: 1,
+                        pric: 15.60
+                    },
+                    {
+                        med_list_codg: "002",
+                        med_list_name: "布洛芬片",
+                        med_chrgitm_type: "1",
+                        fee_amt: 12.50,
+                        cnt: 1,
+                        pric: 12.50
+                    }
+                ]
+            },
+            complete_process: {
+                action: "complete_process",
+                patientInfo: {
+                    visit_type: "1",
+                    dept_code: "001",
+                    dept_name: "骨科",
+                    doctor_code: "DOC001",
+                    doctor_name: "张主任"
+                },
+                feeDetails: [
+                    {
+                        med_list_codg: "001",
+                        med_list_name: "X光检查",
+                        med_chrgitm_type: "4",
+                        fee_amt: 120.00,
+                        cnt: 1,
+                        pric: 120.00
+                    }
+                ]
+            },
+            retry: {
+                action: "retry",
+                transactionName: "ReadCard",
+                maxRetries: 3,
+                baseDelayMs: 1000,
+                businessParams: {}
+            },
+            reverse: {
+                action: "reverse",
+                originalMessageId: "SQ201320241219103012340001"
+            }
+        };
+        
+        // 加载功能参数
+        function loadFunction(functionName, sourceEvent) {
+            // 移除之前的活动状态
+            document.querySelectorAll('.function-btn').forEach(btn => {
+                btn.classList.remove('active');
+            });
+            
+            // 设置当前按钮为活动状态(如果有事件源)
+            if (sourceEvent && sourceEvent.target) {
+                sourceEvent.target.classList.add('active');
+            } else {
+                // 如果没有事件源,根据functionName查找对应按钮
+                const targetBtn = Array.from(document.querySelectorAll('.function-btn')).find(btn => 
+                    btn.textContent.includes(getFunctionDisplayName(functionName)) ||
+                    btn.getAttribute('onclick') === `loadFunction('${functionName}')`
+                );
+                if (targetBtn) {
+                    targetBtn.classList.add('active');
+                }
+            }
+            
+            currentFunction = functionName;
+            
+            if (paramTemplates[functionName]) {
+                // 使用当前配置更新模板
+                let template = JSON.parse(JSON.stringify(paramTemplates[functionName]));
+                updateTemplateWithConfig(template);
+                
+                inputParams.value = JSON.stringify(template, null, 2);
+                addLog(`已加载 ${getFunctionDisplayName(functionName)} 参数模板`, 'info');
+                updateStatus('参数已加载', 'info');
+            } else {
+                addLog(`未找到 ${functionName} 的参数模板`, 'error');
+                updateStatus('参数加载失败', 'error');
+            }
+        }
+        
+        // 使用当前配置更新模板
+        function updateTemplateWithConfig(template) {
+            if (template.config) {
+                template.config.fixmedinsCode = config.fixmedinsCode;
+                template.config.fixmedinsName = config.fixmedinsName;
+                template.config.interfaceVersion = config.interfaceVersion;
+                template.config.defaultOperator = config.operatorId;
+                template.config.defaultOperatorName = config.operatorName;
+            }
+            
+            if (template.operatorId !== undefined) {
+                template.operatorId = config.operatorId;
+            }
+            
+            if (template.operatorName !== undefined) {
+                template.operatorName = config.operatorName;
+            }
+        }
+        
+        // 获取功能显示名称
+        function getFunctionDisplayName(functionName) {
+            const displayNames = {
+                init: "系统初始化",
+                signin: "操作员签到", 
+                signout: "操作员签退",
+                readcard: "工伤读卡",
+                register: "患者登记",
+                presettle: "费用预结算",
+                settle: "费用结算",
+                cancel_settle: "结算撤销",
+                upload_prescription: "处方上报",
+                cancel_prescription: "处方撤销",
+                health: "健康检查",
+                stats: "统计信息",
+                signin_status: "签到状态",
+                batch_upload: "批量上传",
+                complete_process: "完整流程",
+                retry: "智能重试",
+                reverse: "交易冲正"
+            };
+            return displayNames[functionName] || functionName;
+        }
+        
+        // 执行API调用
+        async function executeAPI() {
+            const startTime = new Date();
+            try {
+                const inputText = inputParams.value.trim();
+                if (!inputText) {
+                    addLog('请先选择功能并加载参数', 'error');
+                    updateStatus('参数为空', 'error');
+                    return;
+                }
+                
+                let params;
+                try {
+                    params = JSON.parse(inputText);
+                } catch (e) {
+                    addLog('参数JSON格式错误: ' + e.message, 'error');
+                    updateStatus('JSON格式错误', 'error');
+                    return;
+                }
+                
+                executeBtn.disabled = true;
+                executeBtn.textContent = '🔄 执行中...';
+                updateStatus('正在调用接口...', 'warning');
+                
+                addLog(`开始执行 ${getFunctionDisplayName(currentFunction)} 接口`, 'info');
+                addLog(`请求地址: ${config.baseUrl}/api/entry/workinjury`, 'info');
+                addLog(`请求参数: ${JSON.stringify(params)}`, 'info');
+                
+                // 创建 AbortController 来处理超时
+                const controller = new AbortController();
+                const timeoutId = setTimeout(() => {
+                    controller.abort();
+                    addLog('请求超时(30秒),已取消', 'error');
+                }, 30000);
+                
+                try {
+                    const response = await fetch(`${config.baseUrl}/api/entry/workinjury`, {
+                        method: 'POST',
+                        headers: {
+                            'Content-Type': 'application/json',
+                            'Accept': 'application/json',
+                            'Cache-Control': 'no-cache',
+                            'Pragma': 'no-cache'
+                        },
+                        body: JSON.stringify(params),
+                        signal: controller.signal
+                    });
+                    
+                    clearTimeout(timeoutId);
+                    
+                    const elapsed = new Date() - startTime;
+                    addLog(`HTTP状态码: ${response.status} (耗时: ${elapsed}ms)`, response.ok ? 'success' : 'error');
+                    
+                    if (!response.ok) {
+                        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+                    }
+                    
+                    const contentType = response.headers.get('content-type');
+                    if (!contentType || !contentType.includes('application/json')) {
+                        const text = await response.text();
+                        addLog(`服务端返回非JSON数据: ${text.substring(0, 200)}...`, 'error');
+                        throw new Error('服务端返回的不是JSON格式数据');
+                    }
+                    
+                    const result = await response.json();
+                    outputParams.value = JSON.stringify(result, null, 2);
+                    
+                    if (result.success === true) {
+                        addLog(`接口调用成功: ${result.message}`, 'success');
+                        updateStatus('接口调用成功', 'success');
+                    } else {
+                        addLog(`接口调用失败: ${result.message} (代码: ${result.code})`, 'error');
+                        updateStatus('接口调用失败', 'error');
+                        
+                        // 如果是DLL相关错误,提供额外建议
+                        if (result.message && result.message.includes('JSSiInterface.dll')) {
+                            addLog('建议检查: 1) DLL文件是否存在 2) DLL版本是否正确 3) 运行环境配置', 'warning');
+                        }
+                    }
+                    
+                } catch (fetchError) {
+                    clearTimeout(timeoutId);
+                    
+                    if (fetchError.name === 'AbortError') {
+                        throw new Error('请求超时');
+                    } else {
+                        throw fetchError;
+                    }
+                }
+                
+            } catch (error) {
+                const elapsed = new Date() - startTime;
+                addLog(`网络错误 (${elapsed}ms): ${error.message}`, 'error');
+                updateStatus('网络连接失败', 'error');
+                
+                // 提供更详细的错误信息和建议
+                let errorAdvice = '';
+                if (error.message.includes('Failed to fetch')) {
+                    errorAdvice = '建议检查: 1) 服务是否启动 2) 端口8321是否被占用 3) 防火墙设置';
+                } else if (error.message.includes('超时')) {
+                    errorAdvice = '建议检查: 1) 服务响应速度 2) DLL是否正常加载 3) 网络连接';
+                } else if (error.message.includes('CORS')) {
+                    errorAdvice = '建议检查: 1) 服务端CORS配置 2) 请求头设置';
+                }
+                
+                if (errorAdvice) {
+                    addLog(errorAdvice, 'warning');
+                }
+                
+                outputParams.value = JSON.stringify({
+                    success: false,
+                    error: error.message,
+                    timestamp: new Date().toISOString(),
+                    elapsed: elapsed + 'ms',
+                    function: currentFunction,
+                    advice: errorAdvice
+                }, null, 2);
+                
+            } finally {
+                executeBtn.disabled = false;
+                executeBtn.textContent = '🚀 执行接口';
+            }
+        }
+        
+        // 更新状态显示
+        function updateStatus(text, type = 'info') {
+            statusText.textContent = text;
+            statusDot.className = `status-dot ${type}`;
+        }
+        
+        // 添加日志
+        function addLog(message, type = 'info') {
+            const timestamp = new Date().toLocaleTimeString();
+            const logEntry = document.createElement('div');
+            logEntry.className = `log-entry ${type}`;
+            logEntry.textContent = `[${timestamp}] ${message}`;
+            
+            logContent.appendChild(logEntry);
+            logContent.scrollTop = logContent.scrollHeight;
+            
+            // 限制日志条数
+            const logs = logContent.querySelectorAll('.log-entry');
+            if (logs.length > 100) {
+                logs[0].remove();
+            }
+        }
+        
+        // 清空所有内容
+        function clearAll() {
+            inputParams.value = '';
+            outputParams.value = '';
+            updateStatus('已清空', 'info');
+            addLog('已清空所有内容', 'info');
+            
+            // 移除所有按钮的活动状态
+            document.querySelectorAll('.function-btn').forEach(btn => {
+                btn.classList.remove('active');
+            });
+            currentFunction = null;
+        }
+        
+        // 清空日志
+        function clearLogs() {
+            logContent.innerHTML = '<div class="log-entry info">[INFO] 日志已清空</div>';
+        }
+        
+        // 显示配置模态框
+        function showConfigModal() {
+            document.getElementById('fixmedinsCode').value = config.fixmedinsCode;
+            document.getElementById('fixmedinsName').value = config.fixmedinsName;
+            document.getElementById('interfaceVersion').value = config.interfaceVersion;
+            document.getElementById('operatorId').value = config.operatorId;
+            document.getElementById('operatorName').value = config.operatorName;
+            document.getElementById('baseUrl').value = config.baseUrl;
+            
+            document.getElementById('configModal').style.display = 'block';
+        }
+        
+        // 关闭配置模态框
+        function closeConfigModal() {
+            document.getElementById('configModal').style.display = 'none';
+        }
+        
+        // 保存配置
+        function saveConfig() {
+            config.fixmedinsCode = document.getElementById('fixmedinsCode').value;
+            config.fixmedinsName = document.getElementById('fixmedinsName').value;
+            config.interfaceVersion = document.getElementById('interfaceVersion').value;
+            config.operatorId = document.getElementById('operatorId').value;
+            config.operatorName = document.getElementById('operatorName').value;
+            config.baseUrl = document.getElementById('baseUrl').value;
+            
+            // 保存到localStorage
+            localStorage.setItem('workinjury_config', JSON.stringify(config));
+            
+            addLog('配置已保存', 'success');
+            closeConfigModal();
+        }
+        
+        // 加载保存的配置
+        function loadSavedConfig() {
+            const savedConfig = localStorage.getItem('workinjury_config');
+            if (savedConfig) {
+                try {
+                    config = { ...config, ...JSON.parse(savedConfig) };
+                    addLog('已加载保存的配置', 'info');
+                } catch (e) {
+                    addLog('配置加载失败,使用默认配置', 'warning');
+                }
+            }
+        }
+        
+        // 键盘快捷键
+        document.addEventListener('keydown', function(e) {
+            if (e.ctrlKey) {
+                switch(e.key) {
+                    case 'Enter':
+                        e.preventDefault();
+                        executeAPI();
+                        break;
+                    case 'd':
+                        e.preventDefault();
+                        clearAll();
+                        break;
+                }
+            }
+        });
+        
+        // 点击模态框外部关闭
+        document.getElementById('configModal').addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeConfigModal();
+            }
+        });
+        
+        // 运行系统诊断
+        async function runDiagnostics() {
+            addLog('开始运行系统诊断...', 'info');
+            updateStatus('正在诊断...', 'warning');
+            
+            const diagnostics = {
+                timestamp: new Date().toISOString(),
+                tests: {}
+            };
+            
+            // 1. 检查服务连通性
+            addLog('1. 检查服务连通性...', 'info');
+            try {
+                // 使用健康检查接口测试连通性,避免OPTIONS请求问题
+                const response = await fetch(`${config.baseUrl}/api/entry/workinjury`, {
+                    method: 'POST',
+                    headers: { 
+                        'Content-Type': 'application/json',
+                        'Accept': 'application/json'
+                    },
+                    body: JSON.stringify({ action: 'health' })
+                });
+                
+                if (response.ok) {
+                    diagnostics.tests.connectivity = {
+                        status: 'success',
+                        message: `服务可访问 (HTTP ${response.status})`,
+                        url: `${config.baseUrl}/api/entry/workinjury`
+                    };
+                    addLog('✓ 服务连通性检查通过', 'success');
+                } else {
+                    diagnostics.tests.connectivity = {
+                        status: 'error',
+                        message: `服务响应错误: HTTP ${response.status}`,
+                        url: `${config.baseUrl}/api/entry/workinjury`
+                    };
+                    addLog('✗ 服务连通性检查失败: HTTP ' + response.status, 'error');
+                }
+            } catch (error) {
+                diagnostics.tests.connectivity = {
+                    status: 'error',
+                    message: `服务无法访问: ${error.message}`,
+                    url: `${config.baseUrl}/api/entry/workinjury`
+                };
+                addLog('✗ 服务连通性检查失败: ' + error.message, 'error');
+            }
+            
+            // 2. 解析健康状态(从连通性检查的结果中获取)
+            addLog('2. 解析系统健康状态...', 'info');
+            if (diagnostics.tests.connectivity.status === 'success') {
+                try {
+                    // 从连通性检查的响应中获取健康检查结果
+                    const healthResponse = await fetch(`${config.baseUrl}/api/entry/workinjury`, {
+                        method: 'POST',
+                        headers: { 'Content-Type': 'application/json' },
+                        body: JSON.stringify({ action: 'health' })
+                    });
+                    
+                    if (healthResponse.ok) {
+                        const healthResult = await healthResponse.json();
+                        diagnostics.tests.health = healthResult;
+                        addLog('✓ 健康检查完成', 'success');
+                    } else {
+                        diagnostics.tests.health = {
+                            success: false,
+                            message: `健康检查失败: HTTP ${healthResponse.status}`
+                        };
+                        addLog('✗ 健康检查失败', 'error');
+                    }
+                } catch (error) {
+                    diagnostics.tests.health = {
+                        success: false,
+                        message: `健康检查异常: ${error.message}`
+                    };
+                    addLog('✗ 健康检查异常: ' + error.message, 'error');
+                }
+            } else {
+                diagnostics.tests.health = {
+                    success: false,
+                    message: '跳过健康检查(服务连通性失败)'
+                };
+                addLog('⚠ 跳过健康检查(服务不可达)', 'warning');
+            }
+            
+            // 3. 测试初始化
+            addLog('3. 测试系统初始化...', 'info');
+            if (diagnostics.tests.connectivity.status === 'success') {
+                try {
+                    const initResponse = await fetch(`${config.baseUrl}/api/entry/workinjury`, {
+                        method: 'POST',
+                        headers: { 'Content-Type': 'application/json' },
+                        body: JSON.stringify({
+                            action: 'init',
+                            config: {
+                                fixmedinsCode: config.fixmedinsCode,
+                                fixmedinsName: config.fixmedinsName,
+                                receiverSysCode: 'JSYTH',
+                                interfaceVersion: config.interfaceVersion,
+                                operatorType: '1',
+                                defaultOperator: config.operatorId,
+                                defaultOperatorName: config.operatorName,
+                                logPath: 'logs/workinjury/'
+                            }
+                        })
+                    });
+                    
+                    if (initResponse.ok) {
+                        const initResult = await initResponse.json();
+                        diagnostics.tests.initialization = initResult;
+                        if (initResult.success) {
+                            addLog('✓ 初始化测试成功', 'success');
+                        } else {
+                            addLog('✗ 初始化失败: ' + initResult.message, 'error');
+                        }
+                    } else {
+                        diagnostics.tests.initialization = {
+                            success: false,
+                            message: `初始化请求失败: HTTP ${initResponse.status}`
+                        };
+                        addLog('✗ 初始化请求失败: HTTP ' + initResponse.status, 'error');
+                    }
+                } catch (error) {
+                    diagnostics.tests.initialization = {
+                        success: false,
+                        message: `初始化测试异常: ${error.message}`
+                    };
+                    addLog('✗ 初始化测试异常: ' + error.message, 'error');
+                }
+            } else {
+                diagnostics.tests.initialization = {
+                    success: false,
+                    message: '跳过初始化测试(服务连通性失败)'
+                };
+                addLog('⚠ 跳过初始化测试(服务不可达)', 'warning');
+            }
+            
+            // 4. 环境信息收集
+            addLog('4. 收集环境信息...', 'info');
+            diagnostics.environment = {
+                userAgent: navigator.userAgent,
+                currentUrl: window.location.href,
+                timestamp: new Date().toLocaleString(),
+                config: config
+            };
+            addLog('✓ 环境信息收集完成', 'success');
+            
+            // 5. 生成诊断报告
+            const report = generateDiagnosticReport(diagnostics);
+            outputParams.value = JSON.stringify(diagnostics, null, 2);
+            
+            addLog('系统诊断完成', 'success');
+            addLog(report, 'info');
+            updateStatus('诊断完成', 'success');
+        }
+        
+        // 生成诊断报告
+        function generateDiagnosticReport(diagnostics) {
+            let report = '=== 诊断报告 ===\n';
+            
+            if (diagnostics.tests.connectivity?.status === 'success') {
+                report += '✓ 服务连通性: 正常\n';
+            } else {
+                report += '✗ 服务连通性: 异常 - ' + (diagnostics.tests.connectivity?.message || '未知错误') + '\n';
+            }
+            
+            if (diagnostics.tests.health?.success) {
+                report += '✓ 系统健康: 正常\n';
+            } else {
+                report += '✗ 系统健康: 异常 - ' + (diagnostics.tests.health?.message || '未知错误') + '\n';
+            }
+            
+            if (diagnostics.tests.initialization?.success) {
+                report += '✓ 系统初始化: 正常\n';
+            } else {
+                report += '✗ 系统初始化: 异常 - ' + (diagnostics.tests.initialization?.message || '未知错误') + '\n';
+            }
+            
+            // 提供解决建议
+            const hasErrors = Object.values(diagnostics.tests).some(test => 
+                test.status === 'error' || test.success === false
+            );
+            
+            if (hasErrors) {
+                report += '\n=== 解决建议 ===\n';
+                report += '1. 确认 ThCardReader.exe 服务已启动\n';
+                report += '2. 检查 JSSiInterface.dll 文件是否存在\n';
+                report += '3. 确认端口 8321 未被占用\n';
+                report += '4. 检查防火墙和杀毒软件设置\n';
+                report += '5. 确认医院编号和配置信息正确\n';
+            } else {
+                report += '\n✓ 所有检查都通过,系统状态正常';
+            }
+            
+            return report;
+        }
+        
+        // 页面加载完成
+        window.addEventListener('load', function() {
+            loadSavedConfig();
+            addLog('江苏工伤联网测试平台已启动', 'success');
+            updateStatus('系统就绪', 'success');
+            
+            // 默认加载初始化功能
+            setTimeout(() => {
+                loadFunction('init', null);
+            }, 500);
+        });
+    </script>
+</body>
+</html>