feat: 新增合同配置页面,优化多页面合同关联逻辑

1.  新增crm/contract/selectConfig页面,支持本地配置可选合同列表,区分手动/接口同步来源
2.  优化ContractSelect组件,新增上次选中合同置顶、本地存储选中记录功能
3.  为合卷、分条、退火计划、钢卷编辑页面添加合同必填校验与自动关联逻辑
4.  移除各业务页面冗余的合同关系手动调用代码,统一关联逻辑
This commit is contained in:
2026-06-18 13:49:52 +08:00
parent 7f1a89eb61
commit ee49fbdcc0
7 changed files with 392 additions and 63 deletions

View File

@@ -159,7 +159,7 @@
</el-row>
<el-dialog title="完成退火" :visible.sync="completeOpen" width="720px" append-to-body>
<div class="complete-tip">请为每条钢卷分配逻辑库区去向未分配将无法完成</div>
<div class="complete-tip">请为每条钢卷分配逻辑库区去向和关联合同未分配将无法完成</div>
<el-table :data="completeCoils" v-loading="completeLoading" height="360px">
<el-table-column label="入场钢卷号" prop="enterCoilNo" align="center" />
<el-table-column label="钢卷去向" align="center" width="240">
@@ -170,6 +170,11 @@
</el-select>
</template>
</el-table-column>
<el-table-column label="关联合同" align="center" width="240">
<template slot-scope="scope">
<ContractSelect v-model="scope.row.contractId" placeholder="请选择合同" />
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitComplete"> </el-button>
@@ -234,11 +239,13 @@ import { listMaterialCoil } from "@/api/wms/coil";
import { listWarehouse } from '@/api/wms/warehouse'
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { addAnnealOperateEvent } from "@/api/wms/annealOperateEvent";
import ContractSelect from "@/components/KLPService/ContractSelect";
export default {
name: "AnnealPlan",
components: {
WarehouseSelect
WarehouseSelect,
ContractSelect
},
data() {
return {
@@ -563,17 +570,18 @@ export default {
submitComplete() {
const locations = (this.completeCoils || []).map(item => ({
coilId: item.coilId,
warehouseId: item.warehouseId
warehouseId: item.warehouseId,
contractId: item.contractId,
}));
const missing = locations.filter(item => !item.warehouseId);
const missing = locations.filter(item => !item.warehouseId || !item.contractId);
if (missing.length > 0) {
this.$message.warning('请先为所有钢卷分配实际库位');
this.$message.warning('请先为所有钢卷分配实际库位和关联合同');
return;
}
this.completeLoading = true;
completeAnnealPlan({
planId: this.completePlanId,
locations: locations
locations: locations,
}).then(() => {
// anneal-todo: 新增操作事件
const targetFurnaceName = this.furnaceOptions.find(item => item.furnaceId === this.currentPlan.targetFurnaceId)?.furnaceName || '';

View File

@@ -375,7 +375,6 @@ import AbnormalForm from './components/AbnormalForm';
import PlanSheetViewer from './components/PlanSheetViewer.vue';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
export default {
name: 'MergeCoil',
@@ -827,6 +826,12 @@ export default {
return;
}
// 验证合同
if (!this.targetCoil.contractId) {
this.$message.error('请选择合同');
return;
}
let loadingInstance = null;
try {
this.loading = true;
@@ -840,6 +845,7 @@ export default {
const mergeData = {
...this.targetCoil,
contractId: this.targetCoil.contractId || '',
enterCoilNo: enterCoilNos, // 拼接的入场钢卷号
hasMergeSplit: 2, // 2表示合卷
abnormals: this.abnormals,
@@ -859,16 +865,8 @@ export default {
background: 'rgba(0, 0, 0, 0.7)'
});
const response = await mergeMaterialCoil(mergeData);
await mergeMaterialCoil(mergeData);
const coilId = response.data;
if (this.targetCoil.contractId) {
addCoilContractRel({
coilId: coilId,
contractId: this.targetCoil.contractId,
})
}
this.$message.success('合卷保存成功');
// 延迟返回,让用户看到成功提示

View File

@@ -393,7 +393,6 @@ import { generateCoilNoPrefix } from '@/utils/coil/coilNo'
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo'
import RawMaterialInfo from '@/components/KLPService/Renderer/RawMaterialInfo'
import ContractSelect from '@/components/KLPService/ContractSelect'
import { addCoilContractRel } from '@/api/wms/coilContractRel'
export default {
name: 'StepSplit',
@@ -491,7 +490,8 @@ export default {
materialType: [{ required: true, message: '请选择材料类型', trigger: 'change' }],
itemId: [{ required: true, message: '请选择成品/原料', trigger: 'change' }],
netWeight: [{ required: true, message: '请输入净重', trigger: 'blur' }],
warehouseId: [{ required: true, message: '请选择所在库位', trigger: 'change' }]
warehouseId: [{ required: true, message: '请选择所在库位', trigger: 'change' }],
contractId: [{ required: true, message: '请选择合同', trigger: 'change' }]
},
buttonLoading: false,
currentAction: {},
@@ -872,13 +872,6 @@ export default {
} else {
// 新增分条:调用创建接口
res = await createSpecialChild(this.coilId, this.actionId, splitData)
// 新增分条后,需要添加分条的合同关系
if (this.splitForm.contractId) {
addCoilContractRel({
coilId: res.data.coilId,
contractId: this.splitForm.contractId
})
}
}
this.$message.success(this.splitForm.coilId ? '编辑分条成功' : '新增分条成功')

View File

@@ -378,7 +378,6 @@ import AbnormalForm from './components/AbnormalForm';
import PlanSheetViewer from './components/PlanSheetViewer.vue';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
export default {
name: 'SplitCoil',
@@ -748,6 +747,10 @@ export default {
this.$message.error(`${i + 1}个子卷的目标库区不能为空`);
return;
}
if (!item.contractId) {
this.$message.error(`${i + 1}个子卷的合同不能为空`);
return;
}
}
const loadingInstance = this.$loading({
@@ -768,9 +771,10 @@ export default {
hasMergeSplit: 1, // 1表示分条
newCoils: this.splitList.map(item => ({
...item,
itemType: item.itemType || this.motherCoil.itemType,
itemId: item.itemId || this.motherCoil.itemId,
hasMergeSplit: 1
itemType: item.itemType,
itemId: item.itemId,
hasMergeSplit: 1,
contractId: item.contractId,
}))
};
@@ -778,24 +782,6 @@ export default {
if (response.code === 200) {
this.$message.success('分条保存成功');
// 拿到多个子卷的coilId
const newCoilIds = response.msg.split(',');
// 先构建所有的请求体,并移除合同为空为空的项
const requests = newCoilIds.map((coilId, index) => ({
coilId,
contractId: this.splitList[index].contractId
}))
.filter(req => req.contractId);
// 为每个子卷添加合同关联
Promise.all(requests.map(async (req, index) => {
addCoilContractRel(req);
}));
// 如果是从待操作列表进来的,标记操作为完成
// if (this.actionId) {
// await completeAction(this.actionId, response.msg);
// }
// 延迟返回,让用户看到成功提示
setTimeout(() => {
this.$router.back();

View File

@@ -400,7 +400,6 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import TimeInput from "@/components/TimeInput";
import AbnormalForm from './components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
import ContractSelect from "@/components/KLPService/ContractSelect";
import L2MatchPanel from './panels/L2MatchPanel.vue'
import DrMatchPanel from './panels/DrMatchPanel.vue';
@@ -522,6 +521,7 @@ export default {
warehouseId: [
{ required: true, message: '请选择逻辑库区', trigger: 'change' }
],
contractId: [{ required: true, message: '请选择合同', trigger: 'change' }]
},
actionId: null,
actionType: null, // 待操作类型504/524 = 双机架
@@ -869,6 +869,8 @@ export default {
// 构造更新数据使用标准update接口直接更新原记录
const updateData = {
...this.updateForm,
contractId: this.updateForm.contractId,
// 其他字段...
coilId: this.currentInfo.coilId,
enterCoilNo: this.currentInfo.enterCoilNo,
supplierCoilNo: this.currentInfo.supplierCoilNo,
@@ -877,23 +879,9 @@ export default {
const response = await updateMaterialCoil({ ...updateData, actionId: this.actionId });
// 更新完成后如果选定了合同,需要增加与合同的绑定关系
const coilId = response.msg;
if (this.updateForm.contractId) {
await addCoilContractRel({
coilId: coilId,
contractId: this.updateForm.contractId,
});
}
if (response.code === 200) {
this.$message.success('钢卷信息更新成功');
// 如果是从待操作列表进来的,标记操作为完成
// if (this.actionId) {
// await completeAction(this.actionId, response.msg);
// }
// 延迟返回
setTimeout(() => {
this.$router.back();