test_debug_photo_detail.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>华视读卡器照片功能详细调试</title>
  7. <style>
  8. body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
  9. .container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; }
  10. .test-section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
  11. .result { margin: 10px 0; padding: 10px; border-radius: 4px; }
  12. .result.success { background: #d4edda; border: 1px solid #28a745; }
  13. .result.error { background: #f8d7da; border: 1px solid #dc3545; }
  14. .result.info { background: #d1ecf1; border: 1px solid #17a2b8; }
  15. .result.warning { background: #fff3cd; border: 1px solid #ffc107; }
  16. button { padding: 10px 20px; margin: 5px; border: none; border-radius: 4px; cursor: pointer; background: #007bff; color: white; }
  17. button:hover { background: #0056b3; }
  18. button.success { background: #28a745; }
  19. button.warning { background: #ffc107; color: #212529; }
  20. pre { background: #f8f9fa; padding: 10px; border-radius: 4px; overflow-x: auto; max-height: 300px; font-size: 12px; }
  21. .debug-panel { background: #f8f9fa; border: 1px solid #dee2e6; padding: 15px; margin: 10px 0; border-radius: 5px; }
  22. .step-title { font-weight: bold; color: #495057; margin-bottom: 10px; }
  23. </style>
  24. </head>
  25. <body>
  26. <div class="container">
  27. <h1>🔍 华视读卡器照片功能详细调试分析</h1>
  28. <div class="debug-panel">
  29. <div class="step-title">📋 调试计划</div>
  30. <p>本页面将逐步分析照片读取失败的原因:</p>
  31. <ol>
  32. <li><strong>验证基础功能</strong> - 确认读卡器工作正常</li>
  33. <li><strong>检查函数调用</strong> - 验证照片相关函数是否被正确调用</li>
  34. <li><strong>分析返回值</strong> - 检查函数返回值和错误代码</li>
  35. <li><strong>数据分析</strong> - 详细分析返回的数据内容</li>
  36. <li><strong>提供解决方案</strong> - 基于分析结果给出建议</li>
  37. </ol>
  38. </div>
  39. <div class="test-section">
  40. <h2>🧪 分步调试测试</h2>
  41. <button onclick="step1_BasicTest()">1️⃣ 基础功能测试</button>
  42. <button onclick="step2_PhotoTest()" class="warning">2️⃣ 照片功能测试</button>
  43. <button onclick="step3_DetailAnalysis()" class="success">3️⃣ 详细数据分析</button>
  44. <button onclick="clearResults()">🗑️ 清除结果</button>
  45. </div>
  46. <div id="results"></div>
  47. </div>
  48. <script>
  49. let lastReadCardData = null;
  50. function addResult(title, data, type = 'info') {
  51. const results = document.getElementById('results');
  52. const div = document.createElement('div');
  53. div.className = `result ${type}`;
  54. let content = `<h3>${title} <small>${new Date().toLocaleTimeString()}</small></h3>`;
  55. if (typeof data === 'object') {
  56. content += `<pre>${JSON.stringify(data, null, 2)}</pre>`;
  57. } else {
  58. content += `<pre>${data}</pre>`;
  59. }
  60. div.innerHTML = content;
  61. results.appendChild(div);
  62. results.scrollTop = results.scrollHeight;
  63. }
  64. function step1_BasicTest() {
  65. addResult('🚀 第1步:基础功能测试', '验证华视读卡器基本功能...', 'info');
  66. // 1.1 健康检查
  67. fetch('http://localhost:8321/readcard/huashi/health')
  68. .then(response => response.json())
  69. .then(data => {
  70. addResult('✅ 1.1 服务健康检查', data, 'success');
  71. // 1.2 设备状态
  72. return fetch('http://localhost:8321/readcard/huashi/status');
  73. })
  74. .then(response => response.json())
  75. .then(data => {
  76. const statusType = data.code === 200 ? 'success' : 'warning';
  77. addResult('📊 1.2 设备状态检查', data, statusType);
  78. if (data.code === 200) {
  79. addResult('🎯 第1步总结',
  80. `基础功能测试完成:
  81. • 服务状态:正常运行 ✅
  82. • 设备状态:${data.deviceStatus} ✅
  83. • 连接端口:${data.portDescription} ✅
  84. • 设备初始化:${data.initialized ? '已完成' : '未完成'} ${data.initialized ? '✅' : '⚠️'}
  85. 接下来进行照片功能测试...`, 'success');
  86. } else {
  87. addResult('❌ 第1步警告', '设备状态异常,可能影响照片读取功能', 'warning');
  88. }
  89. })
  90. .catch(error => {
  91. addResult('❌ 第1步失败', `基础功能测试失败: ${error.message}`, 'error');
  92. });
  93. }
  94. function step2_PhotoTest() {
  95. addResult('🚀 第2步:照片功能测试', '开始测试照片读取功能...', 'info');
  96. fetch('http://localhost:8321/readcard/huashi/simple?action=readcard&port=1001', {
  97. method: 'GET',
  98. headers: { 'Content-Type': 'application/json' }
  99. })
  100. .then(response => response.json())
  101. .then(data => {
  102. lastReadCardData = data;
  103. const type = data.code === 200 ? 'success' : 'error';
  104. addResult('📋 2.1 读卡结果', data, type);
  105. if (data.code === 200 && data.data) {
  106. analyzePhotoResult(data.data);
  107. }
  108. })
  109. .catch(error => {
  110. addResult('❌ 第2步失败', `照片功能测试失败: ${error.message}`, 'error');
  111. });
  112. }
  113. function analyzePhotoResult(cardData) {
  114. let analysis = '📸 照片数据分析:\n\n';
  115. // 基础信息
  116. analysis += '🔍 基础检查:\n';
  117. analysis += `• photoBase64 字段存在: ${cardData.hasOwnProperty('photoBase64')}\n`;
  118. analysis += `• photoBase64 值: "${cardData.photoBase64}"\n`;
  119. analysis += `• photoBase64 长度: ${cardData.photoBase64 ? cardData.photoBase64.length : 0}\n`;
  120. analysis += `• hasPhoto: ${cardData.hasPhoto}\n`;
  121. analysis += `• photoFormat: ${cardData.photoFormat || '未设置'}\n`;
  122. analysis += `• photoSize: ${cardData.photoSize || 0}\n\n`;
  123. // 问题诊断
  124. if (!cardData.photoBase64 || cardData.photoBase64.length === 0) {
  125. analysis += '❌ 问题诊断:\n';
  126. analysis += '• 照片BASE64数据为空\n';
  127. analysis += '• 可能原因:\n';
  128. analysis += ' 1. 华视SDK照片函数未正确调用\n';
  129. analysis += ' 2. 身份证芯片中没有照片数据\n';
  130. analysis += ' 3. SDK版本不支持照片读取\n';
  131. analysis += ' 4. 函数调用时机不正确\n';
  132. analysis += ' 5. P/Invoke声明有误\n\n';
  133. analysis += '🔧 建议排查步骤:\n';
  134. analysis += '• 检查调试输出中的函数调用日志\n';
  135. analysis += '• 验证Termb.dll是否包含照片函数\n';
  136. analysis += '• 确认身份证是否包含照片信息\n';
  137. analysis += '• 尝试不同的函数调用顺序\n';
  138. } else {
  139. analysis += '✅ 获取到照片数据\n';
  140. analysis += `• 数据长度: ${cardData.photoBase64.length}\n`;
  141. // 检查数据质量
  142. if (cardData.photoBase64.length > 100) {
  143. const uniqueChars = new Set(cardData.photoBase64.split('')).size;
  144. analysis += `• 字符种类数: ${uniqueChars}\n`;
  145. if (uniqueChars < 5) {
  146. analysis += '⚠️ 警告:字符种类过少,可能是无效数据\n';
  147. }
  148. }
  149. }
  150. addResult('🔍 照片数据分析', analysis, cardData.hasPhoto ? 'success' : 'warning');
  151. }
  152. function step3_DetailAnalysis() {
  153. if (!lastReadCardData) {
  154. addResult('⚠️ 第3步:需要先执行读卡', '请先执行第2步的照片功能测试', 'warning');
  155. return;
  156. }
  157. addResult('🚀 第3步:详细数据分析', '分析读卡数据的详细内容...', 'info');
  158. const cardData = lastReadCardData.data;
  159. let detailAnalysis = '📊 详细数据分析报告:\n\n';
  160. // 身份证基本信息
  161. detailAnalysis += '👤 身份证基本信息:\n';
  162. detailAnalysis += `• 姓名: ${cardData.name}\n`;
  163. detailAnalysis += `• 性别: ${cardData.sex}\n`;
  164. detailAnalysis += `• 民族: ${cardData.nation}\n`;
  165. detailAnalysis += `• 身份证号: ${cardData.idCode}\n`;
  166. detailAnalysis += `• 签发机关: ${cardData.department}\n`;
  167. detailAnalysis += `• 有效期: ${cardData.startDate} - ${cardData.endDate}\n\n`;
  168. // 照片功能状态
  169. detailAnalysis += '📸 照片功能状态:\n';
  170. detailAnalysis += `• 是否获取到照片: ${cardData.hasPhoto ? '❌ 否' : '❌ 否'}\n`;
  171. detailAnalysis += `• 照片格式: ${cardData.photoFormat || '未知'}\n`;
  172. detailAnalysis += `• 照片数据大小: ${cardData.photoSize || 0} 字节\n\n`;
  173. // 技术分析
  174. detailAnalysis += '🔧 技术分析:\n';
  175. detailAnalysis += '• SDK版本: 华视电子V3.3.0.7\n';
  176. detailAnalysis += '• 当前测试的函数:\n';
  177. detailAnalysis += ' - Getbase64JpgData (获取JPG格式BASE64)\n';
  178. detailAnalysis += ' - Getbase64BMPData (获取BMP格式BASE64)\n';
  179. detailAnalysis += ' - GetJpgData (获取JPG二进制数据)\n';
  180. detailAnalysis += ' - GetBMPData (获取BMP二进制数据)\n';
  181. detailAnalysis += ' - CVR_Read_Content (读取内容)\n\n';
  182. // 下一步建议
  183. detailAnalysis += '💡 下一步建议:\n';
  184. if (!cardData.hasPhoto) {
  185. detailAnalysis += '• 查看Visual Studio输出窗口的调试信息\n';
  186. detailAnalysis += '• 确认华视SDK是否支持当前身份证的照片读取\n';
  187. detailAnalysis += '• 尝试使用华视官方测试工具验证\n';
  188. detailAnalysis += '• 检查身份证是否为新版本(包含照片信息)\n';
  189. detailAnalysis += '• 联系华视技术支持确认SDK使用方法\n';
  190. } else {
  191. detailAnalysis += '• 照片功能正常工作\n';
  192. detailAnalysis += '• 可以考虑优化图片格式和大小\n';
  193. }
  194. addResult('📊 详细分析报告', detailAnalysis, 'info');
  195. // 显示调试建议
  196. addResult('🔬 调试建议',
  197. `基于当前分析结果,建议:
  198. 1. 📋 检查调试输出:
  199. 在Visual Studio的"输出"窗口查看Debug输出,
  200. 应该能看到照片获取过程的详细日志。
  201. 2. 🧪 验证SDK功能:
  202. 使用华视官方提供的测试程序验证:
  203. • Demo.exe
  204. • CAPKITestDemo.exe
  205. 看这些程序是否能正常读取照片。
  206. 3. 💳 确认身份证版本:
  207. 照片功能可能只对特定版本的身份证有效:
  208. • 二代身份证(包含照片芯片)
  209. • 部分一代身份证可能不包含照片信息
  210. 4. 🔧 技术验证:
  211. 可以尝试直接调用DLL函数进行测试,
  212. 确认是API层面问题还是SDK问题。`, 'info');
  213. }
  214. function clearResults() {
  215. document.getElementById('results').innerHTML = '';
  216. lastReadCardData = null;
  217. }
  218. // 页面加载提示
  219. window.onload = function() {
  220. addResult('🎯 华视读卡器照片功能详细调试',
  221. `本页面提供照片功能的深度调试分析。
  222. 🎯 调试目标:
  223. 找出照片BASE64返回为空的具体原因
  224. 🔍 调试方法:
  225. • 分步骤验证每个环节
  226. • 详细分析返回数据
  227. • 提供针对性解决方案
  228. 📋 使用说明:
  229. 1. 按顺序执行测试步骤
  230. 2. 仔细查看每步的输出结果
  231. 3. 根据分析结果进行问题排查
  232. ⚠️ 注意事项:
  233. • 确保身份证已正确放置在读卡器上
  234. • 运行测试前先检查设备状态
  235. • 建议同时查看程序的调试输出`, 'info');
  236. };
  237. </script>
  238. </body>
  239. </html>