TVscreen/TAT/index copy.html

326 lines
12 KiB
HTML
Raw 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>
<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>