TVscreen/TAT/index.html
2026-09-18 15:38:25 +08:00

374 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>