123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>江科HIS - 江苏医保电子凭证解码测试</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- body {
- font-family: 'Microsoft YaHei', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- min-height: 100vh;
- padding: 20px;
- }
- .container {
- max-width: 1400px;
- margin: 0 auto;
- background: white;
- border-radius: 15px;
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
- overflow: hidden;
- }
- .header {
- background: linear-gradient(135deg, #2980b9 0%, #3498db 100%);
- color: white;
- padding: 30px;
- text-align: center;
- position: relative;
- }
- .header::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="medical" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="rgba(255,255,255,0.1)"/></pattern></defs><rect width="100" height="100" fill="url(%23medical)"/></svg>');
- opacity: 0.3;
- }
- .header h1 {
- font-size: 2.5em;
- margin-bottom: 10px;
- position: relative;
- z-index: 2;
- }
- .header p {
- font-size: 1.2em;
- opacity: 0.9;
- position: relative;
- z-index: 2;
- }
- .content {
- padding: 40px;
- }
- .card-grid {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 30px;
- margin-bottom: 30px;
- }
- .card {
- background: #f8f9fa;
- border-radius: 12px;
- padding: 25px;
- border: 1px solid #e9ecef;
- transition: all 0.3s ease;
- }
- .card:hover {
- transform: translateY(-5px);
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
- }
- .card h3 {
- color: #2c3e50;
- margin-bottom: 20px;
- font-size: 1.3em;
- border-bottom: 2px solid #3498db;
- padding-bottom: 10px;
- }
- .business-types {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- gap: 15px;
- margin-bottom: 20px;
- }
- .business-btn {
- background: linear-gradient(135deg, #3498db, #2980b9);
- color: white;
- border: none;
- padding: 15px 20px;
- border-radius: 8px;
- cursor: pointer;
- font-size: 14px;
- font-weight: 600;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
- }
- .business-btn:hover {
- transform: translateY(-2px);
- box-shadow: 0 8px 25px rgba(52, 152, 219, 0.3);
- }
- .business-btn:active {
- transform: translateY(0);
- }
- .business-btn.outpatient { background: linear-gradient(135deg, #e74c3c, #c0392b); }
- .business-btn.inpatient { background: linear-gradient(135deg, #f39c12, #e67e22); }
- .business-btn.pharmacy { background: linear-gradient(135deg, #27ae60, #229954); }
- .test-controls {
- display: flex;
- gap: 15px;
- margin-bottom: 20px;
- flex-wrap: wrap;
- }
- .control-btn {
- padding: 12px 24px;
- border: none;
- border-radius: 6px;
- cursor: pointer;
- font-weight: 600;
- font-size: 14px;
- transition: all 0.3s ease;
- }
- .primary-btn {
- background: linear-gradient(135deg, #2ecc71, #27ae60);
- color: white;
- }
- .secondary-btn {
- background: linear-gradient(135deg, #95a5a6, #7f8c8d);
- color: white;
- }
- .control-btn:hover {
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
- }
- .result-area {
- background: #f8f9fa;
- border-radius: 12px;
- padding: 25px;
- margin-top: 20px;
- border: 1px solid #e9ecef;
- }
- .result-tabs {
- display: flex;
- gap: 10px;
- margin-bottom: 20px;
- }
- .tab-btn {
- padding: 10px 20px;
- border: none;
- background: #e9ecef;
- border-radius: 6px 6px 0 0;
- cursor: pointer;
- font-weight: 600;
- transition: all 0.3s ease;
- }
- .tab-btn.active {
- background: #3498db;
- color: white;
- }
- .result-content {
- background: white;
- border-radius: 6px;
- padding: 20px;
- border: 1px solid #dee2e6;
- min-height: 300px;
- font-family: 'Consolas', 'Monaco', monospace;
- white-space: pre-wrap;
- overflow-x: auto;
- }
- .status-indicator {
- display: inline-block;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- margin-right: 8px;
- }
- .status-success { background: #27ae60; }
- .status-error { background: #e74c3c; }
- .status-warning { background: #f39c12; }
- .status-info { background: #3498db; }
- .feature-list {
- list-style: none;
- padding: 0;
- }
- .feature-list li {
- padding: 8px 0;
- border-bottom: 1px solid #ecf0f1;
- display: flex;
- align-items: center;
- }
- .feature-list li:last-child {
- border-bottom: none;
- }
- .feature-icon {
- width: 20px;
- height: 20px;
- background: #27ae60;
- border-radius: 50%;
- margin-right: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: white;
- font-size: 12px;
- font-weight: bold;
- }
- .api-info {
- background: linear-gradient(135deg, #ecf0f1, #bdc3c7);
- padding: 20px;
- border-radius: 8px;
- margin: 15px 0;
- }
- .api-info h4 {
- color: #2c3e50;
- margin-bottom: 10px;
- font-size: 1.1em;
- }
- .api-url {
- background: white;
- padding: 10px;
- border-radius: 4px;
- font-family: 'Consolas', 'Monaco', monospace;
- border-left: 4px solid #3498db;
- margin: 5px 0;
- word-break: break-all;
- }
- @media (max-width: 768px) {
- .card-grid {
- grid-template-columns: 1fr;
- }
-
- .header h1 {
- font-size: 2em;
- }
-
- .content {
- padding: 20px;
- }
- }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="header">
- <h1>🏥 江科HIS</h1>
- <p>医疗信息系统 - 江苏医保电子凭证解码测试平台</p>
- </div>
- <div class="content">
- <div class="card-grid">
- <div class="card">
- <h3>🎯 业务类型测试</h3>
-
- <h4 style="color: #e74c3c; margin: 15px 0 10px 0;">门诊业务</h4>
- <div class="business-types">
- <button class="business-btn outpatient" onclick="testBusiness('01101')">01101 - 挂号</button>
- <button class="business-btn outpatient" onclick="testBusiness('01201')">01201 - 问诊</button>
- <button class="business-btn outpatient" onclick="testBusiness('01202')">01202 - 预约检查</button>
- <button class="business-btn outpatient" onclick="testBusiness('01203')">01203 - 检查</button>
- <button class="business-btn outpatient" onclick="testBusiness('01204')">01204 - 治疗</button>
- <button class="business-btn outpatient" onclick="testBusiness('01301')">01301 - 结算</button>
- <button class="business-btn outpatient" onclick="testBusiness('01302')">01302 - 取药</button>
- </div>
- <h4 style="color: #f39c12; margin: 15px 0 10px 0;">住院业务</h4>
- <div class="business-types">
- <button class="business-btn inpatient" onclick="testBusiness('01102')">01102 - 建档</button>
- <button class="business-btn inpatient" onclick="testBusiness('01103')">01103 - 入院登记</button>
- <button class="business-btn inpatient" onclick="testBusiness('01104')">01104 - 缴纳预缴金</button>
- </div>
- <h4 style="color: #27ae60; margin: 15px 0 10px 0;">药店业务</h4>
- <div class="business-types">
- <button class="business-btn pharmacy" onclick="testBusiness('02121')">02121 - 购药</button>
- <button class="business-btn pharmacy" onclick="testBusiness('02122')">02122 - 下载外购处方</button>
- </div>
- </div>
- <div class="card">
- <h3>⚙️ 系统功能特性</h3>
- <ul class="feature-list">
- <li>
- <span class="feature-icon">✓</span>
- <span>符合江苏医保接口规范 v0.9.9.15</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>支持1.14.6电子凭证解码功能</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>12种标准业务类型支持</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>自动初始化和配置管理</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>完整的错误处理机制</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>实时状态监控和反馈</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>兼容现有华视读卡器</span>
- </li>
- <li>
- <span class="feature-icon">✓</span>
- <span>RESTful API接口调用</span>
- </li>
- </ul>
- <div class="api-info">
- <h4>📡 API接口地址</h4>
- <div class="api-url">http://localhost:8321/api/entry?param=jiangsu_qrcode_01101</div>
- <div class="api-url">http://localhost:8321/api/entry?param=jiangsu_ec_01301</div>
- <p style="margin: 10px 0; color: #7f8c8d; font-size: 0.9em;">
- 格式: jiangsu_qrcode_[业务类型] 或 jiangsu_ec_[业务类型]
- </p>
- </div>
- </div>
- </div>
- <div class="card">
- <h3>🎛️ 测试控制台</h3>
- <div class="test-controls">
- <button class="control-btn primary-btn" onclick="initializeSystem()">
- 🔧 初始化系统
- </button>
- <button class="control-btn secondary-btn" onclick="checkStatus()">
- 📊 检查状态
- </button>
- <button class="control-btn secondary-btn" onclick="clearResults()">
- 🗑️ 清空结果
- </button>
- <button class="control-btn secondary-btn" onclick="exportResults()">
- 📥 导出结果
- </button>
- </div>
- <div class="result-area">
- <div class="result-tabs">
- <button class="tab-btn active" onclick="switchTab('response')">
- <span class="status-indicator status-info"></span>响应结果
- </button>
- <button class="tab-btn" onclick="switchTab('request')">
- <span class="status-indicator status-warning"></span>请求参数
- </button>
- <button class="tab-btn" onclick="switchTab('error')">
- <span class="status-indicator status-error"></span>错误信息
- </button>
- <button class="tab-btn" onclick="switchTab('logs')">
- <span class="status-indicator status-success"></span>系统日志
- </button>
- </div>
- <div id="result-content" class="result-content">
- 欢迎使用江科HIS江苏医保电子凭证解码测试平台!
- 请选择业务类型开始测试...
- 系统信息:
- - 接口版本: 江苏医保接口规范 v0.9.9.15
- - 解码功能: 1.14.6 电子凭证解码
- - 支持业务: 12种标准业务类型
- - 服务地址: http://localhost:8321
- - 状态: 等待测试
- </div>
- </div>
- </div>
- </div>
- </div>
- <script>
- let currentTab = 'response';
- let currentBusiness = '';
- let testResults = {};
- // 切换选项卡
- function switchTab(tab) {
- currentTab = tab;
-
- // 更新选项卡样式
- document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
- event.target.classList.add('active');
-
- // 显示对应内容
- updateResultContent();
- }
- // 测试业务功能
- async function testBusiness(businessType) {
- currentBusiness = businessType;
-
- // 显示加载状态
- document.getElementById('result-content').textContent = `正在测试业务类型: ${businessType}...\n\n请等待响应...`;
-
- try {
- // 构造请求URL
- const url = `http://localhost:8321/api/entry?param=jiangsu_qrcode_${businessType}`;
-
- const startTime = new Date();
-
- // 发送请求
- const response = await fetch(url, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- }
- });
-
- const endTime = new Date();
- const duration = endTime - startTime;
-
- const result = await response.text();
-
- // 保存测试结果
- testResults[businessType] = {
- request: {
- url: url,
- method: 'GET',
- businessType: businessType,
- timestamp: startTime.toISOString(),
- duration: duration + 'ms'
- },
- response: {
- status: response.status,
- statusText: response.statusText,
- data: result,
- timestamp: endTime.toISOString()
- }
- };
-
- updateResultContent();
-
- } catch (error) {
- testResults[businessType] = {
- request: {
- url: `http://localhost:8321/api/entry?param=jiangsu_qrcode_${businessType}`,
- method: 'GET',
- businessType: businessType,
- timestamp: new Date().toISOString()
- },
- error: error.message,
- timestamp: new Date().toISOString()
- };
-
- updateResultContent();
- }
- }
- // 更新结果显示
- function updateResultContent() {
- const content = document.getElementById('result-content');
-
- if (!currentBusiness || !testResults[currentBusiness]) {
- content.textContent = `当前选项卡: ${currentTab}\n\n暂无测试数据,请先选择业务类型进行测试。`;
- return;
- }
-
- const result = testResults[currentBusiness];
-
- switch (currentTab) {
- case 'response':
- if (result.response) {
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `响应状态: ${result.response.status} ${result.response.statusText}\n` +
- `响应时间: ${result.request.duration}\n` +
- `时间戳: ${result.response.timestamp}\n\n` +
- `响应数据:\n${result.response.data}`;
- } else if (result.error) {
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `错误信息: ${result.error}\n` +
- `时间戳: ${result.timestamp}`;
- }
- break;
-
- case 'request':
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `请求URL: ${result.request.url}\n` +
- `请求方法: ${result.request.method}\n` +
- `业务类型: ${result.request.businessType}\n` +
- `发送时间: ${result.request.timestamp}\n\n` +
- `实际DLL调用参数 (EcQuery函数):\n` +
- `{\n` +
- ` "data": {\n` +
- ` "orgId": "H32132200561",\n` +
- ` "businessType": "${result.request.businessType}",\n` +
- ` "operatorId": "system001",\n` +
- ` "operatorName": "系统管理员",\n` +
- ` "officeId": "32760",\n` +
- ` "officeName": "医保科"\n` +
- ` },\n` +
- ` "transType": "ec.query",\n` +
- ` "orgId": "H32132200561"\n` +
- `}\n\n` +
- `说明:\n` +
- `- orgId: 定点编号(医院组织机构代码)\n` +
- `- businessType: 用码业务类型\n` +
- `- operatorId: 收款员编号\n` +
- `- transType: 固定值 "ec.query"`;
- break;
-
- case 'error':
- if (result.error) {
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `错误类型: 网络连接错误\n` +
- `错误信息: ${result.error}\n` +
- `时间戳: ${result.timestamp}\n\n` +
- `故障排查建议:\n` +
- `1. 检查ThCardReader服务是否运行\n` +
- `2. 确认端口8321是否被占用\n` +
- `3. 验证江苏医保DLL是否正确部署\n` +
- `4. 检查网络配置参数`;
- } else if (result.response && result.response.status !== 200) {
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `HTTP状态: ${result.response.status} ${result.response.statusText}\n` +
- `时间戳: ${result.response.timestamp}\n\n` +
- `错误详情:\n${result.response.data}`;
- } else {
- content.textContent = `业务类型: ${currentBusiness}\n\n暂无错误信息。`;
- }
- break;
-
- case 'logs':
- content.textContent = `业务类型: ${currentBusiness}\n` +
- `测试日志记录:\n\n` +
- `[${result.request.timestamp}] 开始测试业务类型: ${currentBusiness}\n` +
- `[${result.request.timestamp}] 构造请求: ${result.request.url}\n` +
- `[${result.request.timestamp}] 发送HTTP请求...\n`;
-
- if (result.response) {
- content.textContent += `[${result.response.timestamp}] 收到响应: ${result.response.status}\n` +
- `[${result.response.timestamp}] 响应耗时: ${result.request.duration}\n` +
- `[${result.response.timestamp}] 测试完成\n`;
- } else if (result.error) {
- content.textContent += `[${result.timestamp}] 请求失败: ${result.error}\n` +
- `[${result.timestamp}] 测试中止\n`;
- }
- break;
- }
- }
- // 初始化系统
- async function initializeSystem() {
- document.getElementById('result-content').textContent = '正在初始化江苏医保系统...\n\n';
-
- try {
- const response = await fetch('http://localhost:8321/readcard/jiangsu/init', {
- method: 'GET'
- });
- const result = await response.text();
-
- document.getElementById('result-content').textContent =
- `系统初始化完成!\n\n` +
- `响应状态: ${response.status} ${response.statusText}\n` +
- `初始化结果:\n${result}`;
-
- } catch (error) {
- document.getElementById('result-content').textContent =
- `系统初始化失败!\n\n` +
- `错误信息: ${error.message}\n\n` +
- `请检查:\n` +
- `1. ThCardReader服务是否运行\n` +
- `2. 端口8321是否可用\n` +
- `3. 江苏医保DLL是否正确安装`;
- }
- }
- // 检查状态
- async function checkStatus() {
- document.getElementById('result-content').textContent = '正在检查系统状态...\n\n';
-
- try {
- const response = await fetch('http://localhost:8321/readcard/jiangsu/status', {
- method: 'GET'
- });
- const result = await response.text();
-
- document.getElementById('result-content').textContent =
- `系统状态检查完成!\n\n` +
- `响应状态: ${response.status} ${response.statusText}\n` +
- `系统状态:\n${result}`;
-
- } catch (error) {
- document.getElementById('result-content').textContent =
- `系统状态检查失败!\n\n` +
- `错误信息: ${error.message}`;
- }
- }
- // 清空结果
- function clearResults() {
- testResults = {};
- currentBusiness = '';
- document.getElementById('result-content').textContent =
- '结果已清空。\n\n请选择业务类型开始新的测试。';
- }
- // 导出结果
- function exportResults() {
- if (Object.keys(testResults).length === 0) {
- alert('暂无测试结果可导出!');
- return;
- }
-
- const exportData = {
- timestamp: new Date().toISOString(),
- system: '江科HIS - 江苏医保电子凭证解码测试',
- version: 'v0.9.9.15',
- results: testResults
- };
-
- const dataStr = JSON.stringify(exportData, null, 2);
- const dataBlob = new Blob([dataStr], {type: 'application/json'});
-
- const link = document.createElement('a');
- link.href = URL.createObjectURL(dataBlob);
- link.download = `江科HIS测试结果_${new Date().toISOString().replace(/[:.]/g, '-')}.json`;
- link.click();
- }
- // 页面加载完成后的初始化
- document.addEventListener('DOMContentLoaded', function() {
- console.log('江科HIS - 江苏医保电子凭证解码测试平台已加载');
- });
- </script>
- </body>
- </html>
|