<template>
|
<div class="picking-confirm">
|
<div class="page-header">
|
<el-page-header @back="goBack">
|
<template #content>
|
<span class="title">出库拣选确认 - {{ orderInfo.orderNo }}</span>
|
</template>
|
</el-page-header>
|
</div>
|
|
<el-row :gutter="20" class="main-content">
|
<el-col :span="8">
|
<div class="scan-section">
|
<el-card header="扫码区域">
|
<el-form label-width="100px" size="small">
|
<el-form-item label="托盘条码">
|
<el-input
|
v-model="scanForm.palletCode"
|
placeholder="扫描或输入托盘条码"
|
@keyup.enter="handlePalletScan"
|
clearable
|
>
|
<template #append>
|
<el-button @click="handlePalletScan">确认</el-button>
|
</template>
|
</el-input>
|
</el-form-item>
|
|
<el-form-item label="物料条码">
|
<el-input
|
v-model="scanForm.barcode"
|
placeholder="扫描或输入物料条码"
|
@keyup.enter="handleBarcodeScan"
|
:disabled="!currentPallet"
|
clearable
|
>
|
<template #append>
|
<el-button @click="handleBarcodeScan" :disabled="!currentPallet">确认</el-button>
|
</template>
|
</el-input>
|
</el-form-item>
|
|
<el-form-item label="拣选数量">
|
<el-input-number
|
v-model="scanForm.quantity"
|
:min="1"
|
:max="maxPickQuantity"
|
:disabled="!currentLockInfo"
|
/>
|
</el-form-item>
|
</el-form>
|
|
<div class="current-info" v-if="currentPallet">
|
<p>当前托盘: {{ currentPallet.palletCode }}</p>
|
<p>货位: {{ currentPallet.locationCode }}</p>
|
<p>状态: {{ currentPallet.statusText }}</p>
|
</div>
|
</el-card>
|
|
<div class="action-buttons">
|
<el-button
|
type="warning"
|
@click="handleBackToStock"
|
:disabled="!currentPallet"
|
style="margin-bottom: 10px;"
|
>
|
回库
|
</el-button>
|
<el-button
|
type="success"
|
@click="handleDirectOutbound"
|
:disabled="!currentPallet"
|
style="margin-bottom: 10px;"
|
>
|
直接出库
|
</el-button>
|
<el-button
|
type="primary"
|
@click="handleOpenSplit"
|
:disabled="!currentLockInfo"
|
>
|
拆包
|
</el-button>
|
</div>
|
</div>
|
</el-col>
|
|
<el-col :span="16">
|
<el-card header="拣选结果">
|
<div class="summary-info">
|
<el-alert
|
:title="`未拣货: ${unpickedCount} 条, ${unpickedQuantity} 个`"
|
type="warning"
|
:closable="false"
|
/>
|
</div>
|
|
<vol-table
|
:data="pickedList"
|
:columns="pickedColumns"
|
:pagination="false"
|
:height="400"
|
>
|
<template #action="{ row }">
|
<el-button type="text" @click="handleCancelPick(row)">撤销</el-button>
|
</template>
|
</vol-table>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 拆包弹窗 -->
|
<vol-box
|
v-model="splitVisible"
|
title="拆包操作"
|
:width="600"
|
:height="500"
|
>
|
<SplitPackageModal
|
v-if="splitVisible"
|
:lockInfo="currentLockInfo"
|
@success="handleSplitSuccess"
|
@close="splitVisible = false"
|
/>
|
</vol-box>
|
</div>
|
</template>
|
|
<script>
|
import SplitPackageModal from './SplitPackageModal.vue'
|
|
export default {
|
components: { SplitPackageModal },
|
data() {
|
return {
|
orderInfo: {},
|
scanForm: {
|
palletCode: '',
|
barcode: '',
|
quantity: 1
|
},
|
currentPallet: null,
|
currentLockInfo: null,
|
pickedList: [],
|
pickedColumns: [
|
{ field: 'barcode', title: '物料条码', width: 150 },
|
{ field: 'materielCode', title: '物料编码', width: 120 },
|
{ field: 'materielName', title: '物料名称', width: 150 },
|
{ field: 'pickQuantity', title: '拣选数量', width: 100 },
|
{ field: 'palletCode', title: '托盘编号', width: 120 },
|
{ field: 'pickTime', title: '拣选时间', width: 160 },
|
{ field: 'operator', title: '操作人', width: 100 },
|
{ field: 'action', title: '操作', width: 80, slot: true }
|
],
|
splitVisible: false,
|
maxPickQuantity: 0
|
}
|
},
|
computed: {
|
unpickedCount() {
|
return this.orderInfo.unpickedCount || 0
|
},
|
unpickedQuantity() {
|
return this.orderInfo.unpickedQuantity || 0
|
}
|
},
|
methods: {
|
goBack() {
|
this.$router.back()
|
},
|
|
async loadOrderInfo() {
|
const orderId = this.$route.query.orderId
|
if (!orderId) return
|
|
try {
|
const result = await this.http.post(`api/OutboundOrder/GetById?id=${orderId}`)
|
if (result.status) {
|
this.orderInfo = result.data
|
}
|
} catch (error) {
|
this.$message.error('加载出库单信息失败')
|
}
|
},
|
|
async handlePalletScan() {
|
if (!this.scanForm.palletCode) {
|
this.$message.warning('请输入托盘条码')
|
return
|
}
|
|
try {
|
const result = await this.http.get(
|
`api/OutboundPicking/GetPalletOutboundStatus?palletCode=${this.scanForm.palletCode}`
|
)
|
if (result.status) {
|
this.currentPallet = result.data
|
this.loadPalletLockInfo()
|
this.$message.success(`托盘 ${this.scanForm.palletCode} 识别成功`)
|
} else {
|
this.$message.error(result.message)
|
}
|
} catch (error) {
|
this.$message.error('托盘识别失败')
|
}
|
},
|
|
async loadPalletLockInfo() {
|
if (!this.currentPallet) return
|
|
try {
|
const result = await this.http.get(
|
`api/OutboundPicking/GetPalletLockInfos?palletCode=${this.currentPallet.palletCode}`
|
)
|
if (result.status && result.data.length > 0) {
|
this.currentLockInfo = result.data[0]
|
this.maxPickQuantity = this.currentLockInfo.assignQuantity - this.currentLockInfo.pickedQty
|
}
|
} catch (error) {
|
console.error('加载锁定信息失败:', error)
|
}
|
},
|
|
async handleBarcodeScan() {
|
// 实现扫码确认逻辑
|
if (!this.scanForm.barcode) {
|
this.$message.warning('请输入物料条码')
|
return
|
}
|
|
try {
|
const request = {
|
barcode: this.scanForm.barcode,
|
quantity: this.scanForm.quantity,
|
palletCode: this.currentPallet.palletCode,
|
orderId: this.orderInfo.id
|
}
|
|
const result = await this.http.post('api/OutboundPicking/ConfirmPicking', request)
|
if (result.status) {
|
this.$message.success('拣选确认成功')
|
this.scanForm.barcode = ''
|
this.scanForm.quantity = 1
|
this.loadPickedHistory()
|
this.loadOrderInfo()
|
} else {
|
this.$message.error(result.message)
|
}
|
} catch (error) {
|
this.$message.error('拣选确认失败')
|
}
|
},
|
|
async handleBackToStock() {
|
if (!this.currentPallet) return
|
|
try {
|
await this.$confirm(`确定将托盘 ${this.currentPallet.palletCode} 回库吗?`, '提示', {
|
type: 'warning'
|
})
|
|
const result = await this.http.post('api/BackToStock/GenerateBackToStockTask', {
|
palletCode: this.currentPallet.palletCode,
|
currentLocation: '拣选位'
|
})
|
|
if (result.status) {
|
this.$message.success('回库任务已生成')
|
this.resetCurrentPallet()
|
}
|
} catch (error) {
|
// 用户取消
|
}
|
},
|
|
async handleDirectOutbound() {
|
if (!this.currentPallet) return
|
|
try {
|
await this.$confirm(`确定将托盘 ${this.currentPallet.palletCode} 直接出库吗?`, '提示', {
|
type: 'warning'
|
})
|
|
const result = await this.http.post('api/OutboundPicking/DirectOutbound', {
|
palletCode: this.currentPallet.palletCode
|
})
|
|
if (result.status) {
|
this.$message.success('直接出库成功')
|
this.resetCurrentPallet()
|
this.loadOrderInfo()
|
}
|
} catch (error) {
|
// 用户取消
|
}
|
},
|
|
handleOpenSplit() {
|
if (!this.currentLockInfo) {
|
this.$message.warning('请先选择锁定信息')
|
return
|
}
|
this.splitVisible = true
|
},
|
|
handleSplitSuccess() {
|
this.$message.success('拆包成功')
|
this.loadPalletLockInfo()
|
},
|
|
resetCurrentPallet() {
|
this.currentPallet = null
|
this.currentLockInfo = null
|
this.scanForm.palletCode = ''
|
},
|
|
async loadPickedHistory() {
|
const orderId = this.$route.query.orderId
|
if (!orderId) return
|
|
try {
|
const result = await this.http.get(`api/OutboundPicking/GetPickingHistory?orderId=${orderId}`)
|
if (result.status) {
|
this.pickedList = result.data
|
}
|
} catch (error) {
|
console.error('加载拣选历史失败:', error)
|
}
|
},
|
|
async handleCancelPick(row) {
|
try {
|
await this.$confirm('确定撤销这条拣选记录吗?', '提示', { type: 'warning' })
|
|
const result = await this.http.post('api/OutboundPicking/CancelPicking', {
|
pickingHistoryId: row.id
|
})
|
|
if (result.status) {
|
this.$message.success('撤销成功')
|
this.loadPickedHistory()
|
this.loadOrderInfo()
|
}
|
} catch (error) {
|
// 用户取消
|
}
|
}
|
},
|
mounted() {
|
this.loadOrderInfo()
|
this.loadPickedHistory()
|
}
|
}
|
</script>
|