TVscreen/TAT/index-1.html

388 lines
14 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">
</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="list1" border stripe class="table" height="35vh" ref="table1Ref"
:header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="ksdh" label="科室"></el-table-column>
<el-table-column label="姓名/条码">
<template #default="{ row }">
<span>{{ row.brxm }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目">
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="cysj" label="采样时间"></el-table-column>
<el-table-column label="等待时间">
<template #default="{ row }">
<span class="red-text">{{ row.holdtime }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</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="list2" border stripe class="table" height="35vh" ref="table2Ref"
:header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="ksdh" label="科室"></el-table-column>
<el-table-column label="姓名/条码">
<template #default="{ row }">
<span>{{ row.brxm }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目">
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="jssj" label="签收时间"></el-table-column>
<el-table-column label="等待时间">
<template #default="{ row }">
<span class="red-text">{{ row.holdtime }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
<div class="card">
<div class="card-header">
<span>标本完成效率TAT</span>
</div>
<div class="table-box">
<el-table :data="list3" border stripe class="table" height="35vh" ref="table3Ref"
:header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="yq" label="仪器"></el-table-column>
<el-table-column label="样本号/条码号">
<template #default="{ row }">
<span>{{ row.ybh }} / {{ row.sqh }}</span>
</template>
</el-table-column>
<el-table-column label="标本/项目">
<template #default="{ row }">
<span>{{ row.yblx }} / {{ row.jymd }}</span>
</template>
</el-table-column>
<el-table-column prop="sjsj" label="上机时间"></el-table-column>
<el-table-column label="等待时间">
<template #default="{ row }">
<span class="red-text">{{ row.holdtime }} 分钟</span>
</template>
</el-table-column>
</el-table>
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
<div class="card">
<div class="card-header red-title">危急值结果:(请工作人员及时处理!)</div>
<div class="table-box">
<el-table :data="list4" border stripe class="table" height="35vh" ref="table4Ref"
:header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle" :row-style="tableRowStyle">
<el-table-column prop="yq" label="仪器"></el-table-column>
<el-table-column prop="ybh" label="样本号"></el-table-column>
<el-table-column prop="xmmc" label="项目"></el-table-column>
<el-table-column prop="csjg" label="结果"></el-table-column>
<el-table-column prop="confirm" label="确认超时"></el-table-column>
</el-table>
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</div>
</div>
</div>
<script>
const { createApp, ref, onMounted, onUnmounted, nextTick } = Vue;
const app = createApp({
components: {
...ElementPlus.components
},
setup() {
// 创建axios实例
const request = axios.create({
baseURL: '',
timeout: 5000 // 请求超时时间
})
// 表格数据
const list1 = ref([]);
const list2 = ref([]);
const list3 = ref([]);
const list4 = 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 }) => {
return {
background: rowIndex % 2 === 0 ? 'transparent' : 'rgba(0, 153, 255, 0.1)',
hover: 'rgba(0, 153, 255, 0.2)'
}
}
// 表格引用
const table1Ref = ref()
const table2Ref = ref()
const table3Ref = ref()
const table4Ref = ref()
// 定义各表格对应的接口地址
const tableApiMap = {
list1: '/api/list1',
list2: '/api/list2',
list3: '/api/list3',
list4: '/api/list4'
};
// 配置
const SCROLL_INTERVAL = 100; // 滚动速度
const SCROLL_PAUSE = 5000; // 到底停顿时间
const NO_SCROLL_REFRESH = 5000; // 无滚动自动刷新
const TOP_PAUSE = 3000; // 回到顶部后停顿时间
// 锁:防止重复触发
const locked = ref({
list1: false,
list2: false,
list3: false,
list4: false
});
const getScrollWrapper = (tableRef) => {
if (!tableRef.value) return null;
const bodyWrapper = tableRef.value.layout.table.refs.bodyWrapper;
return bodyWrapper?.firstElementChild?.firstElementChild || null;
};
// 获取单个表格数据
const fetchTableData = async (listKey) => {
try {
const response = await request.get(tableApiMap[listKey]);
// 根据列表key更新对应数据
if (listKey === 'list1') {
list1.value = response.data.data || [];
} else if (listKey === 'list2') {
list2.value = response.data.data || [];
} else if (listKey === 'list3') {
list3.value = response.data.data || [];
} else if (listKey === 'list4') {
list4.value = response.data.data || [];
}
console.log(`成功获取${listKey}数据`, response.data);
} catch (error) {
console.error(`获取${listKey}数据失败`, error);
}
};
// 封装滚动函数,接收表格ref、数据列表key、数据列表
const createTableScroll = (tableRef, listKey) => {
let scrollTimer = null;
let refreshTimer = null;
const clear = () => {
clearInterval(scrollTimer);
clearInterval(refreshTimer);
scrollTimer = null;
refreshTimer = null;
};
const start = () => {
clear();
// 定时检查:是否需要滚动
const checkAndScroll = () => {
const wrapper = getScrollWrapper(tableRef);
if (!wrapper) return;
// 内容没有溢出 → 只刷新,不滚动
if (wrapper.scrollHeight <= wrapper.clientHeight) {
return;
}
// 锁定中 → 不滚动
if (locked.value[listKey]) return;
// 正常滚动
wrapper.scrollTop += 1;
// 判断到底
const isBottom = wrapper.scrollTop + wrapper.clientHeight >= wrapper.scrollHeight - 2;
if (isBottom) {
locked.value[listKey] = true;
clearInterval(scrollTimer);
// 停顿后刷新 + 重置
setTimeout(async () => {
await fetchTableData(listKey);
await nextTick(); // 等待DOM更新
const newWrapper = getScrollWrapper(tableRef);
if (newWrapper) newWrapper.scrollTop = 0;
// 新增:回到顶部后停顿3秒再解锁并重启滚动
setTimeout(() => {
locked.value[listKey] = false;
start(); // 重新启动滚动
}, TOP_PAUSE);
}, SCROLL_PAUSE);
}
};
// 启动滚动定时器
scrollTimer = setInterval(checkAndScroll, SCROLL_INTERVAL);
// 无滚动时定时刷新
refreshTimer = setInterval(async () => {
const wrapper = getScrollWrapper(tableRef);
if (wrapper && wrapper.scrollHeight <= wrapper.clientHeight) {
await fetchTableData(listKey);
}
}, NO_SCROLL_REFRESH);
};
return { start, clear };
};
// 初始化所有表格数据
const initAllTableData = async () => {
await Promise.all([
fetchTableData('list1'),
fetchTableData('list2'),
fetchTableData('list3'),
fetchTableData('list4')
]);
};
// 每个表格独立实例化滚动
const table1Scroll = createTableScroll(table1Ref, 'list1');
const table2Scroll = createTableScroll(table2Ref, 'list2');
const table3Scroll = createTableScroll(table3Ref, 'list3');
const table4Scroll = createTableScroll(table4Ref, 'list4');
// 动态时间
const nowTime = ref('');
const updateTime = () => {
nowTime.value = dayjs().format('YYYY年MM月DD日 HH:mm:ss');
};
let timeTimer = null;
onMounted(async () => {
// 更新时间
updateTime();
timeTimer = setInterval(updateTime, 1000);
// 初始化加载所有表格数据
await initAllTableData();
// 等待DOM渲染完成后启动表格滚动/刷新
await nextTick();
table1Scroll.start();
table2Scroll.start();
table3Scroll.start();
table4Scroll.start();
});
onUnmounted(() => {
// 清理所有定时器
clearInterval(timeTimer);
table1Scroll.clear();
table2Scroll.clear();
table3Scroll.clear();
table4Scroll.clear();
});
return {
list1,
list2,
list3,
list4,
table1Ref,
table2Ref,
table3Ref,
table4Ref,
nowTime,
tableHeaderStyle,
tableCellStyle,
tableRowStyle
};
}
});
// 注册Element Plus
app.use(ElementPlus);
app.mount('#app');
</script>
</body>
</html>