三端对接完成
This commit is contained in:
parent
b22438134c
commit
482ec9a6f1
|
|
@ -236,3 +236,18 @@ export const getWindowStat = params => {
|
|||
params
|
||||
});
|
||||
};
|
||||
|
||||
// ==================== 大屏展示接口 ====================
|
||||
|
||||
/**
|
||||
* 大屏展示(当前呼叫 + 等候队列)
|
||||
* @param {*} params { calledSize, waitingSize }
|
||||
* @returns
|
||||
*/
|
||||
export const getDisplayScreen = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/display-screen',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/screen/index",
|
||||
"path": "pages/screen/screen",
|
||||
"style": {
|
||||
"navigationBarTitleText": "公告屏",
|
||||
"enablePullDownRefresh": false,
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 挂起提示条 -->
|
||||
<view class="suspend-bar" v-if="serviceStatus === 2">
|
||||
<text>窗口已挂起,无法进行叫号操作</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部功能按钮区 -->
|
||||
<view class="btn-group">
|
||||
<view class="btn-item green" @click="handleCall" :class="{ disabled: callDisabled }">
|
||||
|
|
@ -55,9 +50,14 @@
|
|||
<image class="btn-icon" src="../../static/images/takeTicket/gq_icon.png" mode="aspectFit" />
|
||||
<text>挂起</text>
|
||||
</view>
|
||||
<view class="btn-item green" @click="handleResume" v-if="serviceStatus === 2">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/hj_icon.png" mode="aspectFit" />
|
||||
<text>恢复</text>
|
||||
</view>
|
||||
|
||||
<!-- 挂起遮罩层 -->
|
||||
<view class="suspend-overlay" v-if="serviceStatus === 2">
|
||||
<text class="suspend-tip">窗口已挂起,无法进行叫号操作</text>
|
||||
<view class="resume-btn" @click="handleResume">
|
||||
<image class="resume-btn-icon" src="../../static/images/takeTicket/hj_icon.png" mode="aspectFit" />
|
||||
<text class="resume-btn-text">恢复</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -78,27 +78,11 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 挂起原因弹窗 -->
|
||||
<view class="transfer-mask" v-if="showSuspend" @click="showSuspend = false">
|
||||
<view class="suspend-dialog" @click.stop>
|
||||
<text class="dialog-title">请输入挂起原因</text>
|
||||
<input class="suspend-input" v-model="suspendReason" placeholder="请输入挂起原因(选填)" />
|
||||
<view class="suspend-btns">
|
||||
<view class="dialog-cancel" @click="showSuspend = false">
|
||||
<text>取消</text>
|
||||
</view>
|
||||
<view class="dialog-confirm" @click="confirmSuspend">
|
||||
<text>确认挂起</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getWindowWorkbench, callNext, recall, transferRecord, passRecord, suspendWindow, resumeWindow, getWindowList } from '@/api/ticket.js'
|
||||
import { getWindowWorkbench, callNext, recall, transferRecord, passRecord, suspendWindow, resumeWindow, getWindowList, finishHandle } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
name: 'CallWindow',
|
||||
|
|
@ -121,10 +105,6 @@ export default {
|
|||
showTransfer: false,
|
||||
targetWindowList: [],
|
||||
|
||||
// 挂起弹窗
|
||||
showSuspend: false,
|
||||
suspendReason: '',
|
||||
|
||||
// 操作锁(防止重复点击)
|
||||
actionLock: false
|
||||
}
|
||||
|
|
@ -136,29 +116,14 @@ export default {
|
|||
return this.currentRecord ? this.currentRecord.queueNo : '----'
|
||||
},
|
||||
|
||||
// 状态文字
|
||||
statusText() {
|
||||
if (!this.currentRecord) return ''
|
||||
const map = { 1: '等待办理', 2: '已叫号', 3: '已过号', 4: '已完成', 5: '已取消', 7: '办理中' }
|
||||
return map[this.currentRecord.status] || ''
|
||||
},
|
||||
|
||||
// 状态标签样式
|
||||
statusTagClass() {
|
||||
if (!this.currentRecord) return ''
|
||||
if (this.currentRecord.status === 2) return 'tag-called'
|
||||
if (this.currentRecord.status === 7) return 'tag-handling'
|
||||
return ''
|
||||
},
|
||||
|
||||
// 按钮禁用逻辑:挂起中全部禁用操作按钮
|
||||
suspended() {
|
||||
return this.serviceStatus === 2
|
||||
},
|
||||
|
||||
// 呼叫按钮:挂起中 或 已有当前记录时禁用
|
||||
// 呼叫按钮:挂起中 或 等候人数为0 或 操作锁时禁用
|
||||
callDisabled() {
|
||||
return this.suspended || !!this.currentRecord || this.actionLock
|
||||
return this.suspended || this.waitingCount === 0 || this.actionLock
|
||||
},
|
||||
|
||||
// 重呼按钮:挂起中 或 无当前记录 或 状态不是已叫号/办理中 时禁用
|
||||
|
|
@ -252,10 +217,25 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
// 呼叫下一位
|
||||
// 呼叫下一位(自动完成当前记录)
|
||||
async handleCall() {
|
||||
if (this.callDisabled) return
|
||||
this.actionLock = true
|
||||
|
||||
// 如果当前有记录,先自动完成
|
||||
if (this.currentRecord) {
|
||||
uni.showLoading({ title: '完成当前办理...', mask: true })
|
||||
try {
|
||||
await finishHandle({
|
||||
recordId: this.currentRecord.id,
|
||||
windowId: this.windowId
|
||||
})
|
||||
} catch (e) {
|
||||
// 完成失败不阻塞,继续呼叫(后端可能已处理)
|
||||
console.error('自动完成失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
uni.showLoading({ title: '呼叫中...', mask: true })
|
||||
try {
|
||||
const res = await callNext({ windowId: this.windowId })
|
||||
|
|
@ -380,21 +360,14 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
// 挂起 - 打开原因输入弹窗
|
||||
handleSuspend() {
|
||||
this.suspendReason = ''
|
||||
this.showSuspend = true
|
||||
},
|
||||
|
||||
// 确认挂起
|
||||
async confirmSuspend() {
|
||||
this.showSuspend = false
|
||||
// 挂起 - 直接挂起
|
||||
async handleSuspend() {
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '挂起中...', mask: true })
|
||||
try {
|
||||
const res = await suspendWindow({
|
||||
windowId: this.windowId,
|
||||
reason: this.suspendReason || '临时离岗'
|
||||
reason: '临时离岗'
|
||||
})
|
||||
if (res.success && res.data) {
|
||||
this.serviceStatus = res.data.serviceStatus
|
||||
|
|
@ -575,18 +548,26 @@ export default {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 挂起提示条 */
|
||||
.suspend-bar {
|
||||
width: 100%;
|
||||
background-color: #ff6633;
|
||||
padding: 2vh 0;
|
||||
text-align: center;
|
||||
/* 挂起全屏遮罩 */
|
||||
.suspend-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.suspend-bar text {
|
||||
font-size: 2.5vw;
|
||||
.suspend-tip {
|
||||
font-size: 3.125vw;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4vh;
|
||||
}
|
||||
|
||||
/* 底部按钮 */
|
||||
|
|
@ -643,6 +624,33 @@ export default {
|
|||
background-color: #ff6633;
|
||||
}
|
||||
|
||||
.resume-btn {
|
||||
width: 18vw;
|
||||
height: 22.222vh;
|
||||
border-radius: 1.667vw;
|
||||
background-color: #28c958;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.resume-btn:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.resume-btn-icon {
|
||||
width: 3.646vw;
|
||||
height: 3.646vw;
|
||||
margin-bottom: 1.667vh;
|
||||
}
|
||||
|
||||
.resume-btn-text {
|
||||
font-size: 3.021vw;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 按钮禁用态 */
|
||||
.btn-item.disabled {
|
||||
opacity: 0.4;
|
||||
|
|
@ -674,15 +682,6 @@ export default {
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.suspend-dialog {
|
||||
width: 45vw;
|
||||
background: #fff;
|
||||
border-radius: 2vw;
|
||||
padding: 4vh 3vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 3vw;
|
||||
font-weight: bold;
|
||||
|
|
@ -738,46 +737,11 @@ export default {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 挂起弹窗 */
|
||||
.suspend-input {
|
||||
width: 100%;
|
||||
height: 8vh;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 1vw;
|
||||
padding: 0 2vw;
|
||||
font-size: 2.2vw;
|
||||
margin-bottom: 3vh;
|
||||
}
|
||||
|
||||
.suspend-btns {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 3vw;
|
||||
}
|
||||
|
||||
.dialog-confirm {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 2.5vh 0;
|
||||
font-size: 2.5vw;
|
||||
background: #ff6633;
|
||||
color: #fff;
|
||||
border-radius: 1.5vw;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dialog-confirm:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.dialog-cancel {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 2.5vh 0;
|
||||
padding: 2vh 0;
|
||||
font-size: 2.5vw;
|
||||
background: #eee;
|
||||
color: #666;
|
||||
border-radius: 1.5vw;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
</view>
|
||||
|
||||
<!-- 公告屏 -->
|
||||
<view class="card" @click="goToPage('/pages/screen/index', '公告屏')">
|
||||
<view class="card" @click="goToPage('/pages/screen/screen', '公告屏')">
|
||||
<view class="card-icon-box screen-bg">
|
||||
<text class="card-icon-text screen-text">屏</text>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<view class="screen-wrap">
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="top-header">
|
||||
<text class="title-left">环江毛南族自治县政务服务中心</text>
|
||||
<text class="title-left">{{ screenTitle }}</text>
|
||||
<view class="title-right">
|
||||
<text>{{ dateStr }}</text>
|
||||
<text>{{ weekStr }} {{ timeStr }}</text>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
<text class="normal-text">请</text>
|
||||
<text class="yellow-text">{{ currCallNo }}</text>
|
||||
<text class="normal-text">到</text>
|
||||
<text class="yellow-text">{{ currWinNo }}号窗口</text>
|
||||
<text class="yellow-text">{{ currWinNo }}</text>
|
||||
</view>
|
||||
<!-- 左右双栏表格区域 -->
|
||||
<view class="table-box">
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
<text>请</text>
|
||||
<text class="row-no">{{ item.no }}</text>
|
||||
<text>到</text>
|
||||
<text class="row-no">{{ item.win }}号窗口</text>
|
||||
<text class="row-no">{{ item.win }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -46,88 +46,60 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getDisplayScreen } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
name: 'CallScreen',
|
||||
data() {
|
||||
return {
|
||||
// 大屏标题(来自接口)
|
||||
screenTitle: '环江毛南族自治县政务服务中心',
|
||||
// 实时日期时间
|
||||
dateStr: '',
|
||||
weekStr: '',
|
||||
timeStr: '',
|
||||
timer: null, // 定时器
|
||||
serverTimeOffset: 0, // 服务端时间与本地时间的差值(毫秒)
|
||||
clockTimer: null, // 时钟刷新定时器
|
||||
fetchTimer: null, // 数据轮询定时器
|
||||
// 顶部大字播报
|
||||
currCallNo: 'A010',
|
||||
currWinNo: '2',
|
||||
//左侧当前呼叫数据
|
||||
callList: [
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
},
|
||||
{
|
||||
no: 'A0009',
|
||||
win: '1'
|
||||
}
|
||||
],
|
||||
//右侧等候队列 三列一组
|
||||
waitList: [
|
||||
['A0001', 'A0002', 'A0003'],
|
||||
['A0004', 'A0005', 'A0006'],
|
||||
['A0001', 'A0001', 'A0001'],
|
||||
['A0001', 'A0001', 'A0001'],
|
||||
['A0001', 'A0001', 'A0001'],
|
||||
['A0001', 'A0001', 'A0001'],
|
||||
['A0001', 'A0001', 'A0001'],
|
||||
['A0001', 'A0001', 'A0001']
|
||||
]
|
||||
currCallNo: '',
|
||||
currWinNo: '',
|
||||
// 左侧当前呼叫列表
|
||||
callList: [],
|
||||
// 右侧等候队列(每行3个)
|
||||
waitList: []
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.getNowTime() // 首次赋值时间
|
||||
// 每秒刷新时间
|
||||
this.timer = setInterval(() => {
|
||||
this.getNowTime()
|
||||
}, 1000)
|
||||
// 首次加载数据(获取服务端时间后启动时钟)
|
||||
this.fetchDisplayData()
|
||||
// 定时轮询刷新叫号数据
|
||||
this.fetchTimer = setInterval(() => {
|
||||
this.fetchDisplayData()
|
||||
}, 5000)
|
||||
},
|
||||
onUnload() {
|
||||
// 销毁定时器防止内存泄漏
|
||||
clearInterval(this.timer)
|
||||
clearInterval(this.clockTimer)
|
||||
clearInterval(this.fetchTimer)
|
||||
},
|
||||
methods: {
|
||||
// 获取系统实时时间
|
||||
getNowTime() {
|
||||
const now = new Date()
|
||||
// 启动时钟(首次拿到 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 second = this.addZero(now.getSeconds())
|
||||
// 星期映射
|
||||
const weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
const week = weekArr[now.getDay()]
|
||||
|
||||
|
|
@ -135,9 +107,66 @@ export default {
|
|||
this.weekStr = week
|
||||
this.timeStr = `${hour}:${minute}`
|
||||
},
|
||||
// 数字补0
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -261,7 +290,9 @@ export default {
|
|||
}
|
||||
|
||||
.wait-row {
|
||||
justify-content: space-around;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.row-blue {
|
||||
Loading…
Reference in New Issue