feat: 更新采购计划和出入库管理功能

添加清除所有草稿功能
扩展采购计划和出入库接口类型定义
新增出入库统计和产品列表接口
重写计划详情页面数据展示逻辑
改进数据分析组件支持动态数据
优化库存管理页面查询和展示逻辑
完善详情信息组件展示和文件预览功能
This commit is contained in:
re-JZzzz
2025-09-28 20:04:30 +08:00
parent 11f9433ba7
commit 321c3fce49
12 changed files with 856 additions and 674 deletions

View File

@ -12,7 +12,7 @@
待审批计划
</div>
<div class="count" style="color: rgba(255, 178, 30, 1);">
12
{{ pendingCount }}
</div>
</div>
<div class="item">
@ -20,7 +20,7 @@
已批准计划
</div>
<div class="count" style="color: rgba(67, 101, 220, 1);">
28
{{ approvedCount }}
</div>
</div>
<div class="item">
@ -28,7 +28,7 @@
采购中计划
</div>
<div class="count" style="color: rgba(113, 214, 213, 1);">
15
{{ purchasingCount }}
</div>
</div>
<div class="item">
@ -36,7 +36,7 @@
已完成计划
</div>
<div class="count" style="color: rgba(0, 184, 122, 1);">
86
{{ completedCount }}
</div>
</div>
</div>
@ -53,7 +53,7 @@
本年度已采购金额
</div>
<div class="count" style="color: rgba(255, 153, 0, 1);">
520,000.00
{{ yearlyAmount.shijiJine }}
</div>
</div>
<div class="item">
@ -61,7 +61,7 @@
本年度采购预算金额
</div>
<div class="count" style="color: rgba(67, 101, 220, 1);">
3,000,000.00
{{ yearlyAmount.yujiJine }}
</div>
</div>
</div>
@ -73,34 +73,38 @@
<el-card style="border-radius: 10px;">
<div class="content">
<div class="tabs">
<el-button type="success">导出</el-button>
<el-button type="primary" @click="isNewProcurementDialogVisible = true">新建采购申请单</el-button>
<!-- <el-button type="success">导出</el-button> -->
<el-button type="primary" @click="handleAdd">新建采购申请单</el-button>
</div>
<!-- 标签页导航 -->
<div class="tabs">
<!-- <el-badge :value="pendingCount" type="warning">
<el-button :type="activeTab === 'pending' ? 'primary' : ''"
@click="changeTab('pending')">待审批</el-button>
<el-badge :value="total" type="success">
<el-button :type="activeTab === 'all' ? 'primary' : ''"
@click="changeTab('all')">全部</el-button>
</el-badge>
<el-badge :value="purchasingCount" type="info">
<el-button :type="activeTab === 'purchasing' ? 'primary' : ''"
@click="changeTab('purchasing')">采购中</el-button>
<el-badge :value="pendingCount" type="warning">
<el-button :type="activeTab === '3' ? 'primary' : ''"
@click="changeTab('3')">待审批</el-button>
</el-badge>
<el-badge :value="purchasingCount" type="primary">
<el-button :type="activeTab === '5' ? 'primary' : ''"
@click="changeTab('5')">采购中</el-button>
</el-badge>
<el-badge :value="rejectedCount" type="danger">
<el-button :type="activeTab === 'rejected' ? 'primary' : ''"
@click="changeTab('rejected')">
<el-button :type="activeTab === '7' ? 'primary' : ''"
@click="changeTab('7')">
未通过
</el-button>
</el-badge>
<el-badge :value="approvedCount" type="primary">
<el-button :type="activeTab === 'approved' ? 'primary' : ''"
@click="changeTab('approved')">已通过</el-button>
<el-badge :value="approvedCount" type="success">
<el-button :type="activeTab === '9' ? 'primary' : ''"
@click="changeTab('9')">已通过</el-button>
</el-badge>
<el-badge :value="completedCount" type="success">
<el-button :type="activeTab === 'completed' ? 'primary' : ''"
@click="changeTab('completed')">已完成</el-button>
</el-badge> -->
<el-button :type="activeTab === '11' ? 'primary' : ''"
@click="changeTab('11')">已完成</el-button>
</el-badge>
</div>
<!-- 表格 -->
<el-table :data="caigouPlanList" border style="width: 100%;margin-top: 15px;">
@ -115,9 +119,10 @@
<dict-tag :options="wz_caigou_examine" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="80" align="center">
<el-table-column label="操作" fixed="right" align="center">
<template #default="scope">
<el-button type="text" @click="handleView(scope.row)">查看</el-button>
<el-button type="text" @click="handleUpdate(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
@ -131,26 +136,23 @@
</el-card>
</el-col>
</el-row>
<el-dialog v-model="isNewProcurementDialogVisible" title="新建采购申请单" width="60%" :close-on-click-modal="false">
<el-dialog v-model="isDialogVisible" :title="dialogTitle" width="60%" :close-on-click-modal="false">
<div class="new-procurement-form">
<!-- 基础信息 -->
<div class="form-section">
<h3>基础信息</h3>
<!-- 输入框行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="计划名称">
<el-input v-model="form.jihuaName" placeholder="请填写计划名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="合同名称">
<el-input v-model="form.hetonName" placeholder="请填写合同名称" />
</el-form-item>
</el-col>
</el-row>
<!-- 下拉框行 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="合同类型">
<el-select v-model="form.hetonType" placeholder="请选择">
@ -159,6 +161,9 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 下拉框行 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="采购类型">
<el-select v-model="form.caigouType" placeholder="请选择">
@ -173,6 +178,13 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="申请原因">
<el-input v-model="form.reason" placeholder="请输入申请原因" type="textarea" />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 供应商信息 -->
@ -184,9 +196,9 @@
<el-select v-model="form.danwei" placeholder="请选择">
<!-- <el-option v-for="option in supplierList" :key="option.value" :label="option.label"
:value="option.value" /> -->
<el-option label="供应商1" value="供应商1" />
<el-option label="供应商1" value="供应商1" />
<el-option label="供应商1" value="供应商1" />
<el-option label="供应商1" value="供应商1" />
<el-option label="供应商1" value="供应商1" />
<el-option label="供应商1" value="供应商1" />
</el-select>
</el-form-item>
</el-col>
@ -216,13 +228,13 @@
<el-table-column prop="chanpinMonovalent" label="产品单价">
<template #default="scope">
<el-input v-model="scope.row.chanpinMonovalent" placeholder="请填写" type="number"
@change="calculateTotalPrice(scope.row)" />
@change="calculateTotalPrice(scope.row)" min="0" />
</template>
</el-table-column>
<el-table-column prop="goumaiNumber" label="购买数量">
<template #default="scope">
<el-input v-model="scope.row.goumaiNumber" placeholder="请填写" type="number"
@change="calculateTotalPrice(scope.row)" />
@change="calculateTotalPrice(scope.row)" min="0" />
</template>
</el-table-column>
<el-table-column prop="danwei" label="单位">
@ -230,6 +242,11 @@
<el-input v-model="scope.row.danwei" placeholder="请填写" />
</template>
</el-table-column>
<el-table-column prop="yontu" label="用途(简要描述)">
<template #default="scope">
<el-input v-model="scope.row.yontu" placeholder="请填写" />
</template>
</el-table-column>
<el-table-column prop="totalPrice" label="合计" :formatter="calculateTotalPrice">
<template #default="scope">
<span>{{ calculateTotalPrice(scope.row) }}</span>
@ -271,17 +288,38 @@
<!-- 附件上传 -->
<div class="form-section">
<h3>附件上传</h3>
<!-- 附件 -->
<el-table :data="form.opsCaigouPlanFilesBos || []" border v-if="currentOperation === 'update'">
<el-table-column prop="fileName" label="文件名" align="center" />
<el-table-column label="文件类型" align="center">
<template #default="scope">
{{ getFileType(scope.row.fileName) }}
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="text" @click="handlePreview(scope.row)">
预览
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<file-upload ref="fileUploadRef" :isDrag="true" :file-list="form.opsCaigouPlanFilesBos"
:is-show-tip="false"
@update:file-list="handleUpdateFileList"
:is-show-tip="false" @update:file-list="handleUpdateFileList"
:file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf', 'png', 'jpg', 'jpeg']" />
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelNewProcurement">取消</el-button>
<el-button @click="saveDraft" :loading="buttonLoading">保存草稿</el-button>
<el-button type="primary" @click="submitProcurement" :loading="buttonLoading">提交申请</el-button>
<el-button @click="cancelOperation">取消</el-button>
<el-button v-if="currentOperation !== 'update'" @click="saveDraft" :loading="buttonLoading">保存草稿</el-button>
<el-button type="primary" @click="getSubmitFunction()" :loading="buttonLoading">
{{ currentOperation === 'add' ? '提交申请' : '更新' }}
</el-button>
</div>
</template>
</el-dialog>
@ -361,13 +399,13 @@
}
</style>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue';
import { ref, reactive, computed, getCurrentInstance, onUnmounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useProcurementDraftStore } from '@/store/modules/procurementDraft';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type, wz_caigou_examine } = toRefs<any>(proxy?.useDict('wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
import { listCaigouPlan, getSupplierList, addCaigouPlan } from '@/api/wuziguanli/caigouPlan';
import { listCaigouPlan, getSupplierList, addCaigouPlan, caigouPlanDetail, updateCaigouPlan,getCount } from '@/api/wuziguanli/caigouPlan';
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
import { useRouter } from 'vue-router';
@ -384,6 +422,25 @@ const buttonLoading = ref(false);
const loading = ref(true);
const total = ref(0);
// 标签页状态变量
const activeTab = ref('all');
// 各状态数量变量
const pendingCount = ref(0);
const purchasingCount = ref(0);
const rejectedCount = ref(0);
const approvedCount = ref(0);
const completedCount = ref(0);
// 标签页切换函数
const changeTab = (tab: string) => {
activeTab.value = tab;
// 重置页码
queryParams.value.pageNum = 1;
// 重新获取列表数据
getList();
};
const initFormData: CaigouPlanForm = {
id: undefined,
projectId: undefined,
@ -405,7 +462,7 @@ const initFormData: CaigouPlanForm = {
shenheStatus: undefined,
yujiJine: undefined,
shijiJine: undefined,
opsCaigouPlanFilesBos: [],
opsCaigouPlanFilesBos: undefined,
opsCaigouPlanChanpinBos: [
{
chanpinName: '',
@ -413,9 +470,11 @@ const initFormData: CaigouPlanForm = {
chanpinMonovalent: 0,
goumaiNumber: 0,
danwei: '',
yontu: '',
totalPrice: 0
}
],
reason: undefined,
}
const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
form: { ...initFormData },
@ -441,6 +500,7 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
shenheStatus: undefined,
yujiJine: undefined,
shijiJine: undefined,
reason: undefined,
opsCaigouPlanChanpinBos: [
{
chanpinName: '',
@ -448,6 +508,7 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
chanpinMonovalent: 0,
goumaiNumber: 0,
danwei: '',
yontu: '',
totalPrice: 0
}
],
@ -457,42 +518,133 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
},
rules: {}
});
const { queryParams, form, rules } = toRefs(data);
// 查询运维-物资-采购计划单年度金额
const yearlyAmount=ref({
yujiJine: 0,
shijiJine: 0,
})
const getYearlyAmount = async () => {
try {
const res = await getCount(queryParams.value.projectId);
if (res.code === 200) {
yearlyAmount.value.shijiJine = res.data.shijiJine;
yearlyAmount.value.yujiJine = res.data.yujiJine;
}
} catch (error) {
console.error('获取年度金额失败:', error);
ElMessage({ message: '获取年度金额失败,请重试', type: 'error' });
}
}
/** 查询运维-物资-采购计划单列表 */
const getList = async () => {
loading.value = true;
const res = await listCaigouPlan(queryParams.value);
caigouPlanList.value = res.rows;
total.value = res.total;
loading.value = false;
// 创建查询参数的副本,避免直接修改原参数
const queryParamsCopy = { ...queryParams.value };
// 根据当前选中的标签页设置状态过滤条件
if (activeTab.value !== 'all') {
queryParamsCopy.status = activeTab.value;
} else {
// 如果是'全部'标签页,不设置状态过滤条件
queryParamsCopy.status = undefined;
}
try {
// 先查询所有数据来统计各状态数量
const allDataRes = await listCaigouPlan({ ...queryParamsCopy, status: undefined });
// 统计各状态数量
pendingCount.value = allDataRes.rows.filter(item => item.status === '3').length;
purchasingCount.value = allDataRes.rows.filter(item => item.status === '5').length;
rejectedCount.value = allDataRes.rows.filter(item => item.status === '7').length;
approvedCount.value = allDataRes.rows.filter(item => item.status === '9').length;
completedCount.value = allDataRes.rows.filter(item => item.status === '11').length;
total.value = allDataRes.total;
// 然后查询当前标签页的数据
const filteredRes = await listCaigouPlan(queryParamsCopy);
caigouPlanList.value = filteredRes.rows;
} catch (error) {
console.error('获取采购计划列表失败:', error);
ElMessage({ message: '获取数据失败,请重试', type: 'error' });
} finally {
loading.value = false;
}
}
// 新增采购计划单
const addCaigouPlans = async () => {
// 新增采购计划单提交函数
const addCaigouPlanSubmit = async () => {
buttonLoading.value = true; // 显示按钮加载状态
try {
// 提交表单数据到后端
const res = await addCaigouPlan(form.value);
if (res.code === 200) {
ElMessage({ message: '采购申请单已成功提交,等待审批!', type: 'success' });
// 提交成功后,删除相关的草稿
const procurementDraftStore = useProcurementDraftStore();
const draftList = procurementDraftStore.getDraftList();
// 查找并删除与当前计划名称匹配的草稿
if (form.value.jihuaName && draftList && draftList.length > 0) {
const matchingDraft = draftList.find(draft =>
draft.name === form.value.jihuaName
);
if (matchingDraft) {
procurementDraftStore.deleteDraft(matchingDraft.id);
}
}
// 刷新列表数据
getList();
// 关闭对话框并重置表单
resetNewProcurementForm();
isNewProcurementDialogVisible.value = false;
isDialogVisible.value = false;
} else {
// 显示详细的错误信息
ElMessage({
message: res.msg || '新增采购计划单失败,请重试',
ElMessage({
message: res.msg || '新增采购计划单失败,请重试',
type: 'error'
});
}
} catch (error) {
ElMessage({ message: '失败', type: 'error' });
console.error('新增采购计划单失败:', error);
ElMessage({ message: '操作失败', type: 'error' });
} finally {
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
}
}
// 更新采购计划单提交函数
const updateCaigouPlanSubmit = async () => {
buttonLoading.value = true; // 显示按钮加载状态
try {
console.log(form.value);
const res = await updateCaigouPlan(form.value);
if (res.code === 200) {
ElMessage({ message: '采购申请单已成功更新!', type: 'success' });
// 刷新列表数据
getList();
// 关闭对话框并重置表单
resetNewProcurementForm();
isDialogVisible.value = false;
} else {
// 显示详细的错误信息
ElMessage({
message: res.msg || '更新采购计划单失败,请重试',
type: 'error'
});
}
} catch (error) {
console.error('更新采购计划单失败:', error);
ElMessage({ message: '操作失败', type: 'error' });
} finally {
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
}
@ -509,12 +661,29 @@ const getSupplierLists = async () => {
supplierList.value = res.rows;
}
// 获取文件类型(后缀名)
const getFileType = (fileName: string): string => {
if (!fileName) return '';
const lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex === -1) return '';
return fileName.substring(lastDotIndex + 1).toLowerCase();
};
// 预览文件
const handlePreview = (file) => {
// 实际场景可在这里处理文件预览逻辑,如打开新窗口等
window.open(file.fileUrl, '_blank');
};
// 删除文件
const handleDelete = (file) => {
// 这里简单地从表格数据中移除该文件
form.value.opsCaigouPlanFilesBos = form.value.opsCaigouPlanFilesBos.filter(f => f !== file);
};
onMounted(() => {
getList();
getSupplierLists();
getYearlyAmount();
});
// 监听用户选择的项目变化
watch(() => userStore.selectedProject, (newProject) => {
@ -528,10 +697,16 @@ watch(() => userStore.selectedProject, (newProject) => {
getList();
}
}, { immediate: true, deep: true });
// 新建采购申请单对话框是否可见
const isNewProcurementDialogVisible = ref(false);
// 对话框是否可见
const isDialogVisible = ref(false);
// 当前操作类型:'add' 或 'update'
const currentOperation = ref('add');
// 对话框标题
const dialogTitle = computed(() => {
return currentOperation.value === 'add' ? '新建采购申请单' : '编辑采购申请单';
});
// 跳转查看详情
// 跳转查看
const handleView = (row) => {
router.push({
path: '/materialManagement/planDetails',
@ -540,6 +715,106 @@ const handleView = (row) => {
}
});
};
// 处理新增
const handleAdd = async () => {
currentOperation.value = 'add';
resetNewProcurementForm();
// 检查是否有保存的草稿
const procurementDraftStore = useProcurementDraftStore();
const draftList = procurementDraftStore.getDraftList();
if (draftList && draftList.length > 0) {
try {
// 提示用户是否恢复上次保存的草稿
await ElMessageBox.confirm(
'检测到您有未提交的草稿,是否恢复?',
'恢复草稿',
{
confirmButtonText: '恢复',
cancelButtonText: '不恢复',
type: 'info'
}
);
// 获取最新的草稿并恢复
const latestDraft = draftList[0]; // 假设列表是按创建时间降序排列的
const draftData = procurementDraftStore.getDraft(latestDraft.id);
if (draftData) {
form.value = JSON.parse(JSON.stringify(draftData.content));
// 确保产品列表和附件列表有默认值
if (!form.value.opsCaigouPlanChanpinBos || form.value.opsCaigouPlanChanpinBos.length === 0) {
form.value.opsCaigouPlanChanpinBos = [{chanpinName: '',chanpinType: '',chanpinMonovalent: '',goumaiNumber: '',danwei: '',yontu: '',totalPrice: ''}];
}
if (!form.value.opsCaigouPlanFilesBos) {
form.value.opsCaigouPlanFilesBos = [];
}
}
} catch (error) {
// 用户选择不恢复草稿,继续使用空表单
if (error !== 'cancel') {
console.error('恢复草稿时发生错误:', error);
}
}
}
isDialogVisible.value = true;
};
// 根据操作类型获取对应的提交函数
const getSubmitFunction = computed(() => {
return currentOperation.value === 'add' ? submitAddProcurement : submitUpdateProcurement;
});
// 处理编辑
const handleUpdate = async (row) => {
currentOperation.value = 'update';
buttonLoading.value = true;
try {
// 获取采购计划详情
const res = await caigouPlanDetail(row.id);
if (res.code === 200) {
// 深拷贝数据,避免直接修改原始数据
form.value = JSON.parse(JSON.stringify(res.data));
// 将数据字段从Vos后缀改为Bos后缀
if (form.value.opsCaigouPlanChanpinVos) {
form.value.opsCaigouPlanChanpinBos = form.value.opsCaigouPlanChanpinVos;
delete form.value.opsCaigouPlanChanpinVos;
}
if (form.value.opsCaigouPlanFilesVos) {
form.value.opsCaigouPlanFilesBos = form.value.opsCaigouPlanFilesVos;
delete form.value.opsCaigouPlanFilesVos;
}
console.log(form.value);
// 确保产品列表和附件列表有默认值
if (!form.value.opsCaigouPlanChanpinBos || form.value.opsCaigouPlanChanpinBos.length === 0) {
form.value.opsCaigouPlanChanpinBos = [{
chanpinName: '',
chanpinType: '',
chanpinMonovalent: 0,
goumaiNumber: 0,
danwei: '',
yontu: '',
totalPrice: 0
}];
}
if (!form.value.opsCaigouPlanFilesBos || form.value.opsCaigouPlanFilesBos.length === 0) {
form.value.opsCaigouPlanFilesBos = [];
}
// 显示对话框
isDialogVisible.value = true;
} else {
ElMessage({ message: res.msg || '获取采购计划详情失败', type: 'error' });
}
} catch (error) {
console.error('获取采购计划详情失败:', error);
ElMessage({ message: '获取采购计划详情失败', type: 'error' });
} finally {
buttonLoading.value = false;
}
};
// 计算产品总价
const calculateTotalPrice = (row) => {
if (!row.chanpinMonovalent || !row.goumaiNumber) {
@ -595,96 +870,12 @@ const resetNewProcurementForm = () => {
chanpinMonovalent: '',
goumaiNumber: '',
danwei: '',
yontu: '',
totalPrice: ''
}];
form.value.opsCaigouPlanFilesBos = [];
};
// 取消新建采购申请
const cancelNewProcurement = () => {
// 检查是否有未保存的内容
const hasContent = Object.values(form.value).some(value => {
if (Array.isArray(value)) {
return value.length > 0 &&
value.some(item =>
typeof item === 'object' &&
Object.values(item).some(v => v)
);
}
return !!value;
});
if (hasContent) {
ElMessageBox.confirm('表单内容尚未保存,确定要关闭吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
resetNewProcurementForm();
isNewProcurementDialogVisible.value = false;
});
} else {
resetNewProcurementForm();
isNewProcurementDialogVisible.value = false;
}
};
// 草稿校验函数
const validateDraft = () => {
// 草稿只需要计划名称作为必填项
if (!form.value.jihuaName.trim()) {
ElMessage({ message: '请填写计划名称', type: 'error' });
return false;
}
// 检查已填写的产品信息的有效性
for (let i = 0; i < form.value.opsCaigouPlanChanpinBos.length; i++) {
const product = form.value.opsCaigouPlanChanpinBos[i];
if (product.chanpinName && !product.chanpinType) {
ElMessage({ message: `${i + 1}行产品:填写了产品名称,请也填写产品型号`, type: 'warning' });
}
if (product.productPrice && parseFloat(product.productPrice) <= 0) {
ElMessage({ message: `${i + 1}行产品产品单价应大于0`, type: 'warning' });
}
if (product.purchaseQuantity && parseInt(product.purchaseQuantity) <= 0) {
ElMessage({ message: `${i + 1}行产品购买数量应大于0`, type: 'warning' });
}
}
return true;
};
// 保存草稿
const saveDraft = async () => {
// 验证草稿
if (!validateDraft()) {
return;
}
buttonLoading.value = true; // 显示按钮加载状态
try {
// 使用pinia store保存草稿
const draftStore = useProcurementDraftStore();
const savedDraft = draftStore.saveDraft(form.value.jihuaName, form.value);
console.log('保存草稿:', {
draftNumber: savedDraft.draftNumber,
saveTime: savedDraft.saveTime,
content: savedDraft.content
});
ElMessage({ message: `草稿已成功保存(编号:${savedDraft.draftNumber}),您可以在草稿箱中查看`, type: 'success' });
} catch (error) {
console.error('保存草稿失败:', error);
ElMessage({
message: '保存草稿失败,请重试',
type: 'error'
});
} finally {
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
}
};
// 表单校验函数
const validateForm = () => {
// 基础信息校验
@ -717,14 +908,18 @@ const validateForm = () => {
ElMessage({ message: '请选择供应商单位', type: 'error' });
return false;
}
if (!form.value.reason) {
ElMessage({ message: '请填写申请原因', type: 'error' });
return false;
}
// 产品信息校验
const hasValidProduct = form.value.opsCaigouPlanChanpinBos.some(product => {
return product.chanpinName &&
product.chanpinType &&
product.chanpinMonovalent && parseFloat(product.chanpinMonovalent) > 0 &&
product.goumaiNumber && parseInt(product.goumaiNumber) > 0 &&
product.danwei;
product.danwei &&
product.yontu;
});
if (!hasValidProduct) {
@ -764,14 +959,51 @@ const validateForm = () => {
ElMessage({ message: `${i + 1}行产品:请填写单位`, type: 'error' });
return false;
}
if (!product.yontu) {
ElMessage({ message: `${i + 1}行产品:请填写用途`, type: 'error' });
return false;
}
}
}
return true;
};
// 提交申请
const submitProcurement = async () => {
// 新增申请提交
const submitAddProcurement = async () => {
// 在提交前,为所有产品行重新计算并保存总价
form.value.opsCaigouPlanChanpinBos.forEach(product => {
calculateTotalPrice(product);
});
// 表单验证
if (!validateForm()) {
return;
}
try {
// 确认提交
await ElMessageBox.confirm(
'确定要提交采购申请单吗?提交后将进入审批流程,不可撤销。',
'确认操作',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}
);
// 调用新增提交函数
await addCaigouPlanSubmit();
} catch (error) {
// 处理用户取消或其他错误
if (error !== 'cancel') {
console.error('提交采购申请单时发生错误:', error);
ElMessage({ message: '提交过程中发生错误,请重试', type: 'error' });
}
}
}
// 更新申请提交
const submitUpdateProcurement = async () => {
// 在提交前,为所有产品行重新计算并保存总价
form.value.opsCaigouPlanChanpinBos.forEach(product => {
calculateTotalPrice(product);
@ -785,27 +1017,26 @@ const submitProcurement = async () => {
try {
// 确认提交
await ElMessageBox.confirm(
'确定要提交采购申请单吗?提交后将进入审批流程,不可撤销。',
'确认提交',
'确定要更新采购申请单吗?',
'确认操作',
{
confirmButtonText: '确认提交',
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}
);
// 调用提交函数
await addCaigouPlans();
// 调用更新提交函数
await updateCaigouPlanSubmit();
} catch (error) {
// 处理用户取消或其他错误
if (error !== 'cancel') {
console.error('提交采购申请单时发生错误:', error);
ElMessage({ message: '提交过程中发生错误,请重试', type: 'error' });
console.error('更新采购申请单时发生错误:', error);
ElMessage({ message: '更新过程中发生错误,请重试', type: 'error' });
}
}
}
// });
// 处理文件上传完成后获取完整文件列表
const handleUpdateFileList = (fileList) => {
@ -815,4 +1046,118 @@ const handleUpdateFileList = (fileList) => {
fileUrl: file.url,
}));
};
// 检查表单是否有内容
const hasFormContent = () => {
// 检查基础信息字段
if (form.value.jihuaName ||
form.value.hetonName ||
form.value.hetonType ||
form.value.caigouType ||
form.value.cangkuUrl ||
form.value.danwei ||
form.value.chuhuoTime ||
form.value.fukuantiaojian ||
form.value.fapiaoKjfs ||
form.value.reason) {
return true;
}
// 检查产品信息
if (form.value.opsCaigouPlanChanpinBos) {
for (const product of form.value.opsCaigouPlanChanpinBos) {
if (product.chanpinName ||
product.chanpinType ||
product.chanpinMonovalent ||
product.goumaiNumber ||
product.danwei ||
product.yontu) {
return true;
}
}
}
// 检查附件
if (form.value.opsCaigouPlanFilesBos && form.value.opsCaigouPlanFilesBos.length > 0) {
return true;
}
return false;
};
// 取消操作
const cancelOperation = async () => {
// 检查是否有表单内容
if (hasFormContent()) {
try {
// 提示用户确认是否放弃编辑
await ElMessageBox.confirm(
'您有未保存的内容,确定要取消吗?',
'确认取消',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
);
// 重置表单
resetNewProcurementForm();
// 关闭对话框
isDialogVisible.value = false;
} catch (error) {
// 用户取消了确认操作
if (error !== 'cancel') {
console.error('取消操作时发生错误:', error);
}
// 不执行任何操作,保持对话框打开
}
} else {
// 没有表单内容,直接关闭对话框并重置
resetNewProcurementForm();
isDialogVisible.value = false;
}
};
// 保存草稿
const saveDraft = async () => {
buttonLoading.value = true;
try {
// 检查是否有计划名称
if (!form.value.jihuaName || !form.value.jihuaName.trim()) {
ElMessage({ message: '请填写计划名称后再保存草稿', type: 'warning' });
return;
}
// 获取草稿存储
const procurementDraftStore = useProcurementDraftStore();
// 保存草稿到pinia存储
const savedDraft = procurementDraftStore.saveDraft(form.value.jihuaName, form.value);
// 显示成功消息
ElMessage({ message: '草稿保存成功', type: 'success' });
// 关闭对话框
isDialogVisible.value = false;
} catch (error) {
console.error('保存草稿失败:', error);
ElMessage({ message: '草稿保存失败,请重试', type: 'error' });
} finally {
buttonLoading.value = false;
}
};
// 组件卸载时清除草稿
onUnmounted(() => {
try {
// 获取草稿存储
const procurementDraftStore = useProcurementDraftStore();
// 清除所有草稿
procurementDraftStore.clearAllDrafts();
} catch (error) {
console.error('组件卸载时清除草稿失败:', error);
// 这里不显示错误消息,因为组件已经卸载
}
});
</script>