<!DOCTYPE html>
|
<html lang="zh-CN">
|
|
<head>
|
<meta charset="UTF-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<title>诊间</title>
|
<style>
|
* {
|
box-sizing: border-box;
|
margin: 0;
|
padding: 0;
|
}
|
|
body {
|
font-family: "Microsoft YaHei", "Helvetica Neue", sans-serif;
|
background-color: #f4f5f7;
|
height: 100vh;
|
display: flex;
|
flex-direction: column;
|
overflow: hidden;
|
color: #333;
|
}
|
|
/* ================= 顶部 Header ================= */
|
.header {
|
background: #ffffff;
|
padding: 15px 20px;
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
|
z-index: 10;
|
text-align: center;
|
border-bottom: 1px solid #eee;
|
flex-shrink: 0;
|
}
|
|
.header-top {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 30px;
|
}
|
|
.logo {
|
height: 45px;
|
}
|
|
.time-box {
|
display: flex;
|
flex-direction: column;
|
line-height: 1.2;
|
text-align: center;
|
}
|
|
.week-day,
|
.full-date {
|
font-size: 16px;
|
color: #666;
|
}
|
|
.clock {
|
font-size: 36px;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.room-line {
|
margin-top: 10px;
|
font-size: 28px;
|
font-weight: bold;
|
letter-spacing: 2px;
|
color: #333;
|
}
|
|
/* ================= 主体内容区 ================= */
|
.main-container {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
padding: 15px;
|
gap: 15px;
|
overflow: hidden;
|
}
|
|
/* 队列面板通用样式 (左右布局) */
|
.panel {
|
background: white;
|
border-radius: 12px;
|
display: flex;
|
flex-direction: row;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
overflow: hidden;
|
flex: 1;
|
}
|
|
/* 左侧状态标签 (竖排) */
|
.panel-header {
|
width: 60px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 22px;
|
font-weight: bold;
|
color: #fff;
|
writing-mode: vertical-rl;
|
letter-spacing: 6px;
|
text-align: center;
|
flex-shrink: 0;
|
}
|
|
.status-active .panel-header {
|
background: #67c23a;
|
}
|
|
.status-waiting .panel-header {
|
background: #e6a23c;
|
}
|
|
.status-missed .panel-header {
|
background: #f56c6c;
|
}
|
|
/* 右侧列表内容区 */
|
.list-content {
|
flex: 1;
|
overflow-y: auto;
|
padding: 10px;
|
display: flex;
|
flex-wrap: wrap;
|
align-content: flex-start;
|
gap: 10px;
|
background: #fafafa;
|
}
|
|
/* 患者信息项 (固定高度,一行两个) */
|
.patient-item {
|
width: calc(50% - 5px);
|
height: 60px;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 0 15px;
|
background: #ffffff;
|
border: 1px solid #eee;
|
border-radius: 8px;
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
}
|
|
.p-name {
|
font-size: 28px;
|
font-weight: bold;
|
color: #303133;
|
}
|
|
.p-num {
|
font-size: 24px;
|
color: #909399;
|
font-weight: bold;
|
}
|
|
/* ================= 底部控制区 ================= */
|
.footer {
|
background: #fff;
|
padding: 15px 20px;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.05);
|
z-index: 10;
|
flex-shrink: 0;
|
position: relative;
|
}
|
|
.footer-text {
|
font-size: 20px;
|
color: #666;
|
font-weight: bold;
|
}
|
|
#test-voice-btn {
|
position: absolute;
|
right: 20px;
|
background-color: #007bff;
|
color: white;
|
border: none;
|
padding: 10px 20px;
|
border-radius: 6px;
|
font-size: 16px;
|
cursor: pointer;
|
font-weight: bold;
|
}
|
|
#test-voice-btn:hover {
|
background-color: #0056b3;
|
}
|
|
/* 调试信息区 */
|
.debug-info {
|
font-size: 14px;
|
color: #999;
|
background: #f0f0f0;
|
padding: 8px 15px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
flex-shrink: 0;
|
}
|
|
/* 滚动条美化 */
|
.list-content::-webkit-scrollbar {
|
width: 6px;
|
}
|
|
.list-content::-webkit-scrollbar-thumb {
|
background: #ddd;
|
border-radius: 3px;
|
}
|
</style>
|
</head>
|
|
<body>
|
<!-- 顶部栏 -->
|
<div class="header">
|
<div class="header-top">
|
<img src="logo.png" alt="Logo" class="logo">
|
<div class="time-box">
|
<span class="week-day" id="weekDay">星期日</span>
|
<span class="full-date" id="fullDate">2024年01月01日</span>
|
</div>
|
<div class="clock" id="clock">12:00</div>
|
</div>
|
<div class="room-line"><span id="currentRoomId">--</span></div>
|
</div>
|
|
<!-- 主体内容 -->
|
<div class="main-container">
|
<!-- 1. 正在就诊 -->
|
<div class="panel status-active" style="max-height: calc(60px * 2 + 20px + 20px);">
|
<div class="panel-header">正在就诊</div>
|
<div class="list-content" id="inProgressList"></div>
|
</div>
|
|
<!-- 2. 候诊中 -->
|
<div class="panel status-waiting" style="max-height: calc(60px * 4 + 30px + 20px);">
|
<div class="panel-header">候诊中</div>
|
<div class="list-content" id="waitingList"></div>
|
</div>
|
|
<!-- 3. 过号 -->
|
<div class="panel status-missed" style="max-height: calc(60px * 3 + 20px + 20px);">
|
<div class="panel-header">过号</div>
|
<div class="list-content" id="missedList"></div>
|
</div>
|
</div>
|
|
<!-- 底部控制栏 -->
|
<div class="footer">
|
<span class="footer-text">温馨提示:请耐心等待,保持安静!</span>
|
<button id="test-voice-btn">测试语音</button>
|
</div>
|
|
<!-- 调试信息 -->
|
<div class="debug-info" id="debugInfo">调试状态:等待数据...</div>
|
|
<script>
|
// ================= 配置参数 =================
|
var CONFIG = {
|
apiBaseUrl: "http://192.168.100.110:48080/admin-api",
|
// apiBaseUrl: "http://192.168.100.110:48080/admin-api",
|
roomId: "116",
|
refreshRate: 5000
|
};
|
var CALL_TIMES = 2; // 叫号次数
|
|
var appState = { roomName: '', lastSpokenPatient: null };
|
function $(id) { return document.getElementById(id); }
|
|
// ================= 时间模块 =================
|
function updateClock() {
|
var now = new Date();
|
$('clock').innerText = ('0' + now.getHours()).slice(-2) + ':' + ('0' + now.getMinutes()).slice(-2);
|
$('fullDate').innerText = now.getFullYear() + '年' + ('0' + (now.getMonth() + 1)).slice(-2) + '月' + ('0' + now.getDate()).slice(-2) + '日';
|
$('weekDay').innerText = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][now.getDay()];
|
}
|
setInterval(updateClock, 1000); updateClock();
|
|
// ================= 语音播报 =================
|
function speakText(text, times) {
|
times = times || CALL_TIMES;
|
var isAndroid = /Android/i.test(navigator.userAgent);
|
if (isAndroid && window.wowjoy && typeof window.wowjoy.speek === 'function') {
|
for (var i = 0; i < times; i++) setTimeout(function () { window.wowjoy.speek(text); }, i * 1500);
|
} else if (window.speechSynthesis) {
|
window.speechSynthesis.cancel();
|
var utterance = new window.SpeechSynthesisUtterance(text);
|
utterance.lang = 'zh-CN'; utterance.rate = 1.0;
|
window.speechSynthesis.speak(utterance);
|
for (var j = 1; j < times; j++) setTimeout(function () { window.speechSynthesis.speak(utterance); }, j * 1500);
|
}
|
}
|
|
// ================= 数据请求 =================
|
function fetchData() {
|
var url = CONFIG.apiBaseUrl + "/ecg/screen/room-screen-data?roomId=" + CONFIG.roomId;
|
var xhr = new XMLHttpRequest();
|
xhr.open('GET', url, true);
|
xhr.onreadystatechange = function () {
|
if (xhr.readyState === 4) {
|
if (xhr.status === 200) {
|
try {
|
var response = JSON.parse(xhr.responseText);
|
processData(response);
|
updateDebugInfo("获取数据成功 | 原始数据长度: " + (response.data ? Object.keys(response.data).length : 0));
|
} catch (e) { updateDebugInfo("JSON解析失败: " + e.message); }
|
} else { updateDebugInfo("请求失败,状态码: " + xhr.status); }
|
}
|
};
|
xhr.send();
|
}
|
|
// ================= 核心业务逻辑处理 =================
|
function processData(res) {
|
var data = res.data || res;
|
|
// 1. 更新诊室名称 (从第一条数据中获取)
|
var currentRoomName = CONFIG.roomId;
|
var waitingArr = data["1"] || [];
|
var inProgressArr = data["2"] || [];
|
var missedArr = data["3"] || [];
|
|
if (waitingArr.length > 0) currentRoomName = waitingArr[0].roomName || currentRoomName;
|
else if (inProgressArr.length > 0) currentRoomName = inProgressArr[0].roomName || currentRoomName;
|
else if (missedArr.length > 0) currentRoomName = missedArr[0].roomName || currentRoomName;
|
|
appState.roomName = currentRoomName;
|
$('currentRoomId').innerText = currentRoomName;
|
|
// 2. 根据状态码进行二次分类 (处理兜底逻辑)
|
var finalWaitingList = [];
|
var finalInProgressList = [];
|
var finalMissedList = [];
|
|
// 处理候诊队列 (包含兜底)
|
for (var i = 0; i < waitingArr.length; i++) {
|
var status = parseInt(waitingArr[i].status, 10);
|
if (status === 30) finalInProgressList.push(waitingArr[i]);
|
else if (status === 3 || status === 5 || status === 7) finalMissedList.push(waitingArr[i]);
|
else finalWaitingList.push(waitingArr[i]);
|
}
|
// 处理就诊队列
|
for (var j = 0; j < inProgressArr.length; j++) {
|
var status2 = parseInt(inProgressArr[j].status, 10);
|
if (status2 === 3 || status2 === 5 || status2 === 7) finalMissedList.push(inProgressArr[j]);
|
else if (status2 !== 30) finalWaitingList.push(inProgressArr[j]);
|
else finalInProgressList.push(inProgressArr[j]);
|
}
|
// 处理过号队列
|
for (var k = 0; k < missedArr.length; k++) {
|
var status3 = parseInt(missedArr[k].status, 10);
|
if (status3 === 30) finalInProgressList.push(missedArr[k]);
|
else if (status3 !== 3 && status3 !== 5 && status3 !== 7) finalWaitingList.push(missedArr[k]);
|
else finalMissedList.push(missedArr[k]);
|
}
|
|
// 3. 渲染列表
|
renderList('inProgressList', finalInProgressList);
|
renderList('waitingList', finalWaitingList);
|
renderList('missedList', finalMissedList);
|
|
// 4. 更新调试信息
|
updateDebugInfo("候诊:" + finalWaitingList.length + " | 就诊:" + finalInProgressList.length + " | 过号:" + finalMissedList.length);
|
|
// 5. 智能呼叫逻辑
|
if (finalInProgressList.length > 0) {
|
var currentPatient = finalInProgressList[0];
|
var patientId = currentPatient.patId || currentPatient.seqNum;
|
if (appState.lastSpokenPatient !== patientId) {
|
appState.lastSpokenPatient = patientId;
|
speakText(currentPatient.patName + ",请到" + appState.roomName, CALL_TIMES);
|
}
|
} else {
|
appState.lastSpokenPatient = null;
|
}
|
}
|
|
// ================= 渲染列表 =================
|
function renderList(containerId, listData) {
|
var container = $(containerId);
|
container.innerHTML = "";
|
if (listData.length === 0) {
|
container.innerHTML = '<div style="text-align:center; color:#ccc; width:100%; height:60px; line-height:60px; font-size:18px;">暂无患者</div>';
|
return;
|
}
|
for (var i = 0; i < listData.length; i++) {
|
var item = listData[i];
|
var div = document.createElement('div');
|
div.className = 'patient-item';
|
div.innerHTML = '<span class="p-name">' + (item.patName || '未知') + '</span>' +
|
'<span class="p-num">' + (item.seqNum || item.bookSeqNum || '--') + '号</span>';
|
container.appendChild(div);
|
}
|
}
|
|
function updateDebugInfo(msg) {
|
var debugEl = $('debugInfo');
|
if (debugEl) debugEl.innerText = "调试信息: " + msg + " | 时间: " + new Date().toLocaleTimeString();
|
}
|
|
// ================= 初始化 =================
|
window.onload = function () {
|
updateDebugInfo("页面加载完成,即将开始轮询...");
|
fetchData();
|
setInterval(fetchData, CONFIG.refreshRate);
|
$('test-voice-btn').addEventListener('click', function () {
|
updateDebugInfo("用户点击测试语音");
|
speakText("正在测试语音呼叫", CALL_TIMES);
|
}, false);
|
};
|
</script>
|
</body>
|
|
</html>
|