|
@@ -1,11 +1,14 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="merge-container">
|
|
<div class="merge-container">
|
|
|
<van-nav-bar
|
|
<van-nav-bar
|
|
|
- title="海康并库" left-arrow fixed placeholder @click-left="goBack">
|
|
|
|
|
|
|
+ title="海康并库" left-arrow fixed placeholder @click-left="goBack" @click-right="onDetailsClick">
|
|
|
<template #left>
|
|
<template #left>
|
|
|
<van-icon name="arrow-left" size="25" />
|
|
<van-icon name="arrow-left" size="25" />
|
|
|
<div style="color: #fff">返回</div>
|
|
<div style="color: #fff">返回</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+ <template #right>
|
|
|
|
|
+ <div style="color: #fff">详情</div>
|
|
|
|
|
+ </template>
|
|
|
</van-nav-bar>
|
|
</van-nav-bar>
|
|
|
<!-- 扫描输入框区域 -->
|
|
<!-- 扫描输入框区域 -->
|
|
|
<div class="scan-section">
|
|
<div class="scan-section">
|
|
@@ -106,6 +109,14 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <!-- 站点类型选择 -->
|
|
|
|
|
+ <div class="station-type-selector">
|
|
|
|
|
+ <van-radio-group v-model="selectedStationType" @change="handleStationTypeChange" direction="horizontal">
|
|
|
|
|
+ <van-radio name="shelf">上架站点</van-radio>
|
|
|
|
|
+ <van-radio name="return">退货缓存站点</van-radio>
|
|
|
|
|
+ </van-radio-group>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 料箱选择区域 -->
|
|
<!-- 料箱选择区域 -->
|
|
|
<div class="grid-section">
|
|
<div class="grid-section">
|
|
|
<div class="grid-container">
|
|
<div class="grid-container">
|
|
@@ -170,11 +181,14 @@
|
|
|
:style="{ maxHeight: '70%' }"
|
|
:style="{ maxHeight: '70%' }"
|
|
|
>
|
|
>
|
|
|
<div class="location-popup">
|
|
<div class="location-popup">
|
|
|
- <div class="popup-header">
|
|
|
|
|
- <span class="popup-title">库位信息</span>
|
|
|
|
|
- <van-icon name="cross" @click="showLocationPopup = false" />
|
|
|
|
|
- </div>
|
|
|
|
|
<div class="popup-content">
|
|
<div class="popup-content">
|
|
|
|
|
+ <!-- 推荐类型信息 -->
|
|
|
|
|
+ <div class="recommend-type-section">
|
|
|
|
|
+ <div class="recommend-type">
|
|
|
|
|
+ {{ currentLocation.recommendType === 'clear' ? '此库位推荐清空' : '此库位推荐保留' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <van-icon name="cross" @click="showLocationPopup = false" />
|
|
|
|
|
+ </div>
|
|
|
<div class="info-row">
|
|
<div class="info-row">
|
|
|
<span class="info-label">库位编号</span>
|
|
<span class="info-label">库位编号</span>
|
|
|
<span class="info-value">{{ currentLocation.id }}</span>
|
|
<span class="info-value">{{ currentLocation.id }}</span>
|
|
@@ -186,7 +200,7 @@
|
|
|
<!-- 推荐库位列表 -->
|
|
<!-- 推荐库位列表 -->
|
|
|
<div class="recommend-section">
|
|
<div class="recommend-section">
|
|
|
<div class="recommend-title">
|
|
<div class="recommend-title">
|
|
|
- {{ currentLocation.recommendType === 'clear' ? '推荐清空' : '推荐保留' }}
|
|
|
|
|
|
|
+ {{ currentLocation.recommendType === 'clear' ? '推荐目标库位列表' : '推荐来源库位列表' }}
|
|
|
</div>
|
|
</div>
|
|
|
<div v-if="currentLocation.relatedLocations.length > 0" class="recommend-list">
|
|
<div v-if="currentLocation.relatedLocations.length > 0" class="recommend-list">
|
|
|
<div
|
|
<div
|
|
@@ -206,6 +220,12 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</van-popup>
|
|
</van-popup>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 并库任务详情弹框 -->
|
|
|
|
|
+ <MergeTaskDetailsDialog ref="taskDetailsDialogRef"/>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 料箱选择弹框 -->
|
|
|
|
|
+ <BoxSelectionDialog ref="boxSelectionDialogRef" :box-list="currentBoxList" :warehouse="warehouse" @success="onBoxSelectionSuccess" />
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -219,6 +239,8 @@ import { getInventory, inventoryMovement } from '@/api/inventory'
|
|
|
import { boxAndStationUnbindTask } from '@/api/haikang'
|
|
import { boxAndStationUnbindTask } from '@/api/haikang'
|
|
|
import { showConfirmDialog } from 'vant'
|
|
import { showConfirmDialog } from 'vant'
|
|
|
import { getHeader, androidFocus, goBack, scanError, scanSuccess } from '@/utils/android'
|
|
import { getHeader, androidFocus, goBack, scanError, scanSuccess } from '@/utils/android'
|
|
|
|
|
+import MergeTaskDetailsDialog from './components/MergeTaskDetailsDialog.vue'
|
|
|
|
|
+import BoxSelectionDialog from './components/BoxSelectionDialog.vue'
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
getHeader()
|
|
getHeader()
|
|
@@ -244,6 +266,8 @@ const boxCode = ref('')
|
|
|
const sourceLocation = ref('')
|
|
const sourceLocation = ref('')
|
|
|
// 商品条码
|
|
// 商品条码
|
|
|
const scanBarcode = ref('')
|
|
const scanBarcode = ref('')
|
|
|
|
|
+// 选中的站点类型:'return'(退货缓存站点)或 'shelf'(上架站点)
|
|
|
|
|
+const selectedStationType = ref('return')
|
|
|
|
|
|
|
|
// 轮询定时器
|
|
// 轮询定时器
|
|
|
let pollingTimer: ReturnType<typeof setInterval> | null = null
|
|
let pollingTimer: ReturnType<typeof setInterval> | null = null
|
|
@@ -382,6 +406,16 @@ const onTargetLocationEnter = () => {
|
|
|
showToast(`已输入目标库位: ${productInfo.targetLocationNew}`)
|
|
showToast(`已输入目标库位: ${productInfo.targetLocationNew}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 处理站点类型切换
|
|
|
|
|
+const handleStationTypeChange = () => {
|
|
|
|
|
+ // 重新初始化站点(显示不同类型的站点)
|
|
|
|
|
+ initStations()
|
|
|
|
|
+ // 重新加载站点数据
|
|
|
|
|
+ if (boxCode.value) {
|
|
|
|
|
+ refreshBoxData()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 当前选中的库存数据(用于提交移库)
|
|
// 当前选中的库存数据(用于提交移库)
|
|
|
const currentInventoryData = ref<any>(null)
|
|
const currentInventoryData = ref<any>(null)
|
|
|
|
|
|
|
@@ -665,12 +699,19 @@ interface StationItem {
|
|
|
// 站台列表
|
|
// 站台列表
|
|
|
const stationList = ref<StationItem[]>([])
|
|
const stationList = ref<StationItem[]>([])
|
|
|
|
|
|
|
|
-// 初始化站台列表(12个站台,编号13-24)
|
|
|
|
|
|
|
+// 初始化站台列表(根据站点类型显示不同范围的站台)
|
|
|
const initStations = () => {
|
|
const initStations = () => {
|
|
|
- stationList.value = Array.from({ length: 12 }, (_, i) => {
|
|
|
|
|
- const num = String(i + 13).padStart(2, '0')
|
|
|
|
|
|
|
+ const stationRange = selectedStationType.value === 'return'
|
|
|
|
|
+ ? { start: 13, end: 24 } // 退货缓存站点
|
|
|
|
|
+ : { start: 1, end: 12 } // 上架站点
|
|
|
|
|
+
|
|
|
|
|
+ const { start, end } = stationRange
|
|
|
|
|
+ const length = end - start + 1
|
|
|
|
|
+
|
|
|
|
|
+ stationList.value = Array.from({ length }, (_, i) => {
|
|
|
|
|
+ const num = String(start + i).padStart(2, '0')
|
|
|
return {
|
|
return {
|
|
|
- id: i + 1,
|
|
|
|
|
|
|
+ id: start + i,
|
|
|
stationCode: `RLOCHK${num}A01011`,
|
|
stationCode: `RLOCHK${num}A01011`,
|
|
|
displayNumber: num,
|
|
displayNumber: num,
|
|
|
status: 'offline' as const
|
|
status: 'offline' as const
|
|
@@ -1112,6 +1153,24 @@ const confirmSelectLocation = async () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 并库任务详情弹框
|
|
|
|
|
+const taskDetailsDialogRef = ref<any>(null)
|
|
|
|
|
+// 点击详情按钮
|
|
|
|
|
+const onDetailsClick = () => {
|
|
|
|
|
+ taskDetailsDialogRef.value?.showDialog(warehouse)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 料箱选择弹框
|
|
|
|
|
+const boxSelectionDialogRef = ref<any>(null)
|
|
|
|
|
+// 当前可选择的料箱列表
|
|
|
|
|
+const currentBoxList = ref<string[]>([])
|
|
|
|
|
+// 料箱选择成功
|
|
|
|
|
+const onBoxSelectionSuccess = () => {
|
|
|
|
|
+ // 重置页面数据并聚焦到料箱输入框
|
|
|
|
|
+ resetAllData()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
// 根据SKU查询库存信息
|
|
// 根据SKU查询库存信息
|
|
|
const queryInventoryBySku = async (sku: string, location: string) => {
|
|
const queryInventoryBySku = async (sku: string, location: string) => {
|
|
|
try {
|
|
try {
|
|
@@ -1186,20 +1245,17 @@ const getTaskRecommendQty = (location: string): number => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 呼唤机器人
|
|
// 呼唤机器人
|
|
|
-const callRobot = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- showLoadingToast({ message: '正在呼唤机器人...', forbidClick: true })
|
|
|
|
|
- await boxInbound(warehouse)
|
|
|
|
|
- closeToast()
|
|
|
|
|
- scanSuccess()
|
|
|
|
|
- showToast('呼唤机器人成功')
|
|
|
|
|
- // 重置页面数据并聚焦到料箱输入框
|
|
|
|
|
- resetAllData()
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- closeToast()
|
|
|
|
|
- scanError()
|
|
|
|
|
- showToast(error.message || '呼唤机器人失败')
|
|
|
|
|
|
|
+const callRobot = () => {
|
|
|
|
|
+ // 获取当前所有料箱列表
|
|
|
|
|
+ currentBoxList.value = getBoxCodeList()
|
|
|
|
|
+
|
|
|
|
|
+ if (currentBoxList.value.length === 0) {
|
|
|
|
|
+ showToast('暂无需要回库的料箱')
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 显示选择Dialog
|
|
|
|
|
+ boxSelectionDialogRef.value?.showDialog()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 重新输入(不重置料箱号)
|
|
// 重新输入(不重置料箱号)
|
|
@@ -1321,6 +1377,27 @@ const submitMove = () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.station-type-selector {
|
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ padding: 8px 12px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+
|
|
|
|
|
+ .van-radio-group {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 13px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .van-button {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.info-table {
|
|
.info-table {
|
|
|
background: #fff;
|
|
background: #fff;
|
|
|
border: 1px solid #ddd;
|
|
border: 1px solid #ddd;
|
|
@@ -1620,7 +1697,27 @@ const submitMove = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.popup-content {
|
|
.popup-content {
|
|
|
- padding: 12px 0;
|
|
|
|
|
|
|
+ padding: 6px 0;
|
|
|
|
|
+
|
|
|
|
|
+ .recommend-type-section {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
|
+
|
|
|
|
|
+ .recommend-type {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ color: #1989fa;
|
|
|
|
|
+ text-align: left;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .van-icon {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
.info-row {
|
|
.info-row {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -1650,15 +1747,15 @@ const submitMove = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.recommend-section {
|
|
.recommend-section {
|
|
|
- margin-top: 12px;
|
|
|
|
|
- padding-top: 12px;
|
|
|
|
|
- border-top: 1px solid #eee;
|
|
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ padding-top: 6px;
|
|
|
|
|
|
|
|
.recommend-title {
|
|
.recommend-title {
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
color: #333;
|
|
color: #333;
|
|
|
margin-bottom: 8px;
|
|
margin-bottom: 8px;
|
|
|
|
|
+ text-align: left;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.recommend-list {
|
|
.recommend-list {
|