<template>
|
<el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%"
|
@close="closeDia">
|
<el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
|
<el-form-item label="采购订单号" prop="purchaseContractNumber">
|
<el-select
|
v-model="form.purchaseContractNumber"
|
placeholder="请选择采购订单号"
|
clearable
|
filterable
|
:loading="loadingPurchaseOptions"
|
@change="handlePurchaseChange"
|
:disabled="operationType === 'edit'"
|
style="width: 100%"
|
>
|
<el-option
|
v-for="item in purchaseOptions"
|
:key="item.purchaseContractNumber"
|
:label="formatPurchaseOption(item)"
|
:value="item.purchaseContractNumber"
|
/>
|
</el-select>
|
</el-form-item>
|
<el-table
|
:data="productList"
|
border
|
v-loading="loadingProducts"
|
@selection-change="handleSelectionChange"
|
>
|
<el-table-column align="center" type="selection" width="55" />
|
<el-table-column
|
align="center"
|
label="序号"
|
type="index"
|
width="60"
|
/>
|
<el-table-column label="产品大类" prop="productCategory" />
|
<el-table-column label="规格型号" prop="specificationModel" />
|
<el-table-column label="单位" prop="unit" width="70" />
|
<!-- <el-table-column label="供应商" prop="supplierName" width="100" /> -->
|
<el-table-column label="采购数量" prop="quantity" width="100" />
|
<el-table-column label="待入库数量" prop="quantity0" width="100" />
|
<el-table-column label="本次入库数量" prop="quantityStock" width="150">
|
<template #default="scope">
|
<el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />
|
</template>
|
</el-table-column>
|
<el-table-column label="税率(%)" prop="taxRate" width="120" />
|
<el-table-column label="单价(元)" prop="unitPrice" width="150">
|
<template #default="scope">
|
<el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.unitPrice" @change="() => calculateTotalPrice(scope.row)" />
|
</template>
|
</el-table-column>
|
<el-table-column
|
label="总价(元)"
|
:formatter="formattedNumber"
|
prop="totalPrice"
|
width="150"
|
>
|
</el-table-column>
|
</el-table>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="submitForm">确认</el-button>
|
<el-button @click="closeDia">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</template>
|
|
<script setup>
|
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
|
import useUserStore from '@/store/modules/user'
|
import {
|
updateStockIn,
|
addSutockIn,
|
selectProductRecordListByPuechaserId
|
} from "@/api/inventoryManagement/stockIn.js";
|
import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
|
|
const userStore = useUserStore()
|
const { proxy } = getCurrentInstance()
|
const emit = defineEmits(['close', 'success'])
|
|
const operationType = ref('')// 操作类型: 'add' 或 'edit'
|
const dialogFormVisible = ref(false)// 弹框显示状态
|
const productList = ref([]);// 产品列表数据
|
const loadingProducts = ref(false);// 产品加载状态
|
const selectedRows = ref([]) // 产品表格选中行
|
const purchaseOptions = ref([])
|
const loadingPurchaseOptions = ref(false)
|
const loading = ref(false);
|
|
const data = reactive({
|
form: {
|
id: null,
|
purchaseContractNumber: '', // 采购订单号
|
supplierId: null, // 供应商ID
|
supplierName: '', // 供应商名称
|
inboundTime: '', // 入库时间
|
inboundBatch: '', // 入库批次
|
recorderId: userStore.userId, // 录入人ID
|
recorderName: userStore.name, // 录入人姓名
|
entryDate: getCurrentDate(), // 录入日期
|
remark: '', // 备注
|
},
|
rules: {
|
purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }],
|
supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }],
|
inboundTime: [{ required: true, message: "请选择入库时间", trigger: "change" }],
|
inboundBatch: [{ required: true, message: "请输入入库批次", trigger: "blur" }]
|
}
|
})
|
const { form, rules } = toRefs(data)
|
|
// 动态计算对话框标题
|
const getDialogTitle = () => {
|
return operationType.value === 'add' ? '新增入库' : '编辑入库'
|
}
|
|
const formatPurchaseOption = (item = {}) => {
|
const contract = item.purchaseContractNumber || '--';
|
const supplier = item.supplierName ? ` · ${item.supplierName}` : '';
|
return `${contract}${supplier}`;
|
};
|
|
const loadPurchaseOptions = async (keyword = '') => {
|
try {
|
loadingPurchaseOptions.value = true;
|
const res = await purchaseListPage({
|
current: -1,
|
size: -1,
|
purchaseContractNumber: keyword,
|
});
|
const records = res.data?.records || [];
|
purchaseOptions.value = records;
|
if (
|
form.value.purchaseContractNumber &&
|
!purchaseOptions.value.find(
|
(item) => item.purchaseContractNumber === form.value.purchaseContractNumber
|
)
|
) {
|
purchaseOptions.value.push({
|
purchaseContractNumber: form.value.purchaseContractNumber,
|
supplierName: form.value.supplierName,
|
supplierId: form.value.supplierId,
|
});
|
}
|
} finally {
|
loadingPurchaseOptions.value = false;
|
}
|
};
|
|
const handlePurchaseChange = (value) => {
|
form.value.purchaseContractNumber = value || '';
|
const matched = purchaseOptions.value.find(
|
(item) => item.purchaseContractNumber === value
|
);
|
if (matched) {
|
form.value.supplierName = matched.supplierName || form.value.supplierName;
|
form.value.supplierId = matched.supplierId || form.value.supplierId;
|
}
|
if (!value) {
|
productList.value = [];
|
return;
|
}
|
fetchProductsByContract();
|
};
|
|
const exceedsAddLimit = (product) => {
|
const stock = Number(product?.quantityStock ?? 0);
|
const waiting = Number(product?.quantity0 ?? 0);
|
if (!Number.isFinite(stock) || !Number.isFinite(waiting)) {
|
return false;
|
}
|
return stock > waiting;
|
};
|
|
const exceedsEditLimit = (product) => {
|
const stock = Number(product?.quantityStock ?? 0);
|
const waiting = Number(product?.quantity0 ?? 0);
|
const original = Number(product?.originalQuantityStock ?? 0);
|
if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) {
|
return false;
|
}
|
return stock > waiting + original;
|
};
|
|
const formattedNumber = (row, column, cellValue) => {
|
return parseFloat(cellValue).toFixed(2);
|
};
|
|
// 计算总价
|
const calculateTotalPrice = (row) => {
|
const quantityStock = Number(row?.quantityStock ?? 0);
|
const unitPrice = Number(row?.unitPrice ?? 0);
|
|
if (Number.isFinite(quantityStock) && Number.isFinite(unitPrice)) {
|
row.totalPrice = quantityStock * unitPrice;
|
} else {
|
row.totalPrice = 0;
|
}
|
};
|
|
const fetchProductsByContract = async () => {
|
if (!form.value.purchaseContractNumber) {
|
proxy.$modal.msgWarning('请选择合同号')
|
return
|
}
|
try {
|
loadingProducts.value = true
|
const productRes = await selectProductRecordListByPuechaserId({
|
purchaseContractNumber: form.value.purchaseContractNumber
|
});
|
if (!productRes.data || productRes.data.length === 0) {
|
proxy.$modal.msgWarning('该合同下没有产品记录')
|
productList.value = [];
|
return
|
}
|
productList.value = productRes.data.map(item => ({
|
...item,
|
quantityStock: 0,
|
unitPrice: Number(item?.unitPrice ?? 0),
|
totalPrice: 0,
|
originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0),
|
}))
|
} catch (error) {
|
console.error('查询产品记录失败:', error)
|
proxy.$modal.msgError('查询产品记录失败')
|
productList.value = [];
|
} finally {
|
loadingProducts.value = false
|
}
|
}
|
|
const updatePro = async () => {
|
if (selectedRows.value.length === 0) {
|
proxy.$modal.msgWarning('请先选择产品');
|
return;
|
}
|
const target = selectedRows.value[0];
|
const stock = Number(target?.quantityStock ?? 0);
|
if (!Number.isFinite(stock) || stock <= 0) {
|
proxy.$modal.msgWarning('请填写有效的入库数量');
|
return;
|
}
|
if (exceedsEditLimit(target)) {
|
proxy.$modal.msgError('本次入库数量不能超过原入库数量与待入库数量之和');
|
return;
|
}
|
const stockInData = {
|
id: selectedRows.value[0].recordId,
|
quantityStock: Number(selectedRows.value[0].quantityStock),
|
};
|
await updateStockIn(stockInData)
|
proxy.$modal.msgSuccess('修改入库成功')
|
closeDia()
|
emit('success')
|
}
|
|
const submitForm = async () => {
|
if (selectedRows.value.length === 0) {
|
proxy.$modal.msgWarning('请先选择采购合同并选择产品')
|
return
|
}
|
if(operationType.value !== 'add'){
|
await updatePro()
|
return
|
}
|
try {
|
await proxy.$refs.formRef.validate()
|
const invalidProducts = selectedRows.value.filter((product) => {
|
const stock = Number(product?.quantityStock ?? 0);
|
if (!Number.isFinite(stock) || stock <= 0) {
|
return true;
|
}
|
return exceedsAddLimit(product);
|
})
|
|
if (invalidProducts.length > 0) {
|
proxy.$modal.msgError('本次入库数量需大于0,且不能超过待入库数量')
|
return
|
}
|
|
const stockInData = {
|
...form.value,
|
inboundTime: formatDateTime(form.value.inboundTime),
|
nickName: userStore.nickName,
|
details: selectedRows.value.map(product => ({
|
id: product.id,
|
inboundQuantity: Number(product.quantityStock),
|
unitPrice: Number(product.unitPrice),
|
totalPrice: Number(product.totalPrice)
|
})),
|
};
|
loading.value = true
|
await addSutockIn(stockInData)
|
|
proxy.$modal.msgSuccess('新增入库成功')
|
closeDia()
|
emit('success')
|
|
} catch (error) {
|
console.error('提交失败:', error)
|
if (!error.errors) {
|
proxy.$modal.msgError('操作失败,请重试')
|
}
|
} finally {
|
loading.value = false
|
}
|
}
|
|
const closeDia = () => {
|
proxy.$refs.formRef.resetFields()
|
dialogFormVisible.value = false
|
emit('close')
|
}
|
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection.filter(item => item.id);
|
}
|
|
function formatDateTime(date = new Date(), includeTime = true) {
|
const d = new Date(date);
|
const year = d.getFullYear();
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
const day = String(d.getDate()).padStart(2, '0');
|
|
if (!includeTime) {
|
return `${year}-${month}-${day}`;
|
}
|
|
const hours = String(d.getHours()).padStart(2, '0');
|
const minutes = String(d.getMinutes()).padStart(2, '0');
|
const seconds = String(d.getSeconds()).padStart(2, '0');
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
}
|
|
function getCurrentDate() {
|
return formatDateTime(new Date(), false);
|
}
|
|
const openDialog = async (type, row) => {
|
operationType.value = type
|
dialogFormVisible.value = true
|
selectedRows.value = []
|
await loadPurchaseOptions();
|
|
if (type === 'add') {
|
form.value = {
|
id: null,
|
purchaseContractNumber: '',
|
supplierId: null,
|
supplierName: '',
|
inboundTime: '',
|
inboundBatch: '',
|
recorderId: userStore.userId,
|
recorderName: userStore.name,
|
entryDate: getCurrentDate(),
|
remark: ''
|
}
|
productList.value = []
|
} else {
|
form.value = JSON.parse(JSON.stringify(row))
|
try {
|
loadingProducts.value = true
|
const res = await selectProductRecordListByPuechaserId({
|
purchaseContractNumber: form.value.purchaseContractNumber,
|
id: row.id
|
});
|
productList.value = res.data.map(item => ({
|
...item,
|
quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
|
unitPrice: Number(item?.unitPrice ?? 0),
|
totalPrice: Number(item?.quantityStock ?? 0) * Number(item?.unitPrice ?? 0),
|
originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
|
}))
|
selectedRows.value = productList.value
|
} catch (error) {
|
console.error('加载产品失败:', error)
|
proxy.$modal.msgError('加载产品失败')
|
productList.value = []
|
} finally {
|
loadingProducts.value = false
|
}
|
}
|
}
|
|
defineExpose({
|
openDialog,
|
})
|
</script>
|
|
<style scoped lang="scss"></style>
|