<template>
|
<div>
|
<el-dialog v-model="dialogVisible"
|
title="采购申请(库存不足)"
|
width="900px"
|
@close="handleClose">
|
<!-- 简易采购申请表单 -->
|
<el-form :model="form" label-width="100px">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="销售订单号" required>
|
<el-input v-model="form.salesContractNo" placeholder="请输入销售订单号" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="抄送人" required>
|
<el-select v-model="form.ccUserId" placeholder="请选择抄送人" style="width: 100%" filterable>
|
<el-option v-for="user in userOptions" :key="user.userId" :label="user.nickName" :value="user.userId" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
|
<!-- 产品表格 -->
|
<div class="purchase-request-table">
|
<div class="table-toolbar">
|
<span class="table-title">采购产品明细</span>
|
<el-button type="primary" @click="handleAddRow">新增产品</el-button>
|
</div>
|
<el-table :data="tableData" border style="width: 100%;" max-height="400">
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column label="产品名称" min-width="150">
|
<template #default="{ row }">
|
<el-button v-if="!row.productName" type="primary" link @click="openProductSelect(row)">
|
选择产品
|
</el-button>
|
<span v-else>{{ row.productName }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="型号/规格" min-width="150">
|
<template #default="{ row }">
|
{{ row.model || '-' }}
|
</template>
|
</el-table-column>
|
<el-table-column label="单位" width="80" align="center">
|
<template #default="{ row }">
|
{{ row.unit || '-' }}
|
</template>
|
</el-table-column>
|
<el-table-column label="数量" width="120">
|
<template #default="{ row }">
|
<el-input-number v-model="row.quantity" :min="1" :precision="0" :step="1" controls-position="right" style="width: 100%;" />
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="80" align="center" fixed="right">
|
<template #default="{ $index }">
|
<el-button type="danger" link @click="handleDeleteRow($index)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" :loading="saving" @click="handleSave">保存草稿</el-button>
|
<el-button @click="dialogVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<ProductSelectDialog v-model="productSelectVisible" @confirm="handleProductConfirm" single />
|
</div>
|
</template>
|
|
<script setup>
|
import { computed, ref, watch, onMounted } from "vue";
|
import { ElMessage } from "element-plus";
|
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
|
import { saveShortagePurchaseDraft } from "@/api/procurementManagement/procurementLedger.js";
|
import { listUser } from "@/api/system/user.js";
|
import useUserStore from "@/store/modules/user.js";
|
|
const userStore = useUserStore();
|
|
const props = defineProps({
|
modelValue: { type: Boolean, default: false },
|
insufficientItems: { type: Array, default: () => [] },
|
orderRow: { type: Object, default: null },
|
});
|
const emit = defineEmits(["update:modelValue", "saved"]);
|
|
const dialogVisible = computed({
|
get: () => props.modelValue,
|
set: (val) => emit("update:modelValue", val),
|
});
|
|
const productSelectVisible = ref(false);
|
const saving = ref(false);
|
const currentSelectRowIndex = ref(-1);
|
const userOptions = ref([]);
|
|
// 表单数据
|
const form = ref({
|
salesContractNo: "",
|
ccUserId: null,
|
ccUserName: "",
|
});
|
|
// 表格数据
|
const tableData = ref([]);
|
|
// 获取用户列表(抄送人选择)
|
const getUserList = async () => {
|
try {
|
const res = await listUser({ pageSize: 1000 });
|
userOptions.value = res.rows || [];
|
} catch (error) {
|
console.error("获取用户列表失败:", error);
|
}
|
};
|
|
onMounted(() => {
|
getUserList();
|
});
|
|
// 监听对话框打开,初始化数据
|
watch(
|
() => dialogVisible.value,
|
(visible) => {
|
if (visible) {
|
initData();
|
}
|
}
|
);
|
|
// 初始化数据
|
const initData = () => {
|
// 从生产订单中获取销售订单号
|
form.value.salesContractNo = props.orderRow?.salesContractNo || "";
|
form.value.applicantId = userStore.id || "";
|
form.value.applicantName = userStore.name || "";
|
form.value.ccUserId = null;
|
form.value.ccUserName = "";
|
|
// 将库存不足的产品填充到表格
|
// 兼容领料和补料的数据结构
|
tableData.value = props.insufficientItems.map((item) => ({
|
tempId: generateTempId(),
|
productModelId: item.materialModelId || item.productModelId,
|
productName: item.materialName || item.productName,
|
model: item.materialModel || item.model,
|
unit: item.unit,
|
quantity: Math.max(1, Math.ceil((item.demandedQuantity || 0) - (item.stockQuantity || 0))),
|
}));
|
};
|
|
// 生成临时ID
|
let tempIdCounter = 0;
|
const generateTempId = () => {
|
return `temp_${++tempIdCounter}_${Date.now()}`;
|
};
|
|
// 关闭对话框
|
const handleClose = () => {
|
form.value = {
|
salesContractNo: "",
|
applicantId: "",
|
applicantName: "",
|
ccUserId: null,
|
ccUserName: "",
|
};
|
tableData.value = [];
|
currentSelectRowIndex.value = -1;
|
};
|
|
// 新增行
|
const handleAddRow = () => {
|
tableData.value.push({
|
tempId: generateTempId(),
|
productModelId: null,
|
productName: "",
|
model: "",
|
unit: "",
|
quantity: 1,
|
});
|
};
|
|
// 删除行
|
const handleDeleteRow = (index) => {
|
tableData.value.splice(index, 1);
|
};
|
|
// 打开产品选择
|
const openProductSelect = (row) => {
|
currentSelectRowIndex.value = tableData.value.findIndex(
|
(item) => item.tempId === row.tempId
|
);
|
productSelectVisible.value = true;
|
};
|
|
// 产品选择确认
|
const handleProductConfirm = (products) => {
|
if (!products || products.length === 0) return;
|
const index = currentSelectRowIndex.value;
|
if (index < 0 || !tableData.value[index]) return;
|
const product = products[0];
|
const row = tableData.value[index];
|
row.productModelId = product.materialModelId || product.modelId || product.id;
|
row.productName = product.materialName || product.productName || product.name || "";
|
row.model = product.materialModel || product.model || "";
|
row.unit = product.unit || product.measureUnit || "";
|
currentSelectRowIndex.value = -1;
|
productSelectVisible.value = false;
|
};
|
|
// 验证表单
|
const validateForm = () => {
|
if (!form.value.salesContractNo) {
|
ElMessage.warning("请输入销售订单号");
|
return false;
|
}
|
if (!form.value.ccUserId) {
|
ElMessage.warning("请选择抄送人");
|
return false;
|
}
|
if (tableData.value.length === 0) {
|
ElMessage.warning("请至少添加一个产品");
|
return false;
|
}
|
for (let i = 0; i < tableData.value.length; i++) {
|
const row = tableData.value[i];
|
if (!row.productName) {
|
ElMessage.warning(`第${i + 1}行请选择产品`);
|
return false;
|
}
|
if (!row.quantity || row.quantity <= 0) {
|
ElMessage.warning(`第${i + 1}行数量必须大于0`);
|
return false;
|
}
|
}
|
return true;
|
};
|
|
// 保存草稿
|
const handleSave = async () => {
|
if (!validateForm()) return;
|
|
// 获取抄送人姓名
|
const selectedUser = userOptions.value.find(u => u.userId === form.value.ccUserId);
|
form.value.ccUserName = selectedUser?.userName || "";
|
|
saving.value = true;
|
try {
|
// 构建采购草稿数据(根据联调文档 PurchaseLedgerDto 格式)
|
const draftData = {
|
salesContractNo: form.value.salesContractNo,
|
ccUserId: form.value.ccUserId,
|
ccUserName: form.value.ccUserName,
|
// 产品明细数据
|
productData: tableData.value.map((item) => ({
|
productModelId: item.productModelId,
|
productName: item.productName,
|
model: item.model,
|
unit: item.unit,
|
quantity: item.quantity,
|
})),
|
};
|
|
const res = await saveShortagePurchaseDraft(draftData);
|
if (res.code === 200) {
|
ElMessage.success("采购草稿保存成功,已通知抄送人补全信息");
|
emit("saved", res.data); // 返回草稿ID
|
dialogVisible.value = false;
|
} else {
|
ElMessage.error(res.msg || "保存失败");
|
}
|
} catch (error) {
|
console.error("保存采购草稿失败:", error);
|
ElMessage.error("保存失败,请重试");
|
} finally {
|
saving.value = false;
|
}
|
};
|
</script>
|
|
<style scoped lang="scss">
|
.purchase-request-table {
|
margin-top: 20px;
|
|
.table-toolbar {
|
margin-bottom: 10px;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
|
.table-title {
|
font-weight: bold;
|
font-size: 14px;
|
}
|
}
|
}
|
|
.dialog-footer {
|
display: flex;
|
justify-content: center;
|
gap: 10px;
|
}
|
</style>
|