Files
klp-oa/klp-ui/src/views/wms/purchasePlan/panels/CreatePurchasePanel.vue
2025-07-30 10:53:06 +08:00

246 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="purchase-plan-transfer">
<!-- 采购单信息区 -->
<el-card class="section-card" shadow="never">
<div slot="header" class="section-title">采购单信息</div>
<el-form :model="mainForm" :rules="mainFormRules" ref="mainFormRef" :inline="true" label-width="120px" style="margin-bottom: 0;" v-loading="formLoading" element-loading-text="正在加载主数据...">
<el-form-item label="计划编号" prop="planCode">
<el-input v-model="mainForm.planCode" placeholder="请输入计划编号" style="width: 200px;" />
</el-form-item>
<el-form-item label="负责人" prop="owner">
<el-input v-model="mainForm.owner" :multiple="false" placeholder="请填写负责人" style="width: 200px;" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="mainForm.remark" placeholder="请输入备注" style="width: 300px;" />
</el-form-item>
</el-form>
</el-card>
<div>
<!-- 采购单明细区 -->
<el-card shadow="never">
<div slot="header" class="section-title">采购单明细</div>
<el-table
:data="purchaseList"
@selection-change="handleRightSelectionChange"
style="width: 100%"
ref="rightTable"
border
>
<el-table-column type="selection" width="55" />
<el-table-column prop="rawMaterialId" label="原材料">
<template #default="scope">
<RawMaterialSelect v-model="scope.row.rawMaterialId" placeholder="请选择原材料" />
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" />
<el-table-column prop="quantity" label="计划采购数">
<template #default="scope">
<el-input-number v-model="scope.row.quantity" :min="0" size="small" />
</template>
</el-table-column>
<el-table-column prop="owner" label="负责人">
<template #default="scope">
<el-input v-model="scope.row.owner" :multiple="false" placeholder="请填写负责人" size="small" />
</template>
</el-table-column>
<el-table-column prop="remark" label="备注">
<template #default="scope">
<el-input v-model="scope.row.remark" size="small" />
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<div style="margin-top: 20px; text-align: right;" v-loading="submitLoading" element-loading-text="正在提交数据...">
<el-button type="primary" @click="confirm" :loading="submitLoading">{{ submitLoading ? '提交中...' : '确认' }}</el-button>
</div>
</div>
</template>
<script>
import { createPurchasePlan } from '@/api/wms/purchasePlan'
import { listRawMaterial } from '@/api/wms/rawMaterial'
import UserSelect from '@/components/KLPService/UserSelect'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
export default {
name: 'CreatePurchasePanel',
components: { UserSelect, RawMaterialSelect },
props: {
orderId: {
type: [String, Number],
required: true
},
recommendData: {
type: Object,
default: () => ({})
}
},
data() {
return {
// 原材料表格相关
rawMaterialList: [],
total: 0,
pageNum: 1,
pageSize: 10,
rawMaterialLoading: false,
leftSelected: [],
rightSelected: [],
rawMaterialNameFilter: '',
// 采购列表
purchaseList: [],
// 细化的loading状态
formLoading: false,
submitLoading: false,
mainForm: {
planCode: '',
owner: '',
remark: ''
},
mainFormRules: {
planCode: [
{ required: true, message: '请输入计划编号', trigger: 'blur' }
],
owner: [
{ required: true, message: '请输入负责人', trigger: 'blur' }
]
}
}
},
watch: {
recommendData: {
immediate: true,
handler(newVal) {
if (newVal && newVal.detailList) {
this.purchaseList = newVal.detailList
this.mainForm = {
planCode: newVal.planCode || '',
owner: newVal.owner || '',
remark: newVal.remark || ''
}
}
}
}
},
mounted() {
this.fetchRawMaterials();
},
methods: {
// 原材料分页查询
fetchRawMaterials() {
this.rawMaterialLoading = true;
listRawMaterial({ pageNum: this.pageNum, pageSize: this.pageSize, rawMaterialName: this.rawMaterialNameFilter }).then(res => {
// 过滤掉已在采购列表中的原材料
const purchaseIds = this.purchaseList.map(item => item.rawMaterialId);
this.rawMaterialList = (res.rows || []).filter(item => !purchaseIds.includes(item.rawMaterialId));
this.total = res.total || 0;
this.rawMaterialLoading = false;
}).catch(() => {
this.rawMaterialLoading = false;
});
},
handlePageChange(page) {
this.pageNum = page;
this.fetchRawMaterials();
},
handleSelectionChange(selection) {
this.leftSelected = selection;
},
handleRightSelectionChange(selection) {
this.rightSelected = selection;
},
handleRawMaterialFilter() {
this.pageNum = 1;
this.fetchRawMaterials();
},
addToPurchase() {
// 去重添加
const ids = this.purchaseList.map(item => item.rawMaterialId);
const newItems = this.leftSelected.filter(item => !ids.includes(item.rawMaterialId)).map(item => ({
...item,
quantity: 0,
owner: '',
remark: ''
}));
this.purchaseList = this.purchaseList.concat(newItems);
this.$refs.leftTable.clearSelection();
this.fetchRawMaterials();
},
removeFromPurchase() {
const removeIds = this.rightSelected.map(item => item.rawMaterialId);
this.purchaseList = this.purchaseList.filter(item => !removeIds.includes(item.rawMaterialId));
this.$refs.rightTable.clearSelection();
this.fetchRawMaterials();
},
confirm() {
this.submitLoading = true;
this.$refs.mainFormRef.validate(async(valid) => {
if (!valid) {
this.$message.error('请完整填写主数据信息');
this.submitLoading = false;
return;
}
// 校验采购列表数据除remark外都不能为空
const filtered = this.purchaseList.filter(row => row.rawMaterialId && row.rawMaterialId !== '');
const invalid = filtered.some(row => {
return !row.rawMaterialId || !row.owner || !row.unit || row.quantity === '' || row.quantity === null || row.quantity === undefined;
});
if (invalid) {
this.$message.error('请完整填写所有必填项');
this.submitLoading = false;
return;
}
// 合并主数据和明细数据
const submitData = {
...this.mainForm,
orderId: this.orderId,
detailList: filtered
};
await createPurchasePlan(submitData);
this.$emit('confirm', submitData);
this.submitLoading = false;
});
}
}
}
</script>
<style scoped>
.purchase-plan-transfer {
display: flex;
flex-direction: column;
}
.section-card {
margin-bottom: 20px;
}
.section-title {
font-weight: bold;
font-size: 16px;
color: #333;
}
.transfer-content {
display: flex;
align-items: flex-start;
}
.left-table {
width: 30%;
}
.right-table {
width: 60%;
}
.transfer-actions {
width: 10%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.transfer-actions .el-button {
margin: 10px 0;
}
.filter-bar {
display: flex;
align-items: center;
margin-bottom: 10px;
}
</style>