TVscreen/TAT/index.html

374 lines
12 KiB
HTML
Raw Permalink Normal View History

2026-09-18 15:13:13 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TAT监控大屏</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="screen-container">
<div class="screen-header">
<div class="screen-title">TAT超时提醒大屏</div>
<div class="screen-time" id="timeDom"></div>
</div>
<div class="grid-wrapper">
<!-- 表格1 已采集待收标本超时 -->
<div class="card">
<div class="card-header">
<span>已采集待收标本超时</span>
<span class="red-text" id="count1">共 0个标本</span>
</div>
<div class="table-box">
<table id="table1">
<thead>
<tr>
<th>科室</th>
<th>姓名/条码</th>
<th>标本/项目</th>
<th>采样时间</th>
<th width="120">等待时间</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- 表格2 已核收未上机超时 -->
<div class="card">
<div class="card-header">
<span>已核收未上机超时</span>
<span class="red-text" id="count2">共 0个标本</span>
</div>
<div class="table-box">
<table id="table2">
<thead>
<tr>
<th>科室</th>
<th>姓名/条码</th>
<th>标本/项目</th>
<th>签收时间</th>
<th width="120">等待时间</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- 表格3 标本报告未完成超时 -->
<div class="card">
<div class="card-header">
<span>标本报告未完成超时</span>
<span class="red-text" id="count3">共 0个标本</span>
</div>
<div class="table-box">
<table id="table3">
<thead>
<tr>
<th>仪器</th>
<th>样本号/条码号</th>
<th>标本/项目</th>
<th>上机时间</th>
<th width="120">等待时间</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- 表格4 危急值未处理超时 -->
<div class="card">
<div class="card-header">
<span>危急值未处理超时</span>
<span class="red-text" id="count4">共 0个标本</span>
</div>
<div class="table-box">
<table id="table4">
<thead>
<tr>
<th>仪器</th>
<th>样本号</th>
<th>项目</th>
<th>结果</th>
<th width="120">等待时间</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 右上角关闭按钮 -->
<div class="close-btn-box">
<div class="close-icon-btn" onclick="closeCurrentPage()">×</div>
</div>
<script>
// ===================== 全局配置 =====================
// 从url获取每页行数
function getPageSizeFromUrl() {
const search = window.location.search.slice(1);
const params = new URLSearchParams(search);
const rows = parseInt(params.get('rows'));
return !isNaN(rows) && rows > 0 ? rows : 13;
}
const PAGE_SIZE = getPageSizeFromUrl();
const PAGE_DELAY = 5000; // 翻页间隔
const NO_PAGE_DELAY = 5000; // 不足一页/无数据刷新间隔
// 全局数据存储
const globalData = {
list1: [], list2: [], list3: [], list4: [],
pageList1: [], pageList2: [], pageList3: [], pageList4: []
};
// 定时器存储,页面卸载统一清空
const timerPool = {
timeClock: null,
carousel1: null, carousel2: null, carousel3: null, carousel4: null,
load1: null, load2: null, load3: null, load4: null
};
// ===================== 工具函数 =====================
// 安全清除定时器
function safeClear(timer) {
if (timer) clearTimeout(timer);
return null;
}
// 关闭页面
function closeCurrentPage() {
window.close();
}
// 更新顶部时间
function updateNowTime() {
const dom = document.getElementById('timeDom');
const d = new Date();
const pad = n => String(n).padStart(2, '0');
const year = d.getFullYear();
const month = pad(d.getMonth() + 1);
const day = pad(d.getDate());
const h = pad(d.getHours());
const m = pad(d.getMinutes());
const s = pad(d.getSeconds());
dom.innerText = `${year}年${month}月${day}日 ${h}:${m}:${s}`;
}
// 原生Ajax GET请求
function ajaxGet(url, callback) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
let res;
try {
res = JSON.parse(xhr.responseText);
} catch (err) {
res = {};
}
callback(null, res);
} else {
callback(new Error('请求失败'), null);
}
};
xhr.onerror = function () {
callback(new Error('网络错误'), null);
};
xhr.send();
}
// 渲染表格1 已采集待收标本超时
function renderTable1(dataArr) {
const tbody = document.querySelector('#table1 tbody');
const countDom = document.getElementById('count1');
tbody.innerHTML = '';
countDom.innerText = `共 ${globalData.list1.length}个标本`;
dataArr.forEach(row => {
const tr = document.createElement('tr');
const tds = [
{ text: row.ksdh },
{ text: `${row.brxm} / ${row.sqh}` },
{ text: `${row.yblx} / ${row.jymd}` },
{ text: row.cysj },
{ text: `${row.holdtime || 0} 分钟`, red: true }
];
tds.forEach(item => {
const td = document.createElement('td');
td.innerText = item.text;
td.setAttribute('data-tip', item.text);
if (item.red) td.className = 'red-text';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
}
// 渲染表格2 已核收未上机超时
function renderTable2(dataArr) {
const tbody = document.querySelector('#table2 tbody');
const countDom = document.getElementById('count2');
tbody.innerHTML = '';
countDom.innerText = `共 ${globalData.list2.length}个标本`;
dataArr.forEach(row => {
const tr = document.createElement('tr');
const tds = [
{ text: row.ksdh },
{ text: `${row.brxm} / ${row.sqh}` },
{ text: `${row.yblx} / ${row.jymd}` },
{ text: row.jssj },
{ text: `${row.holdtime || 0} 分钟`, red: true }
];
tds.forEach(item => {
const td = document.createElement('td');
td.innerText = item.text;
td.setAttribute('data-tip', item.text);
if (item.red) td.className = 'red-text';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
}
// 渲染表格3 标本报告未完成超时
function renderTable3(dataArr) {
const tbody = document.querySelector('#table3 tbody');
const countDom = document.getElementById('count3');
tbody.innerHTML = '';
countDom.innerText = `共 ${globalData.list3.length}个标本`;
dataArr.forEach(row => {
const tr = document.createElement('tr');
const tds = [
{ text: row.yq },
{ text: `${row.ybh} / ${row.sqh}` },
{ text: `${row.yblx} / ${row.jymd}` },
{ text: row.sjsj },
{ text: `${row.holdtime || 0} 分钟`, red: true }
];
tds.forEach(item => {
const td = document.createElement('td');
td.innerText = item.text;
td.setAttribute('data-tip', item.text);
if (item.red) td.className = 'red-text';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
}
// 渲染表格4 危急值未处理超时
function renderTable4(dataArr) {
const tbody = document.querySelector('#table4 tbody');
const countDom = document.getElementById('count4');
tbody.innerHTML = '';
countDom.innerText = `共 ${globalData.list4.length}个标本`;
dataArr.forEach(row => {
const tr = document.createElement('tr');
const tds = [
{ text: row.yq },
{ text: row.ybh },
{ text: row.xmmc },
{ text: row.csjg },
{ text: `${row.holdtime || 0} 分钟`, red: true }
];
tds.forEach(item => {
const td = document.createElement('td');
td.innerText = item.text;
td.setAttribute('data-tip', item.text);
if (item.red) td.className = 'red-text';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
}
// ===================== 分页轮播核心逻辑 =====================
/**
* @param listKey 全局原始数据key list1/list2...
* @param pageKey 分页数据key pageList1...
* @param renderFn 渲染函数
* @param timerKey 定时器存储key
* @param reloadFn 接口重载函数
*/
function startCarousel(listKey, pageKey, renderFn, timerKey, reloadFn) {
let currentPage = 0;
function runCarousel() {
timerPool[timerKey] = safeClear(timerPool[timerKey]);
const total = globalData[listKey].length;
if (total === 0) {
globalData[pageKey] = [];
renderFn([]);
timerPool[timerKey] = setTimeout(runCarousel, NO_PAGE_DELAY);
return;
}
// 数据不足一页,直接全部展示,定时刷新
if (total <= PAGE_SIZE) {
globalData[pageKey] = [...globalData[listKey]];
renderFn(globalData[pageKey]);
timerPool[timerKey] = setTimeout(runCarousel, NO_PAGE_DELAY);
return;
}
// 分页切片
const start = currentPage * PAGE_SIZE;
const end = start + PAGE_SIZE;
globalData[pageKey] = globalData[listKey].slice(start, end);
renderFn(globalData[pageKey]);
const isLastPage = end >= total;
if (isLastPage) {
// 最后一页停留后重新拉取接口数据
timerPool[timerKey] = setTimeout(() => {
currentPage = 0;
reloadFn();
}, PAGE_DELAY);
} else {
// 下一页
timerPool[timerKey] = setTimeout(() => {
currentPage++;
runCarousel();
}, PAGE_DELAY);
}
}
runCarousel();
}
// ===================== 接口加载封装 =====================
function createLoader(url, listKey, pageKey, renderFn, carouselTimerKey, loaderTimerKey) {
function loadData() {
timerPool[loaderTimerKey] = safeClear(timerPool[loaderTimerKey]);
// 停止当前轮播
timerPool[carouselTimerKey] = safeClear(timerPool[carouselTimerKey]);
ajaxGet(url, function (err, res) {
if (err) {
console.log('接口加载失败', url, err);
timerPool[loaderTimerKey] = setTimeout(loadData, NO_PAGE_DELAY);
return;
}
globalData[listKey] = res.data || [];
// 重启轮播
startCarousel(listKey, pageKey, renderFn, carouselTimerKey, loadData);
});
}
loadData();
}
// ===================== 页面初始化 =====================
function pageInit() {
// 初始化时间
updateNowTime();
timerPool.timeClock = setInterval(updateNowTime, 1000);
// 启动4个表格加载+轮播
createLoader('/api/list1', 'list1', 'pageList1', renderTable1, 'carousel1', 'load1');
createLoader('/api/list2', 'list2', 'pageList2', renderTable2, 'carousel2', 'load2');
createLoader('/api/list3', 'list3', 'pageList3', renderTable3, 'carousel3', 'load3');
createLoader('/api/list4', 'list4', 'pageList4', renderTable4, 'carousel4', 'load4');
}
// 页面卸载/关闭 清空全部定时器,释放资源
function clearAllTimer() {
Object.keys(timerPool).forEach(key => {
timerPool[key] = safeClear(timerPool[key]);
});
}
window.onbeforeunload = clearAllTimer;
window.onload = pageInit;
</script>
</body>
</html>