大屏监控、批量打印
Co-authored-by: Copilot <copilot@github.com>
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
28
src/components/countTo/index.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<span>{{ showNum }}</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
|
||||
const props = defineProps<{ value: number }>()
|
||||
const showNum = ref(0)
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(val) => {
|
||||
let start = 0
|
||||
const step = val / 30
|
||||
const timer = setInterval(() => {
|
||||
start += step
|
||||
if (start >= val) {
|
||||
showNum.value = val
|
||||
clearInterval(timer)
|
||||
} else {
|
||||
showNum.value = Math.floor(start)
|
||||
}
|
||||
}, 30)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
@ -68,12 +68,18 @@ export const constantRoutes = [{
|
||||
component: () => import('@/views/error/401'),
|
||||
hidden: true
|
||||
},
|
||||
// 大屏
|
||||
// 大屏统计
|
||||
{
|
||||
path: '/regional/statistics/overview',
|
||||
component: () => import('@/views/regional/statistics/overview/index'),
|
||||
hidden: true
|
||||
},
|
||||
// 大屏监控
|
||||
{
|
||||
path: '/regional/statistics/screenMonitor',
|
||||
component: () => import('@/views/regional/statistics/screenMonitor/index'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: Layout,
|
||||
|
||||
@ -307,8 +307,8 @@ const sizeChange = (page: { currentPage: number, pageSize: number }) => {
|
||||
|
||||
|
||||
const getDays = () => {
|
||||
// queryForm.st = dayjs().subtract(3, 'day').format('YYYY-MM-DD')
|
||||
queryForm.st = '2025-06-01'
|
||||
queryForm.st = dayjs().subtract(3, 'day').format('YYYY-MM-DD')
|
||||
// queryForm.st = '2025-06-01'
|
||||
queryForm.et = dayjs().format('YYYY-MM-DD')
|
||||
|
||||
}
|
||||
|
||||
226
src/views/liswork/batchPrint/index.vue
Normal file
@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="app-container ">
|
||||
<el-row :gutter="20" class="top-area">
|
||||
<el-col :span="16" class="top-left-col">
|
||||
<el-form :model="queryForm" label-width="100px" class="query-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="样本日期:">
|
||||
<el-date-picker v-model="queryForm.jyrq" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
placeholder="选择日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="组别:">
|
||||
<SelectTable v-model:data="queryForm.instrGroup" :tableData="instrGroupOptions" placeholder=""
|
||||
@getDataValue="handleinstrGroupChange" :clearable="false" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="检验仪器:">
|
||||
<SelectTable v-model:data="queryForm.yq" :tableData="instrOptions" label="yqmc" value="yq" objKey="yq"
|
||||
placeholder="" :clearable="false" @getDataValue="" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="样本号:">
|
||||
<el-input v-model="queryForm.ybh" placeholder="请输入样本号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="病人类型:">
|
||||
<SelectTable v-model:data="queryForm.brly" dictType="PT" placeholder="" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="科室:">
|
||||
<SelectTable v-model:data="queryForm.ksdh" dictType="DP" placeholder="" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-form-item label="打印顺序:" class="print-order-item">
|
||||
<el-radio-group v-model="queryForm.printOrder">
|
||||
<el-radio v-for="order in printOrders" :key="order.value" :label="order.value">
|
||||
{{ order.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="8" class="top-right-col">
|
||||
<div class="option-panel">
|
||||
<div class="option-title">过滤选项</div>
|
||||
<el-checkbox-group v-model="selectedOptions" @change="updateSelectedOptions">
|
||||
<el-row :gutter="12" class="option-list">
|
||||
<el-col :span="12" v-for="option in optionItems" :key="option.key">
|
||||
<el-checkbox :label="option.key">{{ option.label }}</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="bottom-card mt10">
|
||||
<div class="table-section">
|
||||
<el-table :data="tableData" border style="width: 100%" height="50vh">
|
||||
<el-table-column label="样本号" prop="ybh" width="120" />
|
||||
<el-table-column label="病人姓名" prop="brxm" width="120" />
|
||||
<el-table-column label="病人类型" prop="brly" width="120" />
|
||||
<el-table-column label="科室" prop="ksmc" width="120" />
|
||||
<el-table-column label="床号" prop="ch" width="120" />
|
||||
<el-table-column label="消息提示" prop="msg" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" @click="submitHandle">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getComDicts } from '@/api/liswork/dict/ComDict';
|
||||
import { getGroupInstrdList } from '@/api/liswork/work/LisWork';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const queryForm = reactive({
|
||||
jyrq: '',
|
||||
instrGroup: '',
|
||||
yq: '',
|
||||
ybh: '',
|
||||
brly: '',
|
||||
ksdh: '',
|
||||
printOrder: 'ybh',
|
||||
options: {
|
||||
excludePatientType: false,
|
||||
excludeDept: false,
|
||||
excludeNegative: false,
|
||||
positiveOnly: false,
|
||||
noNameSkip: false,
|
||||
noResultSkip: false,
|
||||
groupedPrint: false,
|
||||
notPrintedOnly: false,
|
||||
pendingReview: false,
|
||||
reviewedOnly: false
|
||||
}
|
||||
});
|
||||
|
||||
const tableData = ref([]);
|
||||
|
||||
const printOrders = ref([
|
||||
{ label: '样本号', value: 'ybh' },
|
||||
{ label: '科室+床号+样本号', value: 'deptBedSample' },
|
||||
{ label: '病人类型+科室+床号+样本号', value: 'typeDeptBedSample' },
|
||||
{ label: '病人类型+科室+样本号', value: 'typeDeptSample' },
|
||||
{ label: '阳性结果', value: 'positiveResult' }
|
||||
]);
|
||||
const optionItems = ref([
|
||||
{ label: '排除选择的病人类型', key: 'excludePatientType' },
|
||||
{ label: '排除选择的科室', key: 'excludeDept' },
|
||||
{ label: '排除阴性报告', key: 'excludeNegative' },
|
||||
{ label: '仅打印阳性报告', key: 'positiveOnly' },
|
||||
{ label: '无病人姓名不打印', key: 'noNameSkip' },
|
||||
{ label: '无检验结果不打印', key: 'noResultSkip' },
|
||||
{ label: '分组打印报告', key: 'groupedPrint' },
|
||||
{ label: '打印未打印报告', key: 'notPrintedOnly' },
|
||||
{ label: '打印待核报告', key: 'pendingReview' },
|
||||
{ label: '打印已审核报告', key: 'reviewedOnly' }
|
||||
]);
|
||||
|
||||
const selectedOptions = ref(Object.keys(queryForm.options).filter(key => queryForm.options[key]));
|
||||
|
||||
const updateSelectedOptions = () => {
|
||||
Object.keys(queryForm.options).forEach(key => {
|
||||
queryForm.options[key] = selectedOptions.value.includes(key);
|
||||
});
|
||||
}
|
||||
|
||||
const submitHandle = () => {
|
||||
|
||||
}
|
||||
|
||||
const handleinstrGroupChange = () => {
|
||||
queryForm.yq = ''
|
||||
getYqConfig()
|
||||
}
|
||||
|
||||
const instrGroupOptions = ref<{ value: string, label: string }[]>([])
|
||||
const instrOptions = ref<{ value: string, label: string }[]>([])
|
||||
|
||||
const getYqConfig = () => {
|
||||
getGroupInstrdList({ lisgroup: queryForm.instrGroup })
|
||||
.then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
instrOptions.value = res.data.map((item: any) => ({
|
||||
value: item.yq.trim(),
|
||||
label: item.yqmc
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getComDicts({ zdlb: 'GROUP' }).then((res: any) => {
|
||||
instrGroupOptions.value = res.data.map((item: any) => ({
|
||||
value: item.zddh.trim(),
|
||||
label: item.zdmc
|
||||
}))
|
||||
instrGroupOptions.value.push({ value: 'ALL', label: '所有仪器' })
|
||||
getYqConfig()
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.query-form {
|
||||
.el-form-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.option-panel {
|
||||
padding: 5px 12px;
|
||||
background: #f8fbff;
|
||||
border: 1px solid #d9e8fb;
|
||||
border-radius: 8px;
|
||||
|
||||
.option-title {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
padding-left: 10px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 3px;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
background: #3282F6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-card {
|
||||
border-top: 1px solid #d9e8fb;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@ -5,7 +5,7 @@
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: url(../images/bg2.jpg) no-repeat;
|
||||
background: url('../../../../../assets/images/bg2.jpg') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
padding-top: 0rem;
|
||||
padding: 0rem 3.125rem;
|
||||
@ -31,7 +31,7 @@
|
||||
width: 5.78125rem;
|
||||
height: 0.78125rem;
|
||||
display: block;
|
||||
background: #01279d url(../images/title_left_bg.png) no-repeat;
|
||||
background: #01279d url('../../../../../assets/images/title_left_bg.png') no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
width: 1.5625rem;
|
||||
height: 1.5625rem;
|
||||
display: block;
|
||||
background: url(../images/border_bg.jpg) no-repeat;
|
||||
background: url('../../../../../assets/images/border_bg.jpg') no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
width: 1.5625rem;
|
||||
height: 1.5625rem;
|
||||
display: block;
|
||||
background: url(../images/border_bg.jpg) no-repeat;
|
||||
background: url('../../../../../assets/images/border_bg.jpg') no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: block;
|
||||
background: url(../images/title_right_bg.png) no-repeat;
|
||||
background: url('../../../../../assets/images/title_right_bg.png') no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
430
src/views/regional/statistics/screenMonitor/index.vue
Normal file
@ -0,0 +1,430 @@
|
||||
<template>
|
||||
<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">共
|
||||
<CountTo :value="list1.length" />个标本
|
||||
</span>
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<el-table :data="list1" border stripe header-cell-class-name="table-header" class="table" height="35vh"
|
||||
ref="table1Ref" :header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle"
|
||||
:row-style="tableRowStyle">
|
||||
<el-table-column prop="dept" label="科室" />
|
||||
<el-table-column prop="name" label="姓名" />
|
||||
<el-table-column prop="item" label="标本/项目" />
|
||||
<el-table-column prop="time" label="采样/送检时间" />
|
||||
</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">共
|
||||
<CountTo :value="list2.length" />个标本
|
||||
</span>
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<el-table :data="list2" border stripe header-cell-class-name="table-header" class="table" height="35vh"
|
||||
ref="table2Ref" :header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle"
|
||||
:row-style="tableRowStyle">
|
||||
<el-table-column prop="barcode" label="条码" />
|
||||
<el-table-column prop="name" label="姓名" />
|
||||
<el-table-column prop="item" label="检查项目" />
|
||||
<el-table-column prop="time" label="签收时间" />
|
||||
</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 header-cell-class-name="table-header" class="table" height="35vh"
|
||||
ref="table3Ref" :header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle"
|
||||
:row-style="tableRowStyle">
|
||||
<el-table-column prop="machine" label="仪器" />
|
||||
<el-table-column prop="sampleNo" label="样本号" />
|
||||
<el-table-column prop="item" label="检查项目" />
|
||||
<el-table-column prop="time" label="签收时间" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="{ row }">
|
||||
<span :class="row.status === '超时' ? 'timeout' : ''">
|
||||
{{ row.status == '超时' ? `剩${row.Timeout}超时` : '' }}
|
||||
</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 header-cell-class-name="table-header" class="table" height="35vh"
|
||||
ref="table4Ref" :header-cell-style="tableHeaderStyle" :cell-style="tableCellStyle"
|
||||
:row-style="tableRowStyle">
|
||||
<el-table-column prop="machine" label="仪器" />
|
||||
<el-table-column prop="sampleNo" label="样本号" />
|
||||
<el-table-column prop="item" label="项目" />
|
||||
<el-table-column prop="result" label="结果" />
|
||||
<el-table-column prop="confirm" label="确认超时" />
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import CountTo from '@/components/countTo/index.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { templateRef } from '@vueuse/core'
|
||||
import { set } from 'lodash'
|
||||
// 填充模拟数据(保持原有逻辑)
|
||||
const list1 = ref([
|
||||
{ dept: '1111', name: '张三', item: '血常规', time: '2024-05-20 08:15:30' },
|
||||
{ dept: '呼吸内科', name: '李四', item: '生化全套', time: '2024-05-20 09:20:15' },
|
||||
{ dept: '心内科', name: '王五', item: '凝血功能', time: '2024-05-20 10:05:40' },
|
||||
{ dept: '消化内科', name: '赵六', item: '尿常规', time: '2024-05-20 11:10:25' },
|
||||
{ dept: '神经内科', name: '孙七', item: '脑脊液', time: '2024-05-20 12:00:10' },
|
||||
{ dept: 'patient', name: '周八', item: '肾功能', time: '2024-05-20 13:00:00' },
|
||||
{ dept: 'patient', name: '王八', item: '肝功能', time: '2024-05-20 13:15:30' },
|
||||
{ dept: '急诊科', name: '张三', item: '血常规', time: '2024-05-20 08:15:30' },
|
||||
{ dept: '呼吸内科', name: '李四', item: '生化全套', time: '2024-05-20 09:20:15' },
|
||||
{ dept: '心内科', name: '王五', item: '凝血功能', time: '2024-05-20 10:05:40' },
|
||||
{ dept: '消化内科', name: '赵六', item: '尿常规', time: '2024-05-20 11:10:25' },
|
||||
{ dept: '神经内科', name: '孙七', item: '脑脊液', time: '2024-05-20 12:00:10' },
|
||||
{ dept: 'patient', name: '周八', item: '肾功能', time: '2024-05-20 13:00:00' },
|
||||
{ dept: '完结', name: '王八', item: '肝功能', time: '2024-05-20 13:15:30' },
|
||||
])
|
||||
|
||||
const list2 = ref([
|
||||
{ barcode: 'start', name: '周八', item: '肝功能', time: '2024-05-20 08:30:00' },
|
||||
{ barcode: '8800123457', name: '吴九', item: '肾功能', time: '2024-05-20 09:10:00' },
|
||||
{ barcode: '8800123458', name: '郑十', item: '电解质', time: '2024-05-20 10:20:00' },
|
||||
{ barcode: '8800123459', name: '钱十一', item: '血糖', time: '2024-05-20 11:05:00' },
|
||||
{ barcode: '8800123456', name: '周八', item: '肝功能', time: '2024-05-20 08:30:00' },
|
||||
{ barcode: '8800123457', name: '吴九', item: '肾功能', time: '2024-05-20 09:10:00' },
|
||||
{ barcode: '8800123458', name: '郑十', item: '电解质', time: '2024-05-20 10:20:00' },
|
||||
{ barcode: '8800123459', name: '钱十一', item: '血糖', time: '2024-05-20 11:05:00' },
|
||||
{ barcode: '8800123456', name: '周八', item: '肝功能', time: '2024-05-20 08:30:00' },
|
||||
{ barcode: '8800123457', name: '吴九', item: '肾功能', time: '2024-05-20 09:10:00' },
|
||||
{ barcode: '8800123458', name: '郑十', item: '电解质', time: '2024-05-20 10:20:00' },
|
||||
{ barcode: 'end', name: '钱十一', item: '血糖', time: '2024-05-20 11:05:00' },
|
||||
])
|
||||
|
||||
const list3 = ref([
|
||||
{ machine: 'start', sampleNo: 'S20240520001', item: '血常规', time: '2024-05-20 07:15:00', status: '正常', Timeout: '15分钟' },
|
||||
{ machine: '罗氏Cobas 8000', sampleNo: 'S20240520002', item: '生化全套', time: '2024-05-20 08:20:00', status: '超时', Timeout: '20分钟' },
|
||||
{ machine: '希森美康XN-9000', sampleNo: 'S20240520003', item: '凝血功能', time: '2024-05-20 09:00:00', status: '正常', Timeout: '10分钟' },
|
||||
{ machine: '雅培i2000', sampleNo: 'S20240520004', item: '肿瘤标志物', time: '2024-05-20 10:10:00', status: '超时', Timeout: '25分钟' },
|
||||
{ machine: '贝克曼AU5800', sampleNo: 'S20240520001', item: '血常规', time: '2024-05-20 07:15:00', status: '正常', Timeout: '15分钟' },
|
||||
])
|
||||
|
||||
const list4 = ref([
|
||||
{ machine: '贝克曼AU5800', sampleNo: 'S20240520010', item: '血钾', result: '7.8mmol/L', confirm: '15分钟' },
|
||||
{ machine: '罗氏Cobas 8000', sampleNo: 'S20240520011', item: '血糖', result: '28.5mmol/L', confirm: '10分钟' },
|
||||
{ machine: '希森美康XN-9000', sampleNo: 'S20240520012', item: '血小板', result: '25×10^9/L', confirm: '20分钟' },
|
||||
])
|
||||
|
||||
// 表格样式配置(贴合大屏蓝色背景)
|
||||
const tableHeaderStyle = {
|
||||
background: 'rgba(30, 104, 195, 0.8)', // 表头半透深蓝(匹配截图表头)
|
||||
color: '#ffffff', // 表头文字白色
|
||||
fontSize: '16px', // 表头字体偏大
|
||||
fontWeight: 'bold', // 表头加粗
|
||||
borderColor: '#0099ff' // 表头边框浅蓝
|
||||
}
|
||||
|
||||
const tableCellStyle = {
|
||||
background: 'transparent', // 单元格完全透明(继承大屏背景)
|
||||
color: '#ffffff', // 单元格文字白色
|
||||
fontSize: '16px', // 单元格字体清晰
|
||||
borderColor: '#0099ff' // 单元格边框浅蓝(区分度高)
|
||||
}
|
||||
|
||||
const tableRowStyle = ({ rowIndex }: { rowIndex: number }) => {
|
||||
// 斑马纹用极浅的半透蓝(贴合背景,无灰白)
|
||||
return {
|
||||
background: rowIndex % 2 === 0 ? 'transparent' : 'rgba(0, 153, 255, 0.1)',
|
||||
hover: 'rgba(0, 153, 255, 0.2)' // 悬浮行浅蓝高亮
|
||||
}
|
||||
}
|
||||
const table1Ref = templateRef('table1Ref')
|
||||
const table2Ref = templateRef('table2Ref')
|
||||
const table3Ref = templateRef('table3Ref')
|
||||
const table4Ref = templateRef('table4Ref')
|
||||
|
||||
// 封装滚动函数,接收表格ref和数据列表(用于判断是否需要刷新)
|
||||
const createTableScroll = (tableRef: Ref, dataList: Ref) => {
|
||||
let scrollTimer: any = null;
|
||||
let refreshTimer: any = null;
|
||||
const clear = () => {
|
||||
clearInterval(scrollTimer);
|
||||
clearInterval(refreshTimer);
|
||||
scrollTimer = null;
|
||||
refreshTimer = null;
|
||||
};
|
||||
|
||||
|
||||
const start = () => {
|
||||
clear();
|
||||
if (!tableRef.value) return;
|
||||
|
||||
const table = tableRef.value.layout.table.refs;
|
||||
const tableWrapper = table.bodyWrapper.firstElementChild?.firstElementChild;
|
||||
if (!tableWrapper) return;
|
||||
// 只有当内容超出可视区域时才启动滚动和定时刷新 异步判断(确保DOM渲染完成)
|
||||
setTimeout(() => {
|
||||
if (tableWrapper.clientHeight == tableWrapper.scrollHeight) {
|
||||
// 内容未超出可视区域,无需滚动和定时刷新
|
||||
clear()
|
||||
refreshTimer = setInterval(() => {
|
||||
refreshSingleTableData(dataList);
|
||||
}, 5000);
|
||||
}
|
||||
}, 50);
|
||||
scrollTimer = setInterval(() => {
|
||||
tableWrapper.scrollTop += 1;
|
||||
// 仅当前表格滚到底时,刷新当前表格数据(而非全部)
|
||||
if (tableWrapper.clientHeight + tableWrapper.scrollTop == tableWrapper.scrollHeight) {
|
||||
tableWrapper.scrollTop = 0;
|
||||
// 按需刷新单个表格数据,而非全局refreshData
|
||||
refreshSingleTableData(dataList);
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
return { start, clear };
|
||||
};
|
||||
|
||||
// 每个表格独立实例化滚动
|
||||
const table1Scroll = createTableScroll(table1Ref, list1);
|
||||
const table2Scroll = createTableScroll(table2Ref, list2);
|
||||
const table3Scroll = createTableScroll(table3Ref, list3);
|
||||
const table4Scroll = createTableScroll(table4Ref, list4);
|
||||
|
||||
// 单个表格数据刷新(避免全局刷新)
|
||||
const refreshSingleTableData = (dataList: Ref) => {
|
||||
// console.log(`刷新表格数据: ${dataList === list1 ? 'list1' : dataList === list2 ? 'list2' : dataList === list3 ? 'list3' : 'list4'}`);
|
||||
if (dataList === list1) {
|
||||
// list1.value = 新数据(保留原有滚动位置逻辑)
|
||||
}
|
||||
};
|
||||
|
||||
// 定时刷新
|
||||
let timeTimer: any
|
||||
|
||||
// 动态时间
|
||||
const nowTime = ref('')
|
||||
const updateTime = () => {
|
||||
nowTime.value = dayjs().format('YYYY年MM月DD日 HH:mm:ss')
|
||||
}
|
||||
|
||||
// 挂载/卸载时独立控制
|
||||
onMounted(async () => {
|
||||
updateTime();
|
||||
timeTimer = setInterval(updateTime, 1000);
|
||||
await nextTick()
|
||||
table1Scroll.start();
|
||||
table2Scroll.start();
|
||||
table3Scroll.start();
|
||||
table4Scroll.start();
|
||||
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timeTimer);
|
||||
table1Scroll.clear();
|
||||
table2Scroll.clear();
|
||||
table3Scroll.clear();
|
||||
table4Scroll.clear();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.screen-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: url(@/assets/images/bg2.jpg);
|
||||
background-size: 100% 100%;
|
||||
padding: 20px 40px 20px 50px;
|
||||
}
|
||||
|
||||
.screen-header {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.screen-title {
|
||||
font-size: 1.875rem;
|
||||
color: rgba(14, 253, 255, 1);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.screen-time {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
font-size: 20px;
|
||||
color: #0ef;
|
||||
font-weight: 700;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.grid-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
margin-top: 35px;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
background: transparent;
|
||||
border: 1px solid #0efdff80;
|
||||
padding: 10px 20px 20px;
|
||||
height: 42vh;
|
||||
}
|
||||
|
||||
.border_bg_leftTop {
|
||||
position: absolute;
|
||||
left: -0.125rem;
|
||||
top: -0.625rem;
|
||||
width: 5.78125rem;
|
||||
height: 0.78125rem;
|
||||
display: block;
|
||||
background: #01279d url(@/assets/images/title_left_bg.png) no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.border_bg_rightTop {
|
||||
position: absolute;
|
||||
right: -0.15625rem;
|
||||
top: -0.15625rem;
|
||||
width: 1.5625rem;
|
||||
height: 1.5625rem;
|
||||
display: block;
|
||||
background: url(@/assets/images/border_bg.jpg) no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.border_bg_leftBottom {
|
||||
position: absolute;
|
||||
left: -0.125rem;
|
||||
bottom: -0.125rem;
|
||||
width: 1.5625rem;
|
||||
height: 1.5625rem;
|
||||
display: block;
|
||||
background: url(@/assets/images/border_bg.jpg) no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.border_bg_rightBottom {
|
||||
position: absolute;
|
||||
right: -0.15625rem;
|
||||
bottom: -0.15625rem;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: block;
|
||||
background: url(@/assets/images/title_right_bg.png) no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
:deep(.div__body) {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.red-text {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.red-title {
|
||||
color: #ff4d4f !important;
|
||||
}
|
||||
|
||||
|
||||
/* 表格全局样式重置 */
|
||||
:deep(.table) {
|
||||
--el-table-bg-color: transparent;
|
||||
--el-table-border-color: #0099ff;
|
||||
--el-table-row-hover-bg-color: rgba(0, 153, 255, 0.2);
|
||||
--el-table--striped-row-bg-color: rgba(0, 153, 255, 0.1);
|
||||
}
|
||||
|
||||
/* 移除Element默认的表格背景/边框样式 */
|
||||
:deep(.el-table) {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
:deep(.el-table th) {
|
||||
border-right: 1px solid #0099ff !important;
|
||||
}
|
||||
|
||||
:deep(.el-table td) {
|
||||
border-right: 1px solid #0099ff !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
.timeout {
|
||||
color: #00ff00;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
</style>
|
||||