<template>
|
<el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增自定义入库' : '编辑自定义入库'" width="70%"
|
@close="closeDia">
|
<el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
|
<div style="margin-bottom: 10px;" v-if="operationType === 'add'">
|
<el-button type="primary" @click="addProductRow">新增</el-button>
|
</div>
|
<el-table
|
:data="productList"
|
border
|
v-loading="loadingProducts"
|
>
|
<el-table-column
|
align="center"
|
label="序号"
|
type="index"
|
width="60"
|
/>
|
<el-table-column label="产品大类" prop="productCategory" width="200">
|
<template #default="scope">
|
<el-input v-model="scope.row.productCategory" placeholder="请输入产品大类" />
|
</template>
|
</el-table-column>
|
<el-table-column label="规格型号" prop="specificationModel" width="200">
|
<template #default="scope">
|
<el-input v-model="scope.row.specificationModel" placeholder="请输入规格型号" />
|
</template>
|
</el-table-column>
|
<el-table-column label="单位" prop="unit" width="100">
|
<template #default="scope">
|
<el-input v-model="scope.row.unit" placeholder="请输入单位" />
|
</template>
|
</el-table-column>
|
<el-table-column label="供应商" prop="supplierName" width="200">
|
<template #default="scope">
|
<el-input v-model="scope.row.supplierName" placeholder="请输入供应商" />
|
</template>
|
</el-table-column>
|
<el-table-column label="物品类型" prop="itemType" width="150">
|
<template #default="scope">
|
<el-select v-model="scope.row.itemType" filterable allow-create placeholder="请选择物品类型" style="width: 100%">
|
<el-option
|
v-for="item in itemTypeOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
/>
|
</el-select>
|
</template>
|
</el-table-column>
|
<el-table-column label="入库数量" prop="inboundNum" width="150">
|
<template #default="scope">
|
<el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
|
</template>
|
</el-table-column>
|
<el-table-column label="入库日期" prop="inboundDate" width="180">
|
<template #default="scope">
|
<el-date-picker
|
v-model="scope.row.inboundDate"
|
type="date"
|
placeholder="请选择入库日期"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
style="width: 100%"
|
/>
|
</template>
|
</el-table-column>
|
<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="taxInclusiveUnitPrice" width="150">
|
<template #default="scope">
|
<el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" />
|
</template>
|
</el-table-column>
|
<el-table-column
|
label="总价(元)"
|
prop="taxInclusiveTotalPrice"
|
width="150"
|
>
|
</el-table-column>
|
<el-table-column label="操作" width="80" v-if="operationType === 'add'">
|
<template #default="scope">
|
<el-button type="danger" size="small" @click="removeProductRow(scope.$index)">删除</el-button>
|
</template>
|
</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 {
|
addStockInCustom,
|
updateStockInCustom,
|
} from "@/api/inventoryManagement/stockIn.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 loading = ref(false);
|
|
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 itemTypeOptions = [
|
{ label: '物料', value: '物料' },
|
{ label: '原料', value: '原料' },
|
{ label: '成品', value: '成品' },
|
{ label: '其他', value: '其他' },
|
]
|
|
const taxRateOptions = [
|
{ label: '1', value: 1 },
|
{ label: '6', value: 6 },
|
{ label: '13', value: 13 },
|
]
|
|
const data = reactive({
|
form: {
|
id: null,
|
supplierId: null, // 供应商ID
|
supplierName: '', // 供应商名称
|
recorderId: userStore.userId, // 录入人ID
|
recorderName: userStore.name, // 录入人姓名
|
entryDate: getCurrentDate(), // 录入日期
|
remark: '', // 备注
|
},
|
rules: {
|
supplierName: [{ required: true, message: "请输入供应商名称", trigger: "blur" }]
|
}
|
})
|
const { form, rules } = toRefs(data)
|
|
// 新增产品行
|
const addProductRow = () => {
|
productList.value.push({
|
id: null,
|
productCategory: '',
|
specificationModel: '',
|
unit: '',
|
supplierName: form.value.supplierName || '',
|
itemType: '',
|
inboundNum: 0,
|
inboundDate: '',
|
quantityStock: 0,
|
taxInclusiveUnitPrice: 0,
|
taxInclusiveTotalPrice: 0,
|
taxRate: null,
|
taxExclusiveTotalPrice: 0,
|
});
|
};
|
|
// 删除产品行
|
const removeProductRow = (index) => {
|
productList.value.splice(index, 1);
|
};
|
|
// 计算总价(根据数量、单价和含税单价)
|
const calculateTotalPrice = (row) => {
|
// 计算普通总价:quantityStock * taxInclusiveUnitPrice
|
const quantity = Number(row.quantityStock || 0);
|
const taxInclusiveUnitPrice = Number(row.taxInclusiveUnitPrice || 0);
|
row.taxInclusiveTotalPrice = quantity * taxInclusiveUnitPrice;
|
calculateExclusivePrice(row);
|
};
|
|
// 计算不含税总价(根据含税总价和税率)
|
const calculateExclusivePrice = (row) => {
|
const taxInclusiveTotalPrice = Number(row.taxInclusiveTotalPrice || 0);
|
const taxRate = Number(row.taxRate || 0);
|
row.taxExclusiveTotalPrice = taxInclusiveTotalPrice / (1 + taxRate / 100);
|
};
|
|
const submitForm = async () => {
|
try {
|
await proxy.$refs.formRef.validate()
|
|
if (!productList.value.length) {
|
proxy.$modal.msgError('请至少添加一条产品数据')
|
return
|
}
|
|
// 验证自定义添加的数据必填字段
|
for (let i = 0; i < productList.value.length; i++) {
|
const product = productList.value[i];
|
if (!product.productCategory || !product.specificationModel || !product.unit) {
|
proxy.$modal.msgError(`第${i + 1}行产品数据未填写完整(产品大类、规格型号、单位为必填)`)
|
return
|
}
|
if (!product.itemType) {
|
proxy.$modal.msgError(`第${i + 1}行请选择物品类型`)
|
return
|
}
|
if (!product.inboundDate) {
|
proxy.$modal.msgError(`第${i + 1}行请选择入库日期`)
|
return
|
}
|
const stock = Number(product?.inboundNum ?? 0);
|
if (!Number.isFinite(stock) || stock <= 0) {
|
proxy.$modal.msgError(`第${i + 1}行本次入库数量需大于0`)
|
return
|
}
|
}
|
|
const payloadList = productList.value.map(product => ({
|
id: product.id ?? null,
|
inboundNum: Number(product.inboundNum),
|
productCategory: product.productCategory,
|
specificationModel: product.specificationModel,
|
unit: product.unit,
|
supplierName: product.supplierName || form.value.supplierName,
|
itemType: product.itemType,
|
inboundDate: formatDateTime(product.inboundDate, false),
|
taxRate: Number(product.taxRate || 0),
|
taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
|
taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0),
|
taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0),
|
}));
|
loading.value = true
|
if (operationType.value === 'edit') {
|
const editPayload = payloadList[0]
|
await updateStockInCustom(editPayload)
|
} else {
|
await addStockInCustom(payloadList)
|
}
|
|
proxy.$modal.msgSuccess(operationType.value === 'edit' ? '编辑自定义入库成功' : '新增自定义入库成功')
|
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
|
productList.value = []
|
emit('close')
|
}
|
|
const openDialog = async (type, row) => {
|
operationType.value = type
|
dialogFormVisible.value = true
|
|
if (type === 'add') {
|
form.value = {
|
id: null,
|
supplierId: null,
|
supplierName: '',
|
recorderId: userStore.userId,
|
recorderName: userStore.name,
|
entryDate: getCurrentDate(),
|
remark: ''
|
}
|
productList.value = []
|
} else {
|
// 编辑模式:将行数据填充到表格中以支持修改
|
form.value = {
|
id: row?.id ?? null,
|
supplierId: row?.supplierId ?? null,
|
supplierName: row?.supplierName ?? '',
|
recorderId: userStore.userId,
|
recorderName: userStore.name,
|
entryDate: getCurrentDate(),
|
remark: row?.remark ?? ''
|
}
|
productList.value = [{
|
id: row?.id ?? null,
|
productCategory: row?.productCategory ?? '',
|
specificationModel: row?.specificationModel ?? '',
|
unit: row?.unit ?? '',
|
supplierName: row?.supplierName ?? '',
|
itemType: row?.itemType ?? '',
|
inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
|
inboundDate: row?.inboundDate ?? row?.createTime ?? '',
|
quantityStock: Number(row?.quantityStock ?? 0),
|
taxRate: Number(row?.taxRate ?? 0),
|
taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0),
|
taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0),
|
taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
|
}]
|
}
|
}
|
|
defineExpose({
|
openDialog,
|
})
|
</script>
|
|
<style scoped lang="scss"></style>
|