|
|
@@ -109,12 +109,12 @@
|
|
|
'box-waiting': station.status === 'waiting',
|
|
|
'box-error': station.status === 'error',
|
|
|
'box-selected': selectedBox === station.stationCode,
|
|
|
- 'box-split': station.splitCount
|
|
|
+ 'box-split': station.splitCount && station.status !== 'error' && station.status !== 'waiting'
|
|
|
}"
|
|
|
@click="handleStationClick(station)"
|
|
|
>
|
|
|
- <!-- 分割的料箱 -->
|
|
|
- <template v-if="station.splitCount && station.subLocations">
|
|
|
+ <!-- 分割的料箱(异常/等待调箱状态不渲染分割) -->
|
|
|
+ <template v-if="station.splitCount && station.subLocations && station.status !== 'error' && station.status !== 'waiting'">
|
|
|
<div class="sub-grid" :style="getSubGridStyle(station.splitCount)">
|
|
|
<div
|
|
|
v-for="sub in station.subLocations"
|
|
|
@@ -129,7 +129,7 @@
|
|
|
></div>
|
|
|
</div>
|
|
|
</template>
|
|
|
- <!-- 普通站台 -->
|
|
|
+ <!-- 普通站台或异常状态 -->
|
|
|
<template v-else>
|
|
|
<span v-if="station.label" class="box-label">{{ station.label }}</span>
|
|
|
</template>
|
|
|
@@ -199,7 +199,7 @@ import { closeListener, openListener, scanInit } from '@/utils/keydownListener'
|
|
|
import { onMounted, onUnmounted, ref, reactive, nextTick } from 'vue'
|
|
|
import { showToast, showLoadingToast, closeToast } from 'vant'
|
|
|
import { useStore } from '@/store/modules/user'
|
|
|
-import { getWorkingDetailsByBox, getBoxSplitCode, boxInbound, reissueTask, type BoxRelatedMergeDetailsVO, type LocationMergeDetails } from '@/api/location/merge'
|
|
|
+import { getWorkingDetailsByBox, getBoxSplitCode, boxInbound, reissueTask, getBoxStatus, type BoxRelatedMergeDetailsVO, type LocationMergeDetails } from '@/api/location/merge'
|
|
|
import { getInventory, inventoryMovement } from '@/api/inventory'
|
|
|
import { showConfirmDialog } from 'vant'
|
|
|
|
|
|
@@ -222,6 +222,9 @@ const sourceLocation = ref('')
|
|
|
// 商品条码
|
|
|
const scanBarcode = ref('')
|
|
|
|
|
|
+// 轮询定时器
|
|
|
+let pollingTimer: ReturnType<typeof setInterval> | null = null
|
|
|
+
|
|
|
// 页面初始化
|
|
|
onMounted(() => {
|
|
|
openListener()
|
|
|
@@ -234,6 +237,7 @@ onMounted(() => {
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
closeListener()
|
|
|
+ stopPolling()
|
|
|
})
|
|
|
|
|
|
// 设置料箱号输入框焦点
|
|
|
@@ -472,6 +476,11 @@ const loadBoxData = async (code: string) => {
|
|
|
|
|
|
closeToast()
|
|
|
|
|
|
+ // 加载完成后检查是否需要启动轮询
|
|
|
+ if (hasWaitingBox()) {
|
|
|
+ startPolling()
|
|
|
+ }
|
|
|
+
|
|
|
// 加载完成后focus到源库位输入框
|
|
|
scanType.value = 2
|
|
|
focusSourceLocationInput()
|
|
|
@@ -734,8 +743,6 @@ const currentLocation = reactive({
|
|
|
|
|
|
// 点击站台处理
|
|
|
const handleStationClick = (station: StationItem) => {
|
|
|
- // 分割的料箱不处理,由子库位处理
|
|
|
- if (station.splitCount) return
|
|
|
// 离线状态不可点击
|
|
|
if (station.status === 'offline') return
|
|
|
// 异常状态弹出重新下发确认框
|
|
|
@@ -743,6 +750,8 @@ const handleStationClick = (station: StationItem) => {
|
|
|
showReissueConfirm(station)
|
|
|
return
|
|
|
}
|
|
|
+ // 分割的料箱不处理,由子库位处理
|
|
|
+ if (station.splitCount) return
|
|
|
// 其他状态正常选择
|
|
|
selectStation(station)
|
|
|
}
|
|
|
@@ -761,6 +770,86 @@ const showReissueConfirm = (station: StationItem) => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// 获取当前所有料箱编码列表
|
|
|
+const getBoxCodeList = (): string[] => {
|
|
|
+ return stationList.value
|
|
|
+ .filter(s => s.boxCode && s.status !== 'offline')
|
|
|
+ .map(s => s.boxCode!)
|
|
|
+}
|
|
|
+
|
|
|
+// 检查是否存在等待调箱的料箱
|
|
|
+const hasWaitingBox = (): boolean => {
|
|
|
+ return stationList.value.some(s => s.status === 'waiting')
|
|
|
+}
|
|
|
+
|
|
|
+// 局部更新料箱状态
|
|
|
+const refreshBoxStatus = async () => {
|
|
|
+ const boxCodeList = getBoxCodeList()
|
|
|
+ if (boxCodeList.length === 0) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await getBoxStatus(warehouse, boxCodeList)
|
|
|
+ const statusMap = res.data || {}
|
|
|
+
|
|
|
+ // 更新站台列表中的状态
|
|
|
+ stationList.value = stationList.value.map(station => {
|
|
|
+ if (!station.boxCode || !statusMap.hasOwnProperty(station.boxCode)) {
|
|
|
+ return station
|
|
|
+ }
|
|
|
+
|
|
|
+ const newBoxStatus = statusMap[station.boxCode]
|
|
|
+ const inventoryLocations = station.inventoryLocations || []
|
|
|
+
|
|
|
+ let status: StationItem['status'] = 'offline'
|
|
|
+ let label: string | undefined = undefined
|
|
|
+
|
|
|
+ if (newBoxStatus === 0 || newBoxStatus === 10) {
|
|
|
+ status = 'waiting'
|
|
|
+ label = '等待调箱'
|
|
|
+ } else if (newBoxStatus === 20) {
|
|
|
+ if (inventoryLocations.length === 0) {
|
|
|
+ status = 'emptyBox'
|
|
|
+ label = '空箱'
|
|
|
+ } else {
|
|
|
+ status = 'filled'
|
|
|
+ }
|
|
|
+ } else if (newBoxStatus === 30) {
|
|
|
+ status = 'offline'
|
|
|
+ } else if (newBoxStatus === 40) {
|
|
|
+ status = 'error'
|
|
|
+ label = '异'
|
|
|
+ }
|
|
|
+
|
|
|
+ return { ...station, status, label }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 检查是否需要继续轮询
|
|
|
+ if (hasWaitingBox()) {
|
|
|
+ startPolling()
|
|
|
+ } else {
|
|
|
+ stopPolling()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('刷新料箱状态失败', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 启动轮询
|
|
|
+const startPolling = () => {
|
|
|
+ if (pollingTimer) return // 已经在轮询中
|
|
|
+ pollingTimer = setInterval(() => {
|
|
|
+ refreshBoxStatus()
|
|
|
+ }, 10000) // 10秒
|
|
|
+}
|
|
|
+
|
|
|
+// 停止轮询
|
|
|
+const stopPolling = () => {
|
|
|
+ if (pollingTimer) {
|
|
|
+ clearInterval(pollingTimer)
|
|
|
+ pollingTimer = null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 执行重新下发任务
|
|
|
const doReissueTask = async (station: StationItem) => {
|
|
|
if (!station.boxCode) {
|
|
|
@@ -772,10 +861,10 @@ const doReissueTask = async (station: StationItem) => {
|
|
|
await reissueTask(warehouse, station.stationCode, station.boxCode)
|
|
|
closeToast()
|
|
|
showToast('重新下发成功')
|
|
|
- // 重新加载料箱数据
|
|
|
- if (boxCode.value) {
|
|
|
- loadBoxData(boxCode.value)
|
|
|
- }
|
|
|
+ // 局部刷新料箱状态
|
|
|
+ setTimeout(() => {
|
|
|
+ refreshBoxStatus()
|
|
|
+ }, 500)
|
|
|
} catch (error: any) {
|
|
|
closeToast()
|
|
|
showToast(error.message || '重新下发失败')
|
|
|
@@ -1096,13 +1185,13 @@ const submitMove = () => {
|
|
|
border-color: #e0b0b0;
|
|
|
}
|
|
|
|
|
|
- &.box-error {
|
|
|
+ &.box-error {
|
|
|
background: #ffcccc;
|
|
|
border-color: #ff6666;
|
|
|
+ cursor: pointer;
|
|
|
|
|
|
.box-label {
|
|
|
- color: #ff0000;
|
|
|
- font-weight: bold;
|
|
|
+ color: #cc0000;
|
|
|
}
|
|
|
}
|
|
|
|