2025-09-20 20:38:57 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="procurementPlan">
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-row :gutter="20">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-col :span="13">
|
|
|
|
|
|
<el-card>
|
|
|
|
|
|
<div style="display: flex;align-items: center;height: 120px;justify-content: space-around;">
|
|
|
|
|
|
<div class="img">
|
|
|
|
|
|
<img src="/assets/caigou.png" alt="">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
待审批计划
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(255, 178, 30, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ pendingCount }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
已批准计划
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ approvedCount }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
采购中计划
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(113, 214, 213, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ purchasingCount }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
已完成计划
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(0, 184, 122, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ completedCount }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="11">
|
|
|
|
|
|
<el-card>
|
|
|
|
|
|
<div style="display: flex;align-items: center;height: 120px;justify-content: space-around;">
|
|
|
|
|
|
<div class="img">
|
|
|
|
|
|
<img src="/assets/qian.jpg" alt="">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
本年度已采购金额
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(255, 153, 0, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ yearlyAmount.shijiJine }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="item">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
本年度采购预算金额
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
{{ yearlyAmount.yujiJine }}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
<el-row style="margin-top: 20px;">
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
<el-card style="border-radius: 10px;">
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<div class="tabs">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<!-- <el-button type="success">导出</el-button> -->
|
|
|
|
|
|
<el-button type="primary" @click="handleAdd">新建采购申请单</el-button>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 标签页导航 -->
|
|
|
|
|
|
<div class="tabs">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-badge :value="total" type="success">
|
|
|
|
|
|
<el-button :type="activeTab === 'all' ? 'primary' : ''"
|
|
|
|
|
|
@click="changeTab('all')">全部</el-button>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
</el-badge>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<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>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
</el-badge>
|
|
|
|
|
|
<el-badge :value="rejectedCount" type="danger">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-button :type="activeTab === '7' ? 'primary' : ''"
|
|
|
|
|
|
@click="changeTab('7')">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
未通过
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-badge>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-badge :value="approvedCount" type="success">
|
|
|
|
|
|
<el-button :type="activeTab === '9' ? 'primary' : ''"
|
|
|
|
|
|
@click="changeTab('9')">已通过</el-button>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
</el-badge>
|
|
|
|
|
|
<el-badge :value="completedCount" type="success">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-button :type="activeTab === '11' ? 'primary' : ''"
|
|
|
|
|
|
@click="changeTab('11')">已完成</el-button>
|
|
|
|
|
|
</el-badge>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 表格 -->
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table :data="caigouPlanList" border style="width: 100%;margin-top: 15px;">
|
|
|
|
|
|
<el-table-column label="计划编号" align="center" prop="jihuaBianhao" />
|
|
|
|
|
|
<el-table-column label="计划名称" align="center" prop="jihuaName" />
|
|
|
|
|
|
<el-table-column label="申请部门" align="center" prop="caigouDanweiName" />
|
|
|
|
|
|
<el-table-column label="申请人" align="center" prop="jingbanrenName" />
|
|
|
|
|
|
<el-table-column prop="createTime" label="申请日期" align="center" />
|
|
|
|
|
|
<el-table-column label="预计金额" align="center" prop="yujiJine" />
|
|
|
|
|
|
<el-table-column label="状态" align="center" prop="status">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<dict-tag :options="wz_caigou_examine" :value="scope.row.status" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-table-column label="操作" fixed="right" align="center">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-10-09 20:22:04 +08:00
|
|
|
|
<el-button link @click="handleView(scope.row)">查看</el-button>
|
|
|
|
|
|
<el-button link @click="handleUpdate(scope.row)">编辑</el-button>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分页 -->
|
|
|
|
|
|
<div class="pagination-section">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
|
|
|
|
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
2025-09-30 17:40:31 +08:00
|
|
|
|
<!-- 添加、修改弹窗 -->
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-dialog v-model="isDialogVisible" :title="dialogTitle" width="60%" :close-on-click-modal="false">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<div class="new-procurement-form">
|
|
|
|
|
|
<!-- 基础信息 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<h3>基础信息</h3>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<!-- 输入框行 -->
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-row :gutter="20">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-col :span="8">
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-form-item label="计划名称">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="form.jihuaName" placeholder="请填写计划名称" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-col :span="8">
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-form-item label="合同名称">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="form.hetonName" placeholder="请填写合同名称" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-col :span="8">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-form-item label="合同类型">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-select v-model="form.hetonType" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in wz_contract_type" :key="option.value"
|
|
|
|
|
|
:label="option.label" :value="option.value" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
</el-row>
|
|
|
|
|
|
<!-- 下拉框行 -->
|
|
|
|
|
|
<el-row :gutter="20">
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-col :span="8">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-form-item label="采购类型">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-select v-model="form.caigouType" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in wz_purchase_type" :key="option.value"
|
|
|
|
|
|
:label="option.label" :value="option.value" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-col :span="8">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-form-item label="仓库地址">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="form.cangkuUrl" placeholder="请输入仓库地址" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<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>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 供应商信息 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<h3>供应商信息</h3>
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
|
<el-form-item label="供应商单位">
|
2025-09-29 20:09:20 +08:00
|
|
|
|
<el-select v-model="form.gonyingshangId" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in supplierList" :key="option.id" :label="option.supplierName"
|
|
|
|
|
|
:value="option.id" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
|
<el-form-item label="送货时间">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-date-picker v-model="form.chuhuoTime" type="date" placeholder="请选择送货日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD" style="width: 100%" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 产品信息 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<h3>产品信息</h3>
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table :data="form.opsCaigouPlanChanpinBos" border style="width: 100%">
|
|
|
|
|
|
<el-table-column prop="chanpinName" label="产品名称">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="scope.row.chanpinName" placeholder="请填写" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table-column prop="chanpinType" label="产品型号">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="scope.row.chanpinType" placeholder="请填写" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
2025-09-30 17:40:31 +08:00
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="shebeiType" label="设备类型">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-select v-model="scope.row.shebeiType" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in wz_device_type" :key="option.value"
|
|
|
|
|
|
:label="option.label" :value="option.value" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</template>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-table-column>
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table-column prop="chanpinMonovalent" label="产品单价">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="scope.row.chanpinMonovalent" placeholder="请填写" type="number"
|
2025-09-28 20:04:30 +08:00
|
|
|
|
@change="calculateTotalPrice(scope.row)" min="0" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table-column prop="goumaiNumber" label="购买数量">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="scope.row.goumaiNumber" placeholder="请填写" type="number"
|
2025-09-28 20:04:30 +08:00
|
|
|
|
@change="calculateTotalPrice(scope.row)" min="0" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-table-column prop="danwei" label="单位">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-input v-model="scope.row.danwei" placeholder="请填写" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<el-table-column prop="yontu" label="用途(简要描述)">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-input v-model="scope.row.yontu" placeholder="请填写" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
<el-table-column prop="totalPrice" label="合计" :formatter="calculateTotalPrice">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<span>{{ calculateTotalPrice(scope.row) }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="操作" fixed="right" width="80">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button type="text" @click="removeProduct(scope.$index)"
|
2025-09-26 20:05:38 +08:00
|
|
|
|
:disabled="form.opsCaigouPlanChanpinBos.length <= 1">删除</el-button>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
<el-button type="primary" size="small" @click="addProduct" style="margin-top: 10px">添加产品</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 合同条款 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<h3>合同条款</h3>
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
<el-col :span="6">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-form-item label="付款方式">
|
|
|
|
|
|
<el-select v-model="form.fukuantiaojian" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in wz_payment_terms" :key="option.value"
|
|
|
|
|
|
:label="option.label" :value="option.value" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="6">
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<el-form-item label="发票开具方式">
|
2025-09-26 20:05:38 +08:00
|
|
|
|
<el-select v-model="form.fapiaoKjfs" placeholder="请选择">
|
|
|
|
|
|
<el-option v-for="option in wz_invoicing_way" :key="option.value"
|
|
|
|
|
|
:label="option.label" :value="option.value" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 附件上传 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<h3>附件上传</h3>
|
2025-09-30 17:40:31 +08:00
|
|
|
|
<FileUpload ref="fileUploadRef" :isDrag="true" v-model="form.opsCaigouPlanFilesBos"
|
2025-09-29 20:09:20 +08:00
|
|
|
|
:is-show-tip="false"
|
2025-09-26 20:05:38 +08:00
|
|
|
|
:file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf', 'png', 'jpg', 'jpeg']" />
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
<div class="dialog-footer">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
<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>
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
2025-09-30 17:40:31 +08:00
|
|
|
|
<style scoped lang="scss">
|
2025-09-20 20:38:57 +08:00
|
|
|
|
.procurementPlan {
|
|
|
|
|
|
background-color: #F2F8FC;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.img {
|
|
|
|
|
|
img {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 80px;
|
|
|
|
|
|
height: 80px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
.text {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.count {
|
|
|
|
|
|
font-size: 25px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.tabs {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content {
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 分页区域样式 */
|
|
|
|
|
|
.pagination-section {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-top: 15px;
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination button {
|
|
|
|
|
|
min-width: 32px;
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination .el-pager li {
|
|
|
|
|
|
min-width: 32px;
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination .el-pager li.active {
|
|
|
|
|
|
background-color: #409eff;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
2025-09-24 20:06:58 +08:00
|
|
|
|
<script setup lang="ts">
|
2025-09-28 20:04:30 +08:00
|
|
|
|
import { ref, reactive, computed, getCurrentInstance, onUnmounted } from 'vue';
|
2025-09-20 20:38:57 +08:00
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
2025-09-24 20:06:58 +08:00
|
|
|
|
import { useProcurementDraftStore } from '@/store/modules/procurementDraft';
|
2025-09-30 17:40:31 +08:00
|
|
|
|
import { } from '@/views/materialManagement/components/upload.vue'
|
2025-09-24 20:06:58 +08:00
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
2025-09-30 17:40:31 +08:00
|
|
|
|
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type, wz_caigou_examine,wz_device_type } = toRefs<any>(proxy?.useDict('wz_device_type','wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
import { listCaigouPlan, getSupplierList, addCaigouPlan, caigouPlanDetail, updateCaigouPlan,getCount } from '@/api/wuziguanli/caigouPlan';
|
2025-09-26 20:05:38 +08:00
|
|
|
|
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
|
2025-09-24 20:06:58 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
import { useRouter } from 'vue-router';
|
2025-09-20 20:38:57 +08:00
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
import FileUpload from '@/views/materialManagement/components/upload.vue';
|
2025-09-29 20:09:20 +08:00
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
// 导入用户store
|
|
|
|
|
|
import { useUserStore } from '@/store/modules/user';
|
|
|
|
|
|
// 获取用户store
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
|
|
|
|
const caigouPlanList = ref<CaigouPlanVO[]>([]);
|
|
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
|
|
const loading = ref(true);
|
|
|
|
|
|
const total = ref(0);
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 文件上传组件引用
|
|
|
|
|
|
const fileUploadRef = ref<InstanceType<typeof FileUpload>>();
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 标签页状态变量
|
|
|
|
|
|
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();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
const initFormData: CaigouPlanForm = {
|
|
|
|
|
|
id: undefined,
|
|
|
|
|
|
projectId: undefined,
|
|
|
|
|
|
jihuaName: undefined,
|
|
|
|
|
|
jihuaBianhao: undefined,
|
|
|
|
|
|
caigouDanwei: undefined,
|
|
|
|
|
|
caigouDanweiName: undefined,
|
|
|
|
|
|
jingbanren: undefined,
|
|
|
|
|
|
jingbanrenName: undefined,
|
|
|
|
|
|
hetonType: undefined,
|
|
|
|
|
|
caigouType: undefined,
|
|
|
|
|
|
cangkuUrl: undefined,
|
|
|
|
|
|
hetonName: undefined,
|
2025-09-29 20:09:20 +08:00
|
|
|
|
gonyingshangId: undefined,
|
2025-09-26 20:05:38 +08:00
|
|
|
|
chuhuoTime: undefined,
|
|
|
|
|
|
fukuantiaojian: undefined,
|
|
|
|
|
|
fapiaoKjfs: undefined,
|
|
|
|
|
|
status: undefined,
|
|
|
|
|
|
shenheStatus: undefined,
|
|
|
|
|
|
yujiJine: undefined,
|
|
|
|
|
|
shijiJine: undefined,
|
2025-09-28 20:04:30 +08:00
|
|
|
|
opsCaigouPlanFilesBos: undefined,
|
2025-09-26 20:05:38 +08:00
|
|
|
|
opsCaigouPlanChanpinBos: [
|
|
|
|
|
|
{
|
|
|
|
|
|
chanpinName: '',
|
|
|
|
|
|
chanpinType: '',
|
|
|
|
|
|
chanpinMonovalent: 0,
|
|
|
|
|
|
goumaiNumber: 0,
|
|
|
|
|
|
danwei: '',
|
2025-09-28 20:04:30 +08:00
|
|
|
|
yontu: '',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
totalPrice: 0
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
2025-09-28 20:04:30 +08:00
|
|
|
|
reason: undefined,
|
2025-09-26 20:05:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
|
|
|
|
|
|
form: { ...initFormData },
|
|
|
|
|
|
queryParams: {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
projectId: undefined,
|
|
|
|
|
|
jihuaName: undefined,
|
|
|
|
|
|
jihuaBianhao: undefined,
|
|
|
|
|
|
caigouDanwei: undefined,
|
|
|
|
|
|
caigouDanweiName: undefined,
|
|
|
|
|
|
jingbanren: undefined,
|
|
|
|
|
|
jingbanrenName: undefined,
|
|
|
|
|
|
hetonType: undefined,
|
|
|
|
|
|
caigouType: undefined,
|
|
|
|
|
|
cangkuUrl: undefined,
|
|
|
|
|
|
hetonName: undefined,
|
2025-09-29 20:09:20 +08:00
|
|
|
|
gonyingshangId: undefined,
|
2025-09-26 20:05:38 +08:00
|
|
|
|
chuhuoTime: undefined,
|
|
|
|
|
|
fukuantiaojian: undefined,
|
|
|
|
|
|
fapiaoKjfs: undefined,
|
|
|
|
|
|
status: undefined,
|
|
|
|
|
|
shenheStatus: undefined,
|
|
|
|
|
|
yujiJine: undefined,
|
|
|
|
|
|
shijiJine: undefined,
|
2025-09-28 20:04:30 +08:00
|
|
|
|
reason: undefined,
|
2025-09-26 20:05:38 +08:00
|
|
|
|
opsCaigouPlanChanpinBos: [
|
|
|
|
|
|
{
|
|
|
|
|
|
chanpinName: '',
|
|
|
|
|
|
chanpinType: '',
|
|
|
|
|
|
chanpinMonovalent: 0,
|
|
|
|
|
|
goumaiNumber: 0,
|
|
|
|
|
|
danwei: '',
|
2025-09-28 20:04:30 +08:00
|
|
|
|
yontu: '',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
totalPrice: 0
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
opsCaigouPlanFilesBos: undefined,
|
|
|
|
|
|
params: {
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
rules: {}
|
2025-09-24 20:06:58 +08:00
|
|
|
|
});
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
const { queryParams, form, rules } = toRefs(data);
|
|
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 查询运维-物资-采购计划单年度金额
|
|
|
|
|
|
const yearlyAmount=ref({
|
|
|
|
|
|
yujiJine: 0,
|
|
|
|
|
|
shijiJine: 0,
|
|
|
|
|
|
})
|
|
|
|
|
|
const getYearlyAmount = async () => {
|
|
|
|
|
|
try {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 检查项目ID是否存在
|
|
|
|
|
|
if (!queryParams.value.projectId) {
|
|
|
|
|
|
ElMessage({ message: '项目ID不能为空', type: 'warning' });
|
|
|
|
|
|
// 重置年度金额数据
|
|
|
|
|
|
yearlyAmount.value = {
|
|
|
|
|
|
yujiJine: 0,
|
|
|
|
|
|
shijiJine: 0
|
|
|
|
|
|
};
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
const res = await getCount(queryParams.value.projectId);
|
2025-09-30 17:40:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查响应数据结构
|
|
|
|
|
|
if (res && res.code === 200 && res.data) {
|
|
|
|
|
|
// 确保金额数据有效
|
|
|
|
|
|
yearlyAmount.value.shijiJine = res.data.shijiJine || 0;
|
|
|
|
|
|
yearlyAmount.value.yujiJine = res.data.yujiJine || 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ElMessage({ message: '获取年度金额数据格式异常', type: 'error' });
|
|
|
|
|
|
console.error('获取年度金额响应数据异常:', res);
|
|
|
|
|
|
// 重置年度金额数据
|
|
|
|
|
|
yearlyAmount.value = {
|
|
|
|
|
|
yujiJine: 0,
|
|
|
|
|
|
shijiJine: 0
|
|
|
|
|
|
};
|
2025-09-28 20:04:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('获取年度金额失败:', error);
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({ message: '获取年度金额失败,请重试', type: 'error' });
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 重置年度金额数据,避免显示错误数据
|
|
|
|
|
|
yearlyAmount.value = {
|
|
|
|
|
|
yujiJine: 0,
|
|
|
|
|
|
shijiJine: 0
|
|
|
|
|
|
};
|
2025-09-28 20:04:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
/** 查询运维-物资-采购计划单列表 */
|
|
|
|
|
|
const getList = async () => {
|
|
|
|
|
|
loading.value = true;
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 创建查询参数的副本,避免直接修改原参数
|
|
|
|
|
|
const queryParamsCopy = { ...queryParams.value };
|
|
|
|
|
|
|
|
|
|
|
|
// 根据当前选中的标签页设置状态过滤条件
|
|
|
|
|
|
if (activeTab.value !== 'all') {
|
|
|
|
|
|
queryParamsCopy.status = activeTab.value;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果是'全部'标签页,不设置状态过滤条件
|
|
|
|
|
|
queryParamsCopy.status = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 检查项目ID是否存在
|
|
|
|
|
|
if (!queryParamsCopy.projectId) {
|
|
|
|
|
|
ElMessage({ message: '项目ID不能为空', type: 'warning' });
|
|
|
|
|
|
// 重置统计数据
|
|
|
|
|
|
pendingCount.value = 0;
|
|
|
|
|
|
purchasingCount.value = 0;
|
|
|
|
|
|
rejectedCount.value = 0;
|
|
|
|
|
|
approvedCount.value = 0;
|
|
|
|
|
|
completedCount.value = 0;
|
|
|
|
|
|
total.value = 0;
|
|
|
|
|
|
caigouPlanList.value = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 先查询所有数据来统计各状态数量
|
|
|
|
|
|
const allDataRes = await listCaigouPlan({ ...queryParamsCopy, status: undefined });
|
|
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 检查响应数据结构
|
|
|
|
|
|
if (allDataRes && allDataRes.code === 200 && Array.isArray(allDataRes.rows)) {
|
|
|
|
|
|
// 统计各状态数量
|
|
|
|
|
|
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 || 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 然后查询当前标签页的数据
|
|
|
|
|
|
const filteredRes = await listCaigouPlan(queryParamsCopy);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查过滤后的数据结构
|
|
|
|
|
|
if (filteredRes && filteredRes.code === 200 && Array.isArray(filteredRes.rows)) {
|
|
|
|
|
|
caigouPlanList.value = filteredRes.rows;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ElMessage({ message: '获取过滤后的数据格式异常', type: 'error' });
|
|
|
|
|
|
console.error('获取过滤后的数据响应异常:', filteredRes);
|
|
|
|
|
|
caigouPlanList.value = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ElMessage({ message: '获取统计数据格式异常', type: 'error' });
|
|
|
|
|
|
console.error('获取统计数据响应异常:', allDataRes);
|
|
|
|
|
|
// 重置统计数据
|
|
|
|
|
|
pendingCount.value = 0;
|
|
|
|
|
|
purchasingCount.value = 0;
|
|
|
|
|
|
rejectedCount.value = 0;
|
|
|
|
|
|
approvedCount.value = 0;
|
|
|
|
|
|
completedCount.value = 0;
|
|
|
|
|
|
total.value = 0;
|
|
|
|
|
|
caigouPlanList.value = [];
|
|
|
|
|
|
}
|
2025-09-28 20:04:30 +08:00
|
|
|
|
} catch (error) {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('获取采购计划列表失败:', error);
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({ message: '获取数据失败,请重试', type: 'error' });
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 重置统计数据,避免显示错误数据
|
|
|
|
|
|
pendingCount.value = 0;
|
|
|
|
|
|
purchasingCount.value = 0;
|
|
|
|
|
|
rejectedCount.value = 0;
|
|
|
|
|
|
approvedCount.value = 0;
|
|
|
|
|
|
completedCount.value = 0;
|
|
|
|
|
|
total.value = 0;
|
|
|
|
|
|
caigouPlanList.value = [];
|
2025-09-28 20:04:30 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
}
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 新增采购计划单提交函数
|
|
|
|
|
|
const addCaigouPlanSubmit = async () => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
buttonLoading.value = true; // 显示按钮加载状态
|
|
|
|
|
|
try {
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 创建表单数据的深拷贝,避免直接修改原表单数据
|
|
|
|
|
|
const submitData = JSON.parse(JSON.stringify(form.value));
|
|
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 数据完整性检查
|
|
|
|
|
|
if (!submitData || !submitData.projectId) {
|
|
|
|
|
|
ElMessage({ message: '项目信息不完整,无法提交', type: 'error' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提交数据前确保文件列表格式正确
|
|
|
|
|
|
if (submitData.opsCaigouPlanFilesBos === undefined) {
|
|
|
|
|
|
submitData.opsCaigouPlanFilesBos = [];
|
2025-09-29 20:09:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const res = await addCaigouPlan(submitData);
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 检查响应数据结构
|
|
|
|
|
|
if (res && res.code === 200) {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
ElMessage({ message: '采购申请单已成功提交,等待审批!', type: 'success' });
|
|
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 提交成功后,删除相关的草稿
|
|
|
|
|
|
const procurementDraftStore = useProcurementDraftStore();
|
|
|
|
|
|
const draftList = procurementDraftStore.getDraftList();
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
2025-09-30 17:40:31 +08:00
|
|
|
|
// 查找并删除与当前计划名称匹配的草稿
|
|
|
|
|
|
if (form.value.jihuaName && draftList && draftList.length > 0) {
|
|
|
|
|
|
const matchingDraft = draftList.find(draft =>
|
|
|
|
|
|
draft.name === form.value.jihuaName
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (matchingDraft) {
|
|
|
|
|
|
procurementDraftStore.deleteDraft(matchingDraft.id);
|
|
|
|
|
|
}
|
2025-09-28 20:04:30 +08:00
|
|
|
|
}
|
2025-09-30 17:40:31 +08:00
|
|
|
|
} catch (draftError) {
|
|
|
|
|
|
console.error('删除草稿时发生错误:', draftError);
|
|
|
|
|
|
// 草稿删除失败不应影响主流程
|
2025-09-28 20:04:30 +08:00
|
|
|
|
}
|
2025-09-30 17:40:31 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
// 刷新列表数据
|
2025-09-30 17:40:31 +08:00
|
|
|
|
await getList();
|
|
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
// 关闭对话框并重置表单
|
|
|
|
|
|
resetNewProcurementForm();
|
2025-09-28 20:04:30 +08:00
|
|
|
|
isDialogVisible.value = false;
|
2025-09-26 20:05:38 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 显示详细的错误信息
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('新增采购计划单失败:', res);
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({
|
2025-09-30 17:40:31 +08:00
|
|
|
|
message: res?.msg || '新增采购计划单失败,请重试',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
type: 'error'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('新增采购计划单操作异常:', error);
|
|
|
|
|
|
// 根据错误类型提供更具体的错误信息
|
|
|
|
|
|
let errorMessage = '操作失败';
|
|
|
|
|
|
if (error.message) {
|
|
|
|
|
|
errorMessage = `操作失败: ${error.message}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
ElMessage({ message: errorMessage, type: 'error' });
|
2025-09-28 20:04:30 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新采购计划单提交函数
|
|
|
|
|
|
const updateCaigouPlanSubmit = async () => {
|
|
|
|
|
|
buttonLoading.value = true; // 显示按钮加载状态
|
|
|
|
|
|
try {
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 创建表单数据的深拷贝,避免直接修改原表单数据
|
|
|
|
|
|
const submitData = JSON.parse(JSON.stringify(form.value));
|
2025-09-30 17:40:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 数据完整性检查
|
|
|
|
|
|
if (!submitData || !submitData.id || !submitData.projectId) {
|
|
|
|
|
|
ElMessage({ message: '计划ID或项目信息不完整,无法更新', type: 'error' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提交数据前确保文件列表格式正确
|
|
|
|
|
|
if (submitData.opsCaigouPlanFilesBos === undefined) {
|
|
|
|
|
|
submitData.opsCaigouPlanFilesBos = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 20:09:20 +08:00
|
|
|
|
const res = await updateCaigouPlan(submitData);
|
2025-09-30 17:40:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查响应数据结构
|
|
|
|
|
|
if (res && res.code === 200) {
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({ message: '采购申请单已成功更新!', type: 'success' });
|
2025-09-30 17:40:31 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 刷新列表数据
|
2025-09-30 17:40:31 +08:00
|
|
|
|
await getList();
|
|
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 关闭对话框并重置表单
|
|
|
|
|
|
resetNewProcurementForm();
|
|
|
|
|
|
isDialogVisible.value = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 显示详细的错误信息
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('更新采购计划单失败:', res);
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({
|
2025-09-30 17:40:31 +08:00
|
|
|
|
message: res?.msg || '更新采购计划单失败,请重试',
|
2025-09-28 20:04:30 +08:00
|
|
|
|
type: 'error'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
console.error('更新采购计划单操作异常:', error);
|
|
|
|
|
|
// 根据错误类型提供更具体的错误信息
|
|
|
|
|
|
let errorMessage = '操作失败';
|
|
|
|
|
|
if (error.message) {
|
|
|
|
|
|
errorMessage = `操作失败: ${error.message}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
ElMessage({ message: errorMessage, type: 'error' });
|
2025-09-26 20:05:38 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-24 20:06:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
// 采购商列表
|
|
|
|
|
|
const supplierList = ref([]);
|
|
|
|
|
|
const getSupplierLists = async () => {
|
2025-09-30 17:40:31 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 检查项目ID是否存在
|
|
|
|
|
|
if (!userStore.selectedProject || !userStore.selectedProject.id) {
|
|
|
|
|
|
ElMessage({ message: '请先选择项目', type: 'warning' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const res = await getSupplierList({
|
|
|
|
|
|
projectId: userStore.selectedProject.id
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 检查响应数据结构
|
|
|
|
|
|
if (res && res.code === 200 && Array.isArray(res.data)) {
|
|
|
|
|
|
supplierList.value = res.data;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ElMessage({ message: '获取供应商列表数据格式异常', type: 'error' });
|
|
|
|
|
|
console.error('获取供应商列表响应数据异常:', res);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取供应商列表失败:', error);
|
|
|
|
|
|
ElMessage({ message: '获取供应商列表失败,请重试', type: 'error' });
|
|
|
|
|
|
// 在严重错误情况下清空列表,避免显示错误数据
|
|
|
|
|
|
supplierList.value = [];
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
}
|
2025-09-20 20:38:57 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
getList();
|
|
|
|
|
|
getSupplierLists();
|
2025-09-28 20:04:30 +08:00
|
|
|
|
getYearlyAmount();
|
2025-09-26 20:05:38 +08:00
|
|
|
|
});
|
|
|
|
|
|
// 监听用户选择的项目变化
|
|
|
|
|
|
watch(() => userStore.selectedProject, (newProject) => {
|
|
|
|
|
|
if (newProject && newProject.id) {
|
|
|
|
|
|
queryParams.value.projectId = newProject.id;
|
|
|
|
|
|
// 只在新增表单时设置projectId,编辑表单保留原有值
|
|
|
|
|
|
if (!form.value.id) {
|
|
|
|
|
|
form.value.projectId = newProject.id;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 调用getList刷新数据
|
|
|
|
|
|
getList();
|
2025-09-30 17:40:31 +08:00
|
|
|
|
getYearlyAmount();
|
2025-09-20 20:38:57 +08:00
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
}, { immediate: true, deep: true });
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 对话框是否可见
|
|
|
|
|
|
const isDialogVisible = ref(false);
|
|
|
|
|
|
// 当前操作类型:'add' 或 'update'
|
|
|
|
|
|
const currentOperation = ref('add');
|
|
|
|
|
|
// 对话框标题
|
|
|
|
|
|
const dialogTitle = computed(() => {
|
|
|
|
|
|
return currentOperation.value === 'add' ? '新建采购申请单' : '编辑采购申请单';
|
|
|
|
|
|
});
|
2025-09-20 20:38:57 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 跳转查看
|
2025-09-20 20:38:57 +08:00
|
|
|
|
const handleView = (row) => {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/materialManagement/planDetails',
|
|
|
|
|
|
query: {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
id: row.id
|
2025-09-20 20:38:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 处理新增
|
|
|
|
|
|
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) {
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 转换文件数据格式为FileUpload组件期望的格式
|
|
|
|
|
|
form.value.opsCaigouPlanFilesBos = form.value.opsCaigouPlanFilesVos.map(file => ({
|
|
|
|
|
|
ossId: file.fileId,
|
|
|
|
|
|
name: file.fileName,
|
|
|
|
|
|
url: file.fileUrl
|
|
|
|
|
|
}));
|
2025-09-28 20:04:30 +08:00
|
|
|
|
delete form.value.opsCaigouPlanFilesVos;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 确保产品列表和附件列表有默认值
|
|
|
|
|
|
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) {
|
|
|
|
|
|
ElMessage({ message: '获取采购计划详情失败', type: 'error' });
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2025-09-24 20:06:58 +08:00
|
|
|
|
// 计算产品总价
|
|
|
|
|
|
const calculateTotalPrice = (row) => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!row.chanpinMonovalent || !row.goumaiNumber) {
|
|
|
|
|
|
row.totalPrice = '0.00'; // 保存计算结果到对象中
|
2025-09-24 20:06:58 +08:00
|
|
|
|
return '0.00';
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
const price = parseFloat(row.chanpinMonovalent);
|
|
|
|
|
|
const quantity = parseInt(row.goumaiNumber);
|
2025-09-24 20:06:58 +08:00
|
|
|
|
if (isNaN(price) || isNaN(quantity)) {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
row.totalPrice = '0.00'; // 保存计算结果到对象中
|
2025-09-24 20:06:58 +08:00
|
|
|
|
return '0.00';
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
const result = (price * quantity).toFixed(2);
|
|
|
|
|
|
row.totalPrice = result; // 保存计算结果到对象中
|
|
|
|
|
|
return result;
|
2025-09-24 20:06:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 添加产品
|
|
|
|
|
|
const addProduct = () => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
form.value.opsCaigouPlanChanpinBos.push({
|
|
|
|
|
|
chanpinName: '',
|
|
|
|
|
|
chanpinType: '',
|
|
|
|
|
|
chanpinMonovalent: 0,
|
|
|
|
|
|
goumaiNumber: 0,
|
|
|
|
|
|
danwei: '',
|
|
|
|
|
|
totalPrice: 0
|
2025-09-24 20:06:58 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 删除产品
|
|
|
|
|
|
const removeProduct = (index) => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (form.value.opsCaigouPlanChanpinBos.length <= 1) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '至少保留一个产品信息', type: 'warning' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
form.value.opsCaigouPlanChanpinBos.splice(index, 1);
|
2025-09-24 20:06:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 重置新建采购申请表单
|
|
|
|
|
|
const resetNewProcurementForm = () => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
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 = '';
|
2025-09-29 20:09:20 +08:00
|
|
|
|
form.value.gonyingshangId = '';
|
|
|
|
|
|
form.value.gonyingshangName = '';
|
|
|
|
|
|
form.value.reason = '';
|
2025-09-26 20:05:38 +08:00
|
|
|
|
form.value.opsCaigouPlanChanpinBos = [{
|
|
|
|
|
|
chanpinName: '',
|
|
|
|
|
|
chanpinType: '',
|
|
|
|
|
|
chanpinMonovalent: '',
|
|
|
|
|
|
goumaiNumber: '',
|
|
|
|
|
|
danwei: '',
|
2025-09-28 20:04:30 +08:00
|
|
|
|
yontu: '',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
totalPrice: ''
|
2025-09-24 20:06:58 +08:00
|
|
|
|
}];
|
2025-09-26 20:05:38 +08:00
|
|
|
|
form.value.opsCaigouPlanFilesBos = [];
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 清空文件上传组件中的文件列表
|
|
|
|
|
|
if (fileUploadRef.value) {
|
|
|
|
|
|
fileUploadRef.value.clearAllFiles();
|
|
|
|
|
|
}
|
2025-09-24 20:06:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 表单校验函数
|
|
|
|
|
|
const validateForm = () => {
|
|
|
|
|
|
// 基础信息校验
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!form.value.jihuaName.trim()) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请填写计划名称', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!form.value.hetonName.trim()) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请填写合同名称', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!form.value.hetonType) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请选择合同类型', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!form.value.caigouType) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请选择采购类型', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!form.value.cangkuUrl) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请选择仓库地址', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-29 20:09:20 +08:00
|
|
|
|
if (!form.value.gonyingshangId) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: '请选择供应商单位', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-28 20:04:30 +08:00
|
|
|
|
if (!form.value.reason) {
|
|
|
|
|
|
ElMessage({ message: '请填写申请原因', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-29 20:09:20 +08:00
|
|
|
|
// 附件校验
|
|
|
|
|
|
if (!form.value.opsCaigouPlanFilesBos || form.value.opsCaigouPlanFilesBos.length === 0) {
|
|
|
|
|
|
ElMessage({ message: '请至少上传一个附件', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
// 产品信息校验
|
2025-09-26 20:05:38 +08:00
|
|
|
|
const hasValidProduct = form.value.opsCaigouPlanChanpinBos.some(product => {
|
|
|
|
|
|
return product.chanpinName &&
|
|
|
|
|
|
product.chanpinType &&
|
|
|
|
|
|
product.chanpinMonovalent && parseFloat(product.chanpinMonovalent) > 0 &&
|
|
|
|
|
|
product.goumaiNumber && parseInt(product.goumaiNumber) > 0 &&
|
2025-09-28 20:04:30 +08:00
|
|
|
|
product.danwei &&
|
|
|
|
|
|
product.yontu;
|
2025-09-24 20:06:58 +08:00
|
|
|
|
});
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
if (!hasValidProduct) {
|
|
|
|
|
|
ElMessage({ message: '请至少填写一个有效的产品信息', type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
// 检查每个产品的有效性
|
2025-09-26 20:05:38 +08:00
|
|
|
|
for (let i = 0; i < form.value.opsCaigouPlanChanpinBos.length; i++) {
|
|
|
|
|
|
const product = form.value.opsCaigouPlanChanpinBos[i];
|
|
|
|
|
|
if (product.chanpinName || product.chanpinType || product.chanpinMonovalent || product.goumaiNumber) {
|
|
|
|
|
|
if (!product.chanpinName) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写产品名称`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!product.chanpinType) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写产品型号`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!product.chanpinMonovalent) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写产品单价`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (parseFloat(product.chanpinMonovalent) <= 0) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:产品单价必须大于0`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!product.goumaiNumber) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写购买数量`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-30 17:40:31 +08:00
|
|
|
|
if (!product.shebeiType) {
|
|
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写设备类型`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (parseInt(product.goumaiNumber) <= 0) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:购买数量必须大于0`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
if (!product.danwei) {
|
2025-09-24 20:06:58 +08:00
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写单位`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-09-28 20:04:30 +08:00
|
|
|
|
if (!product.yontu) {
|
|
|
|
|
|
ElMessage({ message: `第${i + 1}行产品:请填写用途`, type: 'error' });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-26 20:05:38 +08:00
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 新增申请提交
|
|
|
|
|
|
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') {
|
|
|
|
|
|
ElMessage({ message: '提交过程中发生错误,请重试', type: 'error' });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新申请提交
|
|
|
|
|
|
const submitUpdateProcurement = async () => {
|
2025-09-26 20:05:38 +08:00
|
|
|
|
// 在提交前,为所有产品行重新计算并保存总价
|
|
|
|
|
|
form.value.opsCaigouPlanChanpinBos.forEach(product => {
|
|
|
|
|
|
calculateTotalPrice(product);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-24 20:06:58 +08:00
|
|
|
|
// 表单验证
|
|
|
|
|
|
if (!validateForm()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 确认提交
|
|
|
|
|
|
await ElMessageBox.confirm(
|
2025-09-28 20:04:30 +08:00
|
|
|
|
'确定要更新采购申请单吗?',
|
|
|
|
|
|
'确认操作',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
{
|
2025-09-28 20:04:30 +08:00
|
|
|
|
confirmButtonText: '确认',
|
2025-09-26 20:05:38 +08:00
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
type: 'warning'
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2025-09-24 20:06:58 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
// 调用更新提交函数
|
|
|
|
|
|
await updateCaigouPlanSubmit();
|
2025-09-24 20:06:58 +08:00
|
|
|
|
|
2025-09-26 20:05:38 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// 处理用户取消或其他错误
|
|
|
|
|
|
if (error !== 'cancel') {
|
2025-09-28 20:04:30 +08:00
|
|
|
|
ElMessage({ message: '更新过程中发生错误,请重试', type: 'error' });
|
2025-09-26 20:05:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 20:09:20 +08:00
|
|
|
|
|
2025-09-28 20:04:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查表单是否有内容
|
|
|
|
|
|
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) {
|
|
|
|
|
|
ElMessage({ message: '草稿保存失败,请重试', type: 'error' });
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 组件卸载时清除草稿
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 获取草稿存储
|
|
|
|
|
|
const procurementDraftStore = useProcurementDraftStore();
|
|
|
|
|
|
// 清除所有草稿
|
|
|
|
|
|
procurementDraftStore.clearAllDrafts();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('组件卸载时清除草稿失败:', error);
|
|
|
|
|
|
// 这里不显示错误消息,因为组件已经卸载
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-20 20:38:57 +08:00
|
|
|
|
</script>
|