diff --git a/index.html b/index.html index 913f5fa..29020ee 100644 --- a/index.html +++ b/index.html @@ -280,6 +280,7 @@ const SITE_MAP = [ { file:'center-data-screen.html', label:'大屏数据配置' }, { file:'center-schedule.html', label:'排班配置' }, { file:'center-simulation.html', label:'模拟急救联动' }, + { file:'exception-dirty.html', label:'系统脏数据' }, { file:'exception-result.html', label:'结果异常' } ]}, { name:'应急就医(操作人员)', dir:'web-admin/emergency-dispatch/operator', entry:'emergency-active.html', pages:[ diff --git a/login.html b/login.html new file mode 100644 index 0000000..25223e1 --- /dev/null +++ b/login.html @@ -0,0 +1,166 @@ + + + + + +原型访问登录 - 健康长庆升级 + + + + +
+ +
+
+ + + +
+ +
+ + +
+ + +
+ +
+ + +
+ + +
+ + + + diff --git a/server.js b/server.js new file mode 100644 index 0000000..15a5fc3 --- /dev/null +++ b/server.js @@ -0,0 +1,228 @@ +/** + * 原型站轻量登录网关 + * + * 功能: + * - 所有静态文件访问前必须通过 Cookie 认证 + * - 未登录自动跳转到自定义登录页 + * - 密码写死在本文件中,按需修改 + * + * 启动:node server.js + * 默认端口:3000(可通过环境变量 PORT 修改) + */ + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const url = require('url'); +const crypto = require('crypto'); +const querystring = require('querystring'); + +/* ========== 配置区 ========== */ + +/** 访问密码(按需修改) */ +const PASSWORD = 'JKCQ_2026!'; + +/** Cookie 签名密钥(部署时建议替换为随机字符串) */ +const SECRET = 'hc-prototype-secret-key-2026'; + +/** Cookie 名称 */ +const COOKIE_NAME = 'prototype_auth'; + +/** Cookie 有效期(秒),默认 7 天 */ +const COOKIE_MAX_AGE = 7 * 24 * 60 * 60; + +/** 服务端口 */ +const PORT = process.env.PORT || 3010; + +/** 静态文件根目录(当前目录) */ +const STATIC_ROOT = __dirname; + +/** 不需要登录即可访问的路径 */ +const PUBLIC_PATHS = ['/login', '/login.html', '/favicon.ico']; + +/* ========== MIME 类型映射 ========== */ + +const MIME_TYPES = { + '.html': 'text/html; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.js': 'application/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', + '.woff': 'font/woff', + '.woff2': 'font/woff2', + '.ttf': 'font/ttf', + '.md': 'text/plain; charset=utf-8', +}; + +/* ========== 工具函数 ========== */ + +/** 生成签名 Cookie 值 */ +function signToken() { + var expires = Date.now() + COOKIE_MAX_AGE * 1000; + var payload = 'ok|' + expires; + var sig = crypto.createHmac('sha256', SECRET).update(payload).digest('hex').slice(0, 16); + return payload + '|' + sig; +} + +/** 校验签名 Cookie 值 */ +function verifyToken(token) { + if (!token) return false; + var parts = token.split('|'); + if (parts.length !== 3) return false; + var status = parts[0]; + var expires = parseInt(parts[1], 10); + var sig = parts[2]; + if (status !== 'ok' || isNaN(expires)) return false; + if (Date.now() > expires) return false; + var expected = crypto.createHmac('sha256', SECRET).update(status + '|' + expires).digest('hex').slice(0, 16); + return sig === expected; +} + +/** 从请求头解析指定 Cookie */ +function getCookie(req, name) { + var header = req.headers.cookie || ''; + var cookies = header.split(';'); + for (var i = 0; i < cookies.length; i++) { + var pair = cookies[i].trim().split('='); + if (pair[0] === name) return decodeURIComponent(pair.slice(1).join('=')); + } + return null; +} + +/** 读取 POST 请求体 */ +function readBody(req, callback) { + var chunks = []; + req.on('data', function(chunk) { chunks.push(chunk); }); + req.on('end', function() { callback(Buffer.concat(chunks).toString()); }); +} + +/** 安全校验回跳地址:只允许站内相对路径 */ +function safeRedirect(target) { + if (!target || typeof target !== 'string') return '/'; + if (target.charAt(0) !== '/') return '/'; + if (target.indexOf('//') === 0) return '/'; + return target; +} + +/** 发送静态文件 */ +function serveFile(res, filePath) { + /* 防止路径穿越攻击 */ + var resolved = path.resolve(filePath); + if (resolved.indexOf(path.resolve(STATIC_ROOT)) !== 0) { + res.writeHead(403); + res.end('Forbidden'); + return; + } + + /* 禁止访问敏感文件 */ + var basename = path.basename(resolved); + if (basename === 'server.js' || basename === '.env' || basename === '.gitignore') { + res.writeHead(403); + res.end('Forbidden'); + return; + } + + fs.stat(resolved, function(err, stats) { + if (err || !stats.isFile()) { + /* 目录请求尝试补 index.html */ + if (!err && stats.isDirectory()) { + var indexFile = path.join(resolved, 'index.html'); + serveFile(res, indexFile); + return; + } + res.writeHead(404); + res.end('Not Found'); + return; + } + + var ext = path.extname(resolved).toLowerCase(); + var contentType = MIME_TYPES[ext] || 'application/octet-stream'; + + res.writeHead(200, { 'Content-Type': contentType, 'Content-Length': stats.size }); + fs.createReadStream(resolved).pipe(res); + }); +} + +/* ========== 请求处理 ========== */ + +var server = http.createServer(function(req, res) { + var parsed = url.parse(req.url, true); + var pathname = decodeURIComponent(parsed.pathname); + + /* --- POST /simple-login:校验密码 --- */ + if (req.method === 'POST' && pathname === '/simple-login') { + readBody(req, function(body) { + var data = querystring.parse(body); + var password = data.password || ''; + var redirect = safeRedirect(data.redirect); + + if (password !== PASSWORD) { + res.writeHead(302, { 'Location': '/login.html?error=1&redirect=' + encodeURIComponent(redirect) }); + res.end(); + return; + } + + var token = signToken(); + var cookie = COOKIE_NAME + '=' + encodeURIComponent(token) + + '; Path=/; HttpOnly; SameSite=Lax; Max-Age=' + COOKIE_MAX_AGE; + + res.writeHead(302, { + 'Set-Cookie': cookie, + 'Location': redirect + }); + res.end(); + }); + return; + } + + /* --- POST /simple-logout:退出登录 --- */ + if (req.method === 'POST' && pathname === '/simple-logout') { + var clearCookie = COOKIE_NAME + '=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0'; + res.writeHead(302, { 'Set-Cookie': clearCookie, 'Location': '/login.html' }); + res.end(); + return; + } + + /* --- GET /simple-logout:也支持 GET 方式退出 --- */ + if (req.method === 'GET' && pathname === '/simple-logout') { + var clearCookie2 = COOKIE_NAME + '=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0'; + res.writeHead(302, { 'Set-Cookie': clearCookie2, 'Location': '/login.html' }); + res.end(); + return; + } + + /* --- 公开路径放行 --- */ + var isPublic = PUBLIC_PATHS.some(function(p) { return pathname === p; }); + + if (isPublic) { + var loginFile = pathname === '/login' ? '/login.html' : pathname; + var fullPath = path.join(STATIC_ROOT, loginFile); + serveFile(res, fullPath); + return; + } + + /* --- 鉴权:检查 Cookie --- */ + var token = getCookie(req, COOKIE_NAME); + if (!verifyToken(token)) { + res.writeHead(302, { 'Location': '/login.html?redirect=' + encodeURIComponent(pathname) }); + res.end(); + return; + } + + /* --- 已登录:返回静态文件 --- */ + if (pathname === '/') pathname = '/index.html'; + + var filePath = path.join(STATIC_ROOT, pathname); + serveFile(res, filePath); +}); + +server.listen(PORT, function() { + console.log('[原型网关] 已启动 -> http://localhost:' + PORT); + console.log('[原型网关] 访问密码: ' + PASSWORD); + console.log('[原型网关] 按 Ctrl+C 停止'); +}); diff --git a/web-admin/emergency-dispatch/admin/archive-center.html b/web-admin/emergency-dispatch/admin/archive-center.html index fa95fc6..4aacdde 100644 --- a/web-admin/emergency-dispatch/admin/archive-center.html +++ b/web-admin/emergency-dispatch/admin/archive-center.html @@ -65,7 +65,7 @@
diff --git a/web-admin/emergency-dispatch/admin/archive-personal-detail-illness.html b/web-admin/emergency-dispatch/admin/archive-personal-detail-illness.html index f9a09ee..ea7a498 100644 --- a/web-admin/emergency-dispatch/admin/archive-personal-detail-illness.html +++ b/web-admin/emergency-dispatch/admin/archive-personal-detail-illness.html @@ -67,6 +67,11 @@ .pagination span{font-size:var(--font-sm);color:var(--text-secondary);} .page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;} .page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);} + /* 固定列 */ + .col-fixed{position:sticky;z-index:2;background:#fff;} + thead .col-fixed{background:#FAFAFA;z-index:3;} + .col-fixed-1{left:0;min-width:60px;width:60px;} + .col-fixed-end{right:0;min-width:80px;box-shadow:-2px 0 4px rgba(0,0,0,0.04);} @@ -79,7 +84,7 @@
@@ -137,48 +142,53 @@
- +
-
-
+ + +
+ - +
-
-
大病就医记录
-
- + - + - + - + @@ -188,10 +198,10 @@ - + - + @@ -201,46 +211,46 @@ - + - + - + - - + + - + - + - + - + - + - +
序号序号 预约医院 挂号类别 预约科室 预约医生 期望预约时间 驻场人员工单状态预约状态 创建时间 完成时间操作操作
11 空军军医大学西京医院 普通号 内科已完成 2026-03-16 12:23:32 2026-03-18 15:42:10详细过程详细过程
22 西安交大一附院 专家号 心血管内科已完成 2026-03-08 14:05:18 2026-03-10 16:20:45详细过程详细过程
33 空军军医大学西京医院 急诊号 骨科 陈伟 2026-02-25 10:00 徐豪已完成已确认 2026-02-23 09:41:072026-02-25 14:33:28详细过程详细过程
44 西安市中心医院 普通号 消化内科 刘芳 2026-04-05 14:00 赵强进行中待确认 2026-04-03 10:12:55 详细过程详细过程
55 西安交大二附院 专家号 神经外科 孙建国 2026-04-12 08:30 王磊进行中已取消 2026-04-10 16:38:22 详细过程详细过程
diff --git a/web-admin/emergency-dispatch/admin/archive-personal-detail.html b/web-admin/emergency-dispatch/admin/archive-personal-detail.html index 94cd503..e8614d3 100644 --- a/web-admin/emergency-dispatch/admin/archive-personal-detail.html +++ b/web-admin/emergency-dispatch/admin/archive-personal-detail.html @@ -80,7 +80,7 @@
@@ -192,7 +192,7 @@ 张驻场 进行中 正常派单 - 详细过程 + 详细过程 2 @@ -205,7 +205,7 @@ 陈驻场 进行中 事后补单 - 详细过程 + 详细过程 3 @@ -218,7 +218,7 @@ 吴驻场 已完成 正常派单 - 详细过程 + 详细过程 4 @@ -231,7 +231,7 @@ 郑驻场 已完成 正常派单 - 详细过程 + 详细过程 5 @@ -244,7 +244,7 @@ 林驻场 已完成 事后补单 - 详细过程 + 详细过程 diff --git a/web-admin/emergency-dispatch/admin/archive-personal.html b/web-admin/emergency-dispatch/admin/archive-personal.html index a8020d1..1a0ec08 100644 --- a/web-admin/emergency-dispatch/admin/archive-personal.html +++ b/web-admin/emergency-dispatch/admin/archive-personal.html @@ -85,7 +85,7 @@
diff --git a/web-admin/emergency-dispatch/admin/archive-unit-detail-illness.html b/web-admin/emergency-dispatch/admin/archive-unit-detail-illness.html index 7269415..017fbba 100644 --- a/web-admin/emergency-dispatch/admin/archive-unit-detail-illness.html +++ b/web-admin/emergency-dispatch/admin/archive-unit-detail-illness.html @@ -61,6 +61,12 @@ .tag-green{background:#F6FFED;color:var(--success);} .tag-blue{background:var(--primary-light);color:var(--primary);} .tag-orange{background:#FFF7E6;color:var(--warning);} + .tag-gray{background:#F5F5F5;color:var(--text-secondary);} + /* 固定列 */ + .col-fixed{position:sticky;z-index:2;background:#fff;} + thead .col-fixed{background:#FAFAFA;z-index:3;} + .col-fixed-1{left:0;min-width:60px;width:60px;} + .col-fixed-end{right:0;min-width:80px;box-shadow:-2px 0 4px rgba(0,0,0,0.04);} .link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;} .link:hover{color:#40a9ff;} .pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);} @@ -81,7 +87,7 @@
@@ -137,22 +143,27 @@
- +
- +
@@ -163,7 +174,7 @@ - + @@ -173,15 +184,15 @@ - + - + - + @@ -194,10 +205,10 @@ - + - + @@ -207,13 +218,13 @@ - + - + - + @@ -226,10 +237,10 @@ - + - + @@ -242,10 +253,10 @@ - + - + @@ -258,7 +269,7 @@ - +
序号序号 就医员工 员工编号 员工部门预约医生 期望预约时间 驻场人员工单状态预约状态 创建时间 完成时间操作操作
11 张丽华-女-45 EMP20220089 综合管理部已完成 2026-04-11 09:32:47 2026-04-13 10:15:22详细过程详细过程
22 李明辉-男-50 EMP20210178 安全环保部张明远 2026-03-28 09:30 李晓明进行中已确认 2026-03-26 16:05:18 详细过程详细过程
33 王秀兰-女-55 EMP20200234 财务部待确认 2026-03-18 14:50:33 详细过程详细过程
44 赵德明-男-49 EMP20200312 人力资源部已完成 2026-03-14 22:18:05 2026-03-17 09:15:33详细过程详细过程
55 张丽华-女-45 EMP20220089 综合管理部已完成 2026-02-18 10:25:41 2026-02-22 11:08:22详细过程详细过程
@@ -341,7 +352,7 @@ 西安交大一附院 心内科 2026-03-28 09:30 - 进行中 + 已确认 3 diff --git a/web-admin/emergency-dispatch/admin/archive-unit-detail.html b/web-admin/emergency-dispatch/admin/archive-unit-detail.html index 5aa460e..3258e1d 100644 --- a/web-admin/emergency-dispatch/admin/archive-unit-detail.html +++ b/web-admin/emergency-dispatch/admin/archive-unit-detail.html @@ -84,7 +84,7 @@
@@ -204,7 +204,7 @@ 赵驻场 已完成 正常派单 - 详细过程 + 详细过程 2 @@ -219,7 +219,7 @@ 陈驻场 已完成 正常派单 - 详细过程 + 详细过程 3 @@ -234,7 +234,7 @@ 吴驻场 进行中 事后补单 - 详细过程 + 详细过程 4 @@ -249,7 +249,7 @@ 郑驻场 已完成 正常派单 - 详细过程 + 详细过程 5 @@ -264,7 +264,7 @@ 黄驻场 已完成 正常派单 - 详细过程 + 详细过程 diff --git a/web-admin/emergency-dispatch/admin/archive-unit.html b/web-admin/emergency-dispatch/admin/archive-unit.html index ebcdcc6..9fd7a0d 100644 --- a/web-admin/emergency-dispatch/admin/archive-unit.html +++ b/web-admin/emergency-dispatch/admin/archive-unit.html @@ -72,7 +72,7 @@
diff --git a/web-admin/emergency-dispatch/admin/center-basic-info-add.html b/web-admin/emergency-dispatch/admin/center-basic-info-add.html index 775f9b6..62aaec8 100644 --- a/web-admin/emergency-dispatch/admin/center-basic-info-add.html +++ b/web-admin/emergency-dispatch/admin/center-basic-info-add.html @@ -93,7 +93,7 @@
@@ -105,10 +105,10 @@
+
+
云坐席电话
+ +
*值班电话
diff --git a/web-admin/emergency-dispatch/admin/center-basic-info-detail.html b/web-admin/emergency-dispatch/admin/center-basic-info-detail.html index 83806fa..a650484 100644 --- a/web-admin/emergency-dispatch/admin/center-basic-info-detail.html +++ b/web-admin/emergency-dispatch/admin/center-basic-info-detail.html @@ -37,11 +37,11 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei diff --git a/web-admin/emergency-dispatch/admin/center-serious-illness.html b/web-admin/emergency-dispatch/admin/center-serious-illness.html index 05922ac..0c48876 100644 --- a/web-admin/emergency-dispatch/admin/center-serious-illness.html +++ b/web-admin/emergency-dispatch/admin/center-serious-illness.html @@ -102,7 +102,7 @@
@@ -404,7 +405,7 @@
-
+ -
+