feat(wms): 新增应收计划管理及入库校验功能

1. 新增receivePlan.js API文件,实现应收货物计划的增删改查和钢卷校验接口
2. 入库页面新增签收前校验功能,支持差异弹窗确认后强行收货
3. 新增收货计划明细管理页面,支持增删改查、Excel导入导出和差异对比
This commit is contained in:
2026-05-12 11:21:04 +08:00
parent 8d272ecadd
commit 57d6702c99
3 changed files with 1093 additions and 80 deletions

View File

@@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询应收货物计划列表
export function listReceivePlan(query) {
return request({
url: '/wms/receivePlan/list',
method: 'get',
params: query
})
}
// 查询应收货物计划详细
export function getReceivePlan(receiveId) {
return request({
url: '/wms/receivePlan/' + receiveId,
method: 'get'
})
}
// 新增应收货物计划
export function addReceivePlan(data) {
return request({
url: '/wms/receivePlan',
method: 'post',
data: data
})
}
// 修改应收货物计划
export function updateReceivePlan(data) {
return request({
url: '/wms/receivePlan',
method: 'put',
data: data
})
}
// 删除应收货物计划
export function delReceivePlan(receiveId) {
return request({
url: '/wms/receivePlan/' + receiveId,
method: 'delete'
})
}
// 校验要签收的钢卷是否在代收计划中
export function checkReceivePlan(data) {
return request({
url: '/wms/receivePlan/validateCoil',
method: 'post',
data: data
})
}

View File

@@ -137,8 +137,10 @@
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="getItemLabel" prop="itemId" v-if="!form.coilId"> <el-form-item :label="getItemLabel" prop="itemId" v-if="!form.coilId">
<product-select v-if="form.itemType == 'product'" @change="handleProductChange" v-model="form.itemId" clearable /> <product-select v-if="form.itemType == 'product'" @change="handleProductChange" v-model="form.itemId"
<raw-material-select v-else-if="form.itemType == 'raw_material'" @change="handleProductChange" v-model="form.itemId" clearable /> clearable />
<raw-material-select v-else-if="form.itemType == 'raw_material'" @change="handleProductChange"
v-model="form.itemId" clearable />
<div v-else>请先选择材料类型</div> <div v-else>请先选择材料类型</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -170,8 +172,10 @@
<el-form-item label="钢卷号" prop="currentCoilNo"> <el-form-item label="钢卷号" prop="currentCoilNo">
<el-input v-model="queryForm.currentCoilNo" placeholder="请输入钢卷号" /> <el-input v-model="queryForm.currentCoilNo" placeholder="请输入钢卷号" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="getList">查询</el-button> <el-checkbox v-model="validateBeforeReceipt" label="在签收前校验">在签收前校验</el-checkbox>
<el-button type="primary" @click="getList" style="margin-left: 10px;">查询</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -249,7 +253,8 @@
</el-form> </el-form>
<template slot="footer" class="dialog-footer"> <template slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmReceipt" v-loading="buttonLoading">签收</el-button> <el-checkbox v-model="validateBeforeReceipt" label="在签收前校验">签收前校验</el-checkbox>
<el-button style="margin-left: 10px;" type="primary" @click="confirmReceipt" v-loading="buttonLoading">签收</el-button>
<el-button @click="receiptModalVisible = false">取消</el-button> <el-button @click="receiptModalVisible = false">取消</el-button>
</template> </template>
</el-dialog> </el-dialog>
@@ -259,7 +264,24 @@
<label-render :content="labelRender.data" :labelType="labelRender.type" v-loading="labelRender.loading" /> <label-render :content="labelRender.data" :labelType="labelRender.type" v-loading="labelRender.loading" />
</el-dialog> </el-dialog>
<label-render ref="labelRender" v-show="false" :content="labelRender.data" :labelType="labelRender.type" v-loading="labelRender.loading" /> <label-render ref="labelRender" v-show="false" :content="labelRender.data" :labelType="labelRender.type"
v-loading="labelRender.loading" />
<!-- 差异确认弹窗 -->
<el-dialog title="钢卷信息差异确认" :visible.sync="differenceModalVisible" width="50%" :close-on-click-modal="false">
<el-alert :title="differenceMessage" type="warning" :closable="false" show-icon>
</el-alert>
<el-table :data="differenceTableData" border style="margin-top: 20px;">
<el-table-column prop="field" label="字段" width="150"></el-table-column>
<el-table-column prop="frontendValue" label="实际值"></el-table-column>
<el-table-column prop="databaseValue" label="计划值"></el-table-column>
</el-table>
<template slot="footer" class="dialog-footer">
<el-button style="margin-left: 10px;" type="primary" @click="confirmDifference"
v-loading="buttonLoading">确认差异并强行收货</el-button>
<el-button @click="differenceModalVisible = false">取消收货</el-button>
</template>
</el-dialog>
<el-dialog v-loading="editCoil.loading" title="入库钢卷信息编辑" :visible.sync="editCoil.dialogVisible" width="30%"> <el-dialog v-loading="editCoil.loading" title="入库钢卷信息编辑" :visible.sync="editCoil.dialogVisible" width="30%">
<el-form ref="form" :model="editCoil.form" :rules="rules" label-width="100px"> <el-form ref="form" :model="editCoil.form" :rules="rules" label-width="100px">
@@ -366,9 +388,7 @@ import { listDeliveryPlan } from '@/api/wms/deliveryPlan'
import handleCoil, { COIL_ACTIONS } from '../js/coilActions' import handleCoil, { COIL_ACTIONS } from '../js/coilActions'
import LabelRender from '../panels/LabelRender/index.vue' import LabelRender from '../panels/LabelRender/index.vue'
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue"; import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
import { delCoilWarehouseOperationLogByCoilId } from '@/api/wms/coilWarehouseOperationLog' import { checkReceivePlan } from '@/api/wms/receivePlan'
// 键值为[400, 500), 不包含在字典中但后续可以加入的特殊操作这类操作录入后会立刻完成例如入库401和发货402
export default { export default {
components: { components: {
@@ -455,20 +475,15 @@ export default {
], ],
currentCoilNo: [ currentCoilNo: [
{ required: true, message: "当前钢卷号不能为空", trigger: "blur" }, { required: true, message: "当前钢卷号不能为空", trigger: "blur" },
// 远程校验,当前钢卷号不能重复 {
// { validator: (rule, value, callback) => {
// validator: (rule, value, callback) => { if (!/^\d{8}$/.test(value)) {
// checkCoilNo({ currentCoilNo: value, coilId: this.form.coilId }).then(res => { callback(new Error('当前钢卷号必须是8位的阿拉伯数字'));
// const { duplicateType } = res.data; } else {
// if (duplicateType === 'current' || duplicateType === 'both') { callback();
// // alert('当前钢卷号重复,请重新输入'); }
// callback(new Error('当前钢卷号重复,请重新输入')); }, trigger: 'blur'
// } else { },
// callback();
// }
// })
// }, trigger: 'blur'
// },
], ],
supplierCoilNo: [ supplierCoilNo: [
{ required: true, message: "厂家原料卷号不能为空", trigger: "blur" }, { required: true, message: "厂家原料卷号不能为空", trigger: "blur" },
@@ -529,13 +544,21 @@ export default {
}, },
coilInfo: {}, coilInfo: {},
todayPlanId: null, todayPlanId: null,
// 是否在签收前进行验证
validateBeforeReceipt: false,
editCoil: { editCoil: {
form: { form: {
}, },
dialogVisible: false, dialogVisible: false,
loading: false, loading: false,
} },
// 差异确认相关数据
differenceModalVisible: false,
differenceMessage: '',
differenceTableData: [],
dbData: null,
checkResult: null
} }
}, },
mounted() { mounted() {
@@ -693,20 +716,62 @@ export default {
}) })
}, },
// 确认收货 // 确认收货
confirmReceipt() { async confirmReceipt() {
await this.$modal.confirm("确认收货后刚钢卷会进入库存并占用所选的实际库区,是否继续?")
// 二次确认 // 二次确认
this.$modal.confirm("收货后刚钢卷会进入库存并占用所选的实际库区,是否继续?").then(() => { try {
this.buttonLoading = true; this.buttonLoading = true;
// 更新操作记录状态 actionStatus: 2 if (this.validateBeforeReceipt) {
handleCoil(COIL_ACTIONS.STORE, this.coilInfo, this.receiptForm) // 先检验是否在代收卷中存在当前的信息
.then(_ => { const res = await checkReceivePlan(this.coilInfo)
this.$message.success("确认收货成功"); const { found, message, differences, dbData } = res.data
this.getList() this.checkResult = res.data
this.receiptModalVisible = false; if (!found) {
}).finally(() => {
this.buttonLoading = false; this.buttonLoading = false;
}); this.$modal.msgError("钢卷不在代收计划中");
}) return;
}
// 检查是否有差异
if (differences && Object.keys(differences).length > 0) {
// 有差异,展示差异弹窗
this.differenceMessage = message || '钢卷信息存在差异,请确认后继续收货'
// 处理差异数据,转换为表格格式
this.differenceTableData = Object.entries(differences).map(([field, value]) => {
// 使用正则表达式提取前端值和数据库值
const regex = /前端值[:]\s*(.+?)\s*[,]\s*数据库值[:]\s*(.+)/
const match = value.match(regex)
const frontendValue = match ? match[1] : ''
const databaseValue = match ? match[2] : ''
return { field, frontendValue, databaseValue }
})
this.dbData = dbData
this.buttonLoading = false
this.differenceModalVisible = true
return
}
}
// 没有差异或不需要校验,直接收货
this.doReceipt()
} catch (error) {
this.buttonLoading = false;
}
},
// 执行收货操作
doReceipt() {
this.buttonLoading = true;
handleCoil(COIL_ACTIONS.STORE, this.coilInfo, this.receiptForm)
.then(_ => {
this.$message.success("确认收货成功");
this.getList()
this.receiptModalVisible = false;
this.differenceModalVisible = false;
}).finally(() => {
this.buttonLoading = false;
});
},
// 确认差异并继续收货
confirmDifference() {
this.doReceipt()
}, },
handleReject(row) { handleReject(row) {
this.$modal.confirm("确认拒签吗?", "拒签确认", { this.$modal.confirm("确认拒签吗?", "拒签确认", {
@@ -812,14 +877,11 @@ export default {
}) })
}, },
// 检查钢卷号是否合法(后端检查) // 检查钢卷号是否合法(后端检查)
checkCoilNo() { // checkCoilNo() {
checkCoilNo({ currentCoilNo: this.form.currentCoilNo, entryCoilNo: this.form.enterCoilNo }).then(res => { // checkCoilNo({ currentCoilNo: this.form.currentCoilNo, entryCoilNo: this.form.enterCoilNo }).then(res => {
console.log(res) // console.log(res)
// if (res.data) { // })
// this.$modal.msgError("钢卷号已存在"); // },
// }
})
},
// 取消操作 // 取消操作
cancel() { cancel() {
this.form = {}; this.form = {};

File diff suppressed because it is too large Load Diff