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

326 lines
12 KiB
HTML
Raw 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>
<script src="./js/vue.global.prod.js"></script>
<link rel="stylesheet" href="./css/element-plus.css">
<script src="./js/element-plus.js"></script>
<script src="./js/axios.min.js"></script>
<script src="./js/dayjs.min.js"></script>
<link rel="stylesheet" href="./css/index.css">
<style>
/* 右上角关闭叉号按钮 透明悬浮 */
.close-btn-box {
position: fixed;
right: 20px;
top: 30px;
/* z-index: 9999; */
}
.close-icon-btn {
width: 44px;
height: 44px;
line-height: 44px;
text-align: center;
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.25);
color: #fff;
border-radius: 50%;
cursor: pointer;
font-size: 24px;
font-weight: bold;
user-select: none;
}
.close-icon-btn:hover {
background: rgba(255, 0, 0, 0.35);
border-color: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body>
<div id="app">
<div class="screen-container">
<div class="screen-header">
<div class="screen-title">TAT超时提醒大屏</div>
<div class="screen-time">{{ nowTime }}</div>
</div>
<div class="grid-wrapper">
<div class="card">
<div class="card-header">
<span>已采集待收标本超时</span>
<span class="red-text">共 {{list1.length}}个标本</span>
</div>
<div class="table-box">
<el-table :data="pageList1" border stripe class="table" height="38vh" :header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="ksdh" label="科室" show-overflow-tooltip></el-table-column>
<el-table-column label="姓名/条码" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.brxm }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="cysj" label="采样时间" width="200" show-overflow-tooltip></el-table-column>
<el-table-column label="等待时间" width="120" show-overflow-tooltip>
<template #default="{ row }">
<span class="red-text">{{ row.holdtime || 0 }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="card">
<div class="card-header">
<span>已核收未上机超时</span>
<span class="red-text">共 {{list2.length}}个标本</span>
</div>
<div class="table-box">
<el-table :data="pageList2" border stripe class="table" height="38vh" :header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="ksdh" label="科室" show-overflow-tooltip></el-table-column>
<el-table-column label="姓名/条码" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.brxm }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="jssj" label="签收时间" width="200" show-overflow-tooltip></el-table-column>
<el-table-column label="等待时间" width="120" show-overflow-tooltip>
<template #default="{ row }">
<span class="red-text">{{ row.holdtime || 0 }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="card">
<div class="card-header">
<span>标本报告未完成超时</span>
<span class="red-text">共 {{list3.length}}个标本</span>
</div>
<div class="table-box">
<el-table :data="pageList3" border stripe class="table" height="38vh" :header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="yq" label="仪器" show-overflow-tooltip></el-table-column>
<el-table-column label="样本号/条码号" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.ybh }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="sjsj" label="上机时间" width="200" show-overflow-tooltip></el-table-column>
<el-table-column label="等待时间" width="120" show-overflow-tooltip>
<template #default="{ row }">
<span class="red-text">{{ row.holdtime || 0 }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="card">
<div class="card-header">危急值未处理超时</div>
<div class="table-box">
<el-table :data="pageList4" border stripe class="table" height="38vh" :header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="yq" label="仪器" show-overflow-tooltip></el-table-column>
<el-table-column prop="ybh" label="样本号" show-overflow-tooltip></el-table-column>
<el-table-column prop="xmmc" label="项目" show-overflow-tooltip></el-table-column>
<el-table-column prop="csjg" label="结果" show-overflow-tooltip></el-table-column>
<el-table-column label="等待时间" width="120" show-overflow-tooltip>
<template #default="{ row }">
<span class="red-text">{{ row.holdtime || 0 }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</div>
<!-- 右上角 叉号关闭按钮 无文字 -->
<div class="close-btn-box">
<div class="close-icon-btn" @click="closeCurrentPage">×</div>
</div>
</div>
<script>
const { createApp, ref, onMounted, onUnmounted } = Vue;
const app = createApp({
setup() {
const request = axios.create({ baseURL: '' });
// ==================== 从地址栏获取 rows 参数 ====================
function getPageSizeFromUrl() {
const params = new URLSearchParams(window.location.search);
const rows = parseInt(params.get('rows'));
return !isNaN(rows) && rows > 0 ? rows : 13; // 默认13行
}
// ==================== 配置 ====================
const PAGE_SIZE = getPageSizeFromUrl(); // 从地址栏获取,默认13
const PAGE_DELAY = 5000; // 翻页间隔
const NO_PAGE_DELAY = 5000; // 不足一页刷新间隔
// ===============================================
// 原始数据
const list1 = ref([]);
const list2 = ref([]);
const list3 = ref([]);
const list4 = ref([]);
// 分页展示数据
const pageList1 = ref([]);
const pageList2 = ref([]);
const pageList3 = ref([]);
const pageList4 = ref([]);
// 样式
const tableHeaderStyle = {
background: 'rgba(30, 104, 195, 1)',
color: '#ffffff', fontSize: '16px', fontWeight: 'bold',
borderColor: '#0099ff', padding: '4px 0px'
};
const tableCellStyle = {
background: 'transparent', color: '#ffffff', fontSize: '15px',
borderColor: '#0099ff', padding: '2px 0px'
};
const tableRowStyle = ({ rowIndex }) => ({
background: rowIndex % 2 === 0 ? 'transparent' : 'rgba(0, 153, 255, 0.1)'
});
// 时间
const nowTime = ref('');
const updateTime = () => {
nowTime.value = dayjs().format('YYYY年MM月DD日 HH:mm:ss');
};
// 关闭当前网页
const closeCurrentPage = () => {
window.close();
};
// 安全清除定时器
const safeClear = (timer) => timer && clearTimeout(timer);
// 核心:分页轮播 + 最后一页刷新
function startCarousel(list, pageList, onFinish) {
let currentPage = 0;
let timer = null;
function run() {
safeClear(timer);
const total = list.value.length;
if (total === 0) {
pageList.value = [];
timer = setTimeout(run, NO_PAGE_DELAY);
return;
}
// 不足一页:不翻页,定时刷新
if (total <= PAGE_SIZE) {
pageList.value = list.value;
timer = setTimeout(run, NO_PAGE_DELAY);
return;
}
// 计算分页
const start = currentPage * PAGE_SIZE;
const end = start + PAGE_SIZE;
pageList.value = list.value.slice(start, end);
const isLastPage = end >= total;
// 最后一页:停留后刷新数据
if (isLastPage) {
timer = setTimeout(() => {
currentPage = 0;
onFinish(); // 刷新
}, PAGE_DELAY);
} else {
// 下一页
timer = setTimeout(() => {
currentPage++;
run();
}, PAGE_DELAY);
}
}
run();
return () => safeClear(timer);
}
// 加载数据 + 启动轮播
function createLoader(url, list, pageList) {
let stopCarousel = null;
async function load() {
try {
if (stopCarousel) stopCarousel();
const { data: res } = await request.get(url);
list.value = res.data || [];
stopCarousel = startCarousel(list, pageList, load);
} catch (e) {
console.log("加载失败", url);
setTimeout(load, NO_PAGE_DELAY);
}
}
load();
return () => stopCarousel && stopCarousel();
}
// 启动所有表格
let stop1, stop2, stop3, stop4;
onMounted(() => {
updateTime();
setInterval(updateTime, 1000);
stop1 = createLoader('/api/list1', list1, pageList1);
stop2 = createLoader('/api/list2', list2, pageList2);
stop3 = createLoader('/api/list3', list3, pageList3);
stop4 = createLoader('/api/list4', list4, pageList4);
});
onUnmounted(() => {
stop1?.();
stop2?.();
stop3?.();
stop4?.();
});
return {
list1, list2, list3, list4,
pageList1, pageList2, pageList3, pageList4,
nowTime, tableHeaderStyle, tableCellStyle, tableRowStyle,
closeCurrentPage
};
}
});
app.use(ElementPlus).mount('#app');
</script>
</body>
</html>