personnel_management_mobile/pages/screen/screen.vue

308 lines
7.8 KiB
Vue
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.

<template>
<view class="screen-wrap">
<!-- 顶部标题栏 -->
<view class="top-header">
<text class="title-left">{{ screenTitle }}</text>
<view class="title-right">
<text>{{ dateStr }}</text>
<text>{{ weekStr }} {{ timeStr }}</text>
</view>
</view>
<!-- 中间大字播报区 -->
<view class="big-call">
<text class="normal-text"></text>
<text class="yellow-text">{{ currCallNo }}</text>
<text class="normal-text"></text>
<text class="yellow-text">{{ currWinNo }}</text>
</view>
<!-- 左右双栏表格区域 -->
<view class="table-box">
<!-- 当前呼叫 -->
<view class="table-left">
<view class="table-head">
<text>当前呼叫</text>
<text class="tip-text">(过号需重新取号)</text>
</view>
<view class="table-list">
<view class="table-row" v-for="(item, idx) in callList" :key="idx" :class="idx % 2 === 1 ? 'row-blue' : ''">
<text>请</text>
<text class="row-no">{{ item.no }}</text>
<text>到</text>
<text class="row-no">{{ item.win }}</text>
</view>
</view>
</view>
<!-- 右:等候办理 -->
<view class="table-right">
<view class="table-head">等候办理</view>
<view class="table-list">
<view class="table-row wait-row" v-for="(row, idx) in waitList" :key="idx" :class="idx % 2 === 1 ? 'row-blue' : ''">
<text v-for="(item, i) in row" :key="i">{{ item }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { getDisplayScreen } from '@/api/ticket.js'
export default {
name: 'CallScreen',
data() {
return {
// 大屏标题(来自接口)
screenTitle: '环江毛南族自治县政务服务中心',
// 实时日期时间
dateStr: '',
weekStr: '',
timeStr: '',
serverTimeOffset: 0, // 服务端时间与本地时间的差值(毫秒)
clockTimer: null, // 时钟刷新定时器
fetchTimer: null, // 数据轮询定时器
// 顶部大字播报
currCallNo: '',
currWinNo: '',
// 左侧当前呼叫列表
callList: [],
// 右侧等候队列每行3个
waitList: []
}
},
onLoad() {
// 首次加载数据(获取服务端时间后启动时钟)
this.fetchDisplayData()
// 定时轮询刷新叫号数据
this.fetchTimer = setInterval(() => {
this.fetchDisplayData()
}, 5000)
},
onUnload() {
clearInterval(this.clockTimer)
clearInterval(this.fetchTimer)
},
methods: {
// 启动时钟(首次拿到 serverTime 后调用)
startClock() {
clearInterval(this.clockTimer)
this.tick()
this.clockTimer = setInterval(() => {
this.tick()
}, 1000)
},
// 每秒走时
tick() {
// 服务端时间 + 本地已流逝的毫秒 = 当前展示时间
const now = this.serverTimeOffset ? new Date(Date.now() + this.serverTimeOffset) : new Date()
const year = now.getFullYear()
const month = this.addZero(now.getMonth() + 1)
const day = this.addZero(now.getDate())
const hour = this.addZero(now.getHours())
const minute = this.addZero(now.getMinutes())
const weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const week = weekArr[now.getDay()]
this.dateStr = `${year}${month}${day}`
this.weekStr = week
this.timeStr = `${hour}:${minute}`
},
addZero(num) {
return num < 10 ? '0' + num : num
},
// 获取大屏展示数据
fetchDisplayData() {
getDisplayScreen({ calledSize: 8, waitingSize: 24 })
.then(res => {
const data = res.data
if (!data) return
// 1. 标题
if (data.title) {
this.screenTitle = data.title
}
// 2. 服务端时间(首次计算偏移量后启动时钟)
if (data.serverTime && !this.serverTimeOffset) {
const serverTs = new Date(data.serverTime.replace(/-/g, '/')).getTime()
this.serverTimeOffset = serverTs - Date.now()
this.startClock()
}
// 3. 顶部大字播报(最新呼叫)
if (data.latestCall) {
this.currCallNo = data.latestCall.queueNo || ''
this.currWinNo = data.latestCall.windowName || ''
} else {
this.currCallNo = ''
this.currWinNo = ''
}
// 4. 左侧当前呼叫列表
if (data.callingList && Array.isArray(data.callingList)) {
this.callList = data.callingList.map(item => ({
no: item.queueNo || '',
win: item.windowName || ''
}))
} else {
this.callList = []
}
// 5. 右侧等候队列每行3个
if (data.waitingList && Array.isArray(data.waitingList)) {
const waitNos = data.waitingList.map(item => item.queueNo || '')
const rows = []
for (let i = 0; i < waitNos.length; i += 3) {
const row = waitNos.slice(i, i + 3)
while (row.length < 3) {
row.push('')
}
rows.push(row)
}
this.waitList = rows
} else {
this.waitList = []
}
})
.catch(err => {
console.error('获取大屏数据失败:', err)
})
}
}
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
/* 使用 vw/vh 自适应屏幕,设计基准 1920*1080 */
.screen-wrap {
width: 100vw;
height: 100vh;
background: #083378;
display: flex;
flex-direction: column;
overflow: hidden;
}
/*顶部蓝色栏 */
.top-header {
width: 100%;
height: 12.963vh; /* 140/1080*100 */
background: #167bff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2.604vw; /* 50/1920*100 */
box-sizing: border-box;
}
.title-left {
font-size: 3.229vw; /* 62/1920*100 */
color: #fff;
font-weight: bold;
}
.title-right {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.title-right text {
font-size: 2.083vw; /* 40/1920*100 */
color: #fff;
line-height: 4.63vh; /* 50/1080*100 */
}
/*中间大字叫号 */
.big-call {
height: 24.074vh; /* 260/1080*100 */
display: flex;
justify-content: center;
align-items: center;
gap: 1.563vw; /* 30/1920*100 */
}
.normal-text {
font-size: 6.25vw; /* 120/1920*100 */
color: #ffffff;
font-weight: bold;
}
.yellow-text {
font-size: 6.25vw; /* 120/1920*100 */
color: #ffef33;
font-weight: bold;
}
/*左右表格容器 */
.table-box {
flex: 1;
display: flex;
gap: 1.563vw; /* 30/1920*100 */
padding: 0 1.563vw 2.778vh; /* 0 30/1920*100 30/1080*100 */
box-sizing: border-box;
}
.table-left,
.table-right {
flex: 1;
display: flex;
flex-direction: column;
border-radius: 0.833vw; /* 16/1920*100 */
}
.table-head {
width: 100%;
height: 10.185vh; /* 110/1080*100 */
background: #167bff;
display: flex;
justify-content: center;
align-items: center;
font-size: 2.708vw; /* 52/1920*100 */
color: #fff;
font-weight: bold;
}
.tip-text {
font-size: 1.875vw; /* 36/1920*100 */
margin-left: 1.042vw; /* 20/1920*100 */
opacity: 0.9;
}
.table-list {
height: 60vh;
overflow-y: auto;
}
/*表格行样式 */
.table-row {
width: 100%;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
font-size: 2.813vw; /* 54/1920*100 */
background: #ffffff;
}
.wait-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
justify-items: center;
}
.row-blue {
background: #e6f0ff;
}
.row-no {
color: #0055ff;
font-weight: bold;
margin: 0 1.042vw; /* 20/1920*100 */
}
</style>