chore: 保存盘点开发前改动

This commit is contained in:
zgw
2026-06-25 17:42:39 +08:00
parent 1af5b3cbd3
commit 4b8bc03343
114 changed files with 10005 additions and 1392 deletions

View File

@@ -155,7 +155,7 @@
icon="el-icon-magic-stick"
size="mini"
:disabled="single"
@click="handleAutoAssign"
@click="openAutoAssignDialog"
v-hasPermi="['out:stockout:autoAssign']"
>自动分配
</el-button>
@@ -251,8 +251,9 @@
<el-table-column label="物料编码" align="center" prop="productId" width="150"/>
<el-table-column label="物料名称" align="center" prop="productName" min-width="150" show-overflow-tooltip/>
<el-table-column label="库存明细" align="center" prop="stockDetailId" width="160" show-overflow-tooltip/>
<el-table-column label="托盘类型" align="center" prop="trayType" width="90"/>
<el-table-column label="计划数量" align="center" prop="quantity" width="100"/>
<el-table-column label="扫码数量" align="center" prop="allotNum" width="100"/>
<el-table-column label="分配数量" align="center" prop="allotNum" width="100"/>
<el-table-column label="实际数量" align="center" prop="assignNum" width="100"/>
<el-table-column label="备注" align="center" prop="remark" min-width="120" show-overflow-tooltip/>
<template slot="empty">
@@ -273,12 +274,72 @@
</div>
<!-- ===================== 手动分配弹窗 ===================== -->
<el-dialog
title="选择出库口"
:visible.sync="exitDialogVisible"
width="420px"
append-to-body
>
<el-form label-width="110px" size="small">
<el-form-item
v-for="trayType in autoAssignTrayTypes"
:key="trayType"
:label="formatTrayTypeLabel(trayType)"
required
>
<el-select
v-model="selectedExitByTrayType[trayType]"
placeholder="请选择出库口"
clearable
filterable
style="width: 100%;"
:loading="exitLoading"
>
<el-option
v-for="point in getExitOptionsByTrayType(trayType)"
:key="point.pointId"
:label="formatExitLabel(point)"
:value="point.pointId"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="exitDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmAutoAssign">确认分配</el-button>
</div>
</el-dialog>
<el-dialog
title="选择出库库存"
:visible.sync="assignDialogVisible"
width="80%"
append-to-body
>
<el-form v-if="manualAssignTrayTypes.length > 0" label-width="110px" size="small" style="margin-bottom: 12px;">
<el-form-item
v-for="trayType in manualAssignTrayTypes"
:key="trayType"
:label="formatTrayTypeLabel(trayType)"
required
>
<el-select
v-model="selectedExitByTrayType[trayType]"
placeholder="请选择出库口"
clearable
filterable
style="width: 320px;"
:loading="exitLoading"
>
<el-option
v-for="point in getExitOptionsByTrayType(trayType)"
:key="point.pointId"
:label="formatExitLabel(point)"
:value="point.pointId"
/>
</el-select>
</el-form-item>
</el-form>
<el-table
v-loading="stockLoading"
:data="stockList"
@@ -295,6 +356,7 @@
<el-table-column label="批次" prop="lotNo" align="center"/>
<el-table-column label="货位" prop="cargoSpaceName" align="center"/>
<el-table-column label="托盘号" prop="trayCode" align="center"/>
<el-table-column label="托盘类型" prop="trayType" align="center" width="90"/>
<el-table-column label="可用数量" prop="availableQuantity" align="center"/>
</el-table>
@@ -317,6 +379,7 @@ import {
} from "@/api/out/stockout"
import { listStockoutdetail } from "@/api/out/stockoutdetail"
import { listStockDetail } from "@/api/bas/stock"
import { listStationPoint } from "@/api/bas/stationpoint"
export default {
name: "Stockout",
@@ -325,6 +388,7 @@ export default {
return {
loading: true,
ids: [],
selectedRows: [],
single: true,
multiple: true,
showSearch: true,
@@ -356,17 +420,33 @@ export default {
detailQueryParams: {
pageNum: 1,
pageSize: 10,
stockoutId: null
stockoutId: null,
status: null
},
// 子单选中ID
detailIds: [],
detailSingle: true,
// 手动分配弹窗
exitDialogVisible: false,
assignDialogVisible: false,
exitLoading: false,
stockLoading: false,
exitOptions: [],
stockList: [],
selectedStockList: []
selectedExitId: null,
selectedExitByTrayType: {},
selectedStockList: [],
autoAssignDetails: [],
defaultTrayTypeKey: '__DEFAULT__'
}
},
computed: {
autoAssignTrayTypes() {
return this.collectTrayTypes(this.autoAssignDetails)
},
manualAssignTrayTypes() {
return this.collectTrayTypes(this.selectedStockList)
}
},
created() {
@@ -409,16 +489,19 @@ export default {
resetDetailList() {
this.detailList = []
this.detailQueryParams.stockoutId = null
this.detailQueryParams.status = null
this.currentStockout = null
this.detailTotal = 0
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.stockoutId)
this.selectedRows = selection
this.single = selection.length !== 1
},
handleRowClick(row) {
this.currentStockout = row
this.detailQueryParams.stockoutId = row.stockoutId
this.detailQueryParams.status = row.status
this.detailQueryParams.pageNum = 1
this.getDetailList()
},
@@ -444,23 +527,126 @@ export default {
this.$modal.msgWarning("请选择子单")
return
}
if (!this.currentStockout) {
this.$modal.msgWarning("请先选择出库主单")
return
}
const detail = this.detailList.find(item => item.stockoutDetailId === this.detailIds[0])
this.selectedExitId = null
this.selectedExitByTrayType = {}
this.selectedStockList = []
this.assignDialogVisible = true
this.stockLoading = true
this.loadExitOptions(this.currentStockout.warehouseId)
// 根据物料编码查询可用库存明细
listStockDetail({
productId: detail.productId,
warehouseId: this.currentStockout ? this.currentStockout.warehouseId : null,
stockStatus: '1'
}).then(res => {
this.stockList = res.rows
this.stockList = res.rows || []
this.stockLoading = false
})
},
loadExitOptions(warehouseId) {
if (!warehouseId) {
this.exitOptions = []
return Promise.resolve()
}
this.exitLoading = true
return listStationPoint({
warehouseId: warehouseId,
status: '0'
}).then(res => {
const rows = res.rows || res.data || []
this.exitOptions = rows.filter(point => {
return ['2', '3'].includes(String(point.pointType)) && String(point.pointStatus || '0') === '0'
})
this.exitLoading = false
}).catch(() => {
this.exitOptions = []
this.exitLoading = false
})
},
formatExitLabel(point) {
const typeName = String(point.pointType) === '3' ? '入出库' : '出库'
const trayType = point.trayType ? `,${point.trayType}类托盘` : ''
return `${point.pointName || point.pointId}(${point.pointId},${typeName}${trayType})`
},
getTrayTypeKey(row) {
return row && row.trayType ? String(row.trayType) : this.defaultTrayTypeKey
},
collectTrayTypes(rows) {
const types = []
;(rows || []).forEach(row => {
const key = this.getTrayTypeKey(row)
if (!types.includes(key)) {
types.push(key)
}
})
return types
},
formatTrayTypeLabel(trayType) {
return trayType === this.defaultTrayTypeKey ? '默认出库口' : `${trayType}类托盘`
},
pointSupportsTrayType(point, trayType) {
if (trayType === this.defaultTrayTypeKey) {
return true
}
if (!point.trayType) {
return true
}
return String(point.trayType).split(',').map(item => item.trim()).includes(trayType)
},
getExitOptionsByTrayType(trayType) {
return this.exitOptions.filter(point => this.pointSupportsTrayType(point, trayType))
},
resetExitSelections(trayTypes) {
this.selectedExitByTrayType = {}
;(trayTypes || []).forEach(trayType => {
this.$set(this.selectedExitByTrayType, trayType, null)
})
},
ensureExitSelections(trayTypes) {
;(trayTypes || []).forEach(trayType => {
if (!Object.prototype.hasOwnProperty.call(this.selectedExitByTrayType, trayType)) {
this.$set(this.selectedExitByTrayType, trayType, null)
}
})
},
validateExitSelections(trayTypes) {
const missingType = (trayTypes || []).find(trayType => !this.selectedExitByTrayType[trayType])
if (missingType) {
this.$modal.msgWarning(`请选择${this.formatTrayTypeLabel(missingType)}的出库口`)
return false
}
return true
},
buildExitByTrayType(trayTypes) {
const exitByTrayType = {}
;(trayTypes || []).forEach(trayType => {
if (trayType !== this.defaultTrayTypeKey) {
exitByTrayType[trayType] = this.selectedExitByTrayType[trayType]
}
})
return exitByTrayType
},
// 库存选中事件
handleStockSelectionChange(val) {
this.selectedStockList = val
this.ensureExitSelections(this.manualAssignTrayTypes)
},
// 确认分配
@@ -469,13 +655,25 @@ export default {
this.$modal.msgWarning("请选择要出库的库存")
return
}
const trayTypes = this.manualAssignTrayTypes
if (!this.validateExitSelections(trayTypes)) {
return
}
const stockIdList = Array.from(new Set(this.selectedStockList.map(item => item.detailId || item.stockDetailId || item.stockId)))
const exitByStockId = {}
this.selectedStockList.forEach(item => {
const stockKey = item.detailId || item.stockDetailId || item.stockId
exitByStockId[stockKey] = this.selectedExitByTrayType[this.getTrayTypeKey(item)]
})
const detailId = this.detailIds[0]
this.$modal.confirm("确认选中库存进行分配?").then(() => {
// 调用子单手动分配接口
return manualAssignStockout({
stockoutDetailId: detailId,
exitId: this.selectedExitByTrayType[this.defaultTrayTypeKey] || null,
exitByTrayType: this.buildExitByTrayType(trayTypes),
exitByStockId: exitByStockId,
stockIdList: stockIdList
})
}).then(() => {
@@ -503,9 +701,40 @@ export default {
this.getList()
})
},
handleAutoAssign() {
autoAssignStockout(this.ids[0]).then(() => {
openAutoAssignDialog() {
const stockout = this.selectedRows[0]
if (!stockout) {
this.$modal.msgWarning("请选择出库单据")
return
}
this.selectedExitId = null
this.selectedExitByTrayType = {}
this.autoAssignDetails = []
this.exitDialogVisible = true
this.loadExitOptions(stockout.warehouseId)
const detailPromise = this.currentStockout && this.currentStockout.stockoutId === stockout.stockoutId && this.detailList.length > 0
? Promise.resolve(this.detailList)
: listStockoutdetail({ stockoutId: stockout.stockoutId, status: stockout.status, pageNum: 1, pageSize: 9999 }).then(res => res.rows || [])
detailPromise.then(rows => {
this.autoAssignDetails = rows
this.resetExitSelections(this.autoAssignTrayTypes)
})
},
confirmAutoAssign() {
const trayTypes = this.autoAssignTrayTypes
if (trayTypes.length === 0) {
this.$modal.msgWarning("未加载到出库明细")
return
}
if (!this.validateExitSelections(trayTypes)) {
return
}
autoAssignStockout(this.ids[0], {
exitId: this.selectedExitByTrayType[this.defaultTrayTypeKey] || null,
exitByTrayType: this.buildExitByTrayType(trayTypes)
}).then(() => {
this.$modal.msgSuccess("自动分配成功")
this.exitDialogVisible = false
this.getDetailList()
})
}