采购申请调整

This commit is contained in:
吴红兵
2026-02-26 16:54:39 +08:00
parent ac30902e2f
commit 1ec4a16c49
25 changed files with 587 additions and 326 deletions

View File

@@ -0,0 +1,48 @@
/*
* 采购模板管理 API
*/
import request from '/@/utils/request';
/**
* 模板列表
*/
export function listTemplates(params?: any) {
return request({
url: '/purchase/purchasingtemplate/list',
method: 'get',
params,
});
}
/**
* 上传 / 覆盖模板
* @param formData 含 file、type 的 FormData
*/
export function uploadTemplate(formData: FormData) {
return request({
url: '/purchase/purchasingtemplate/upload',
method: 'post',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
});
}
/**
* 获取模板下载地址
*/
export function getTemplateDownloadUrl(type: string) {
return `/purchase/purchasingtemplate/download?type=${encodeURIComponent(type)}`;
}
/**
* 更新模板类型名称
*/
export function updateTemplateTitle(data: { id: number | string; templateTitle: string }) {
return request({
url: '/purchase/purchasingtemplate/updateTitle',
method: 'post',
data,
});
}

View File

@@ -2,7 +2,7 @@
<div class="modern-page-container"> <div class="modern-page-container">
<div class="page-wrapper"> <div class="page-wrapper">
<el-card class="content-card" shadow="never"> <el-card class="content-card" shadow="never">
<template #header> <template #header v-if="isEditMode">
<div class="card-header"> <div class="card-header">
<span class="card-title"> <span class="card-title">
<el-icon class="title-icon"><Document /></el-icon> <el-icon class="title-icon"><Document /></el-icon>
@@ -19,112 +19,51 @@
:disabled="isViewMode || flowFormDisabled" :disabled="isViewMode || flowFormDisabled"
class="compact-form"> class="compact-form">
<!-- 基本信息与采购详情同页展示 --> <!-- 基本信息三列紧凑 -->
<div> <div class="form-section-compact">
<el-row :gutter="24"> <el-row :gutter="16">
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="采购项目名称" prop="projectName"> <el-form-item label="采购项目名称" prop="projectName">
<el-input <el-input v-model="dataForm.projectName" placeholder="请输入采购项目名称" clearable :disabled="flowFieldDisabled('projectName')" />
v-model="dataForm.projectName"
placeholder="请输入采购项目名称"
clearable
:disabled="flowFieldDisabled('projectName')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="填报日期" prop="applyDate"> <el-form-item label="填报日期" prop="applyDate">
<el-date-picker <el-date-picker v-model="dataForm.applyDate" type="date" placeholder="请选择填报日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width: 100%" :disabled="flowFieldDisabled('applyDate')" />
v-model="dataForm.applyDate"
type="date"
placeholder="请选择填报日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%"
:disabled="flowFieldDisabled('applyDate')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="8" class="mb12">
<el-row :gutter="24">
<el-col :span="12" class="mb16">
<el-form-item label="资金来源" prop="fundSource"> <el-form-item label="资金来源" prop="fundSource">
<el-select <el-select v-model="dataForm.fundSource" placeholder="请选择资金来源" clearable style="width: 100%" :disabled="flowFieldDisabled('fundSource')">
v-model="dataForm.fundSource" <el-option v-for="item in fundSourceList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择资金来源"
clearable
style="width: 100%"
:disabled="flowFieldDisabled('fundSource')">
<el-option
v-for="item in fundSourceList"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="预算金额" prop="budget"> <el-form-item label="预算金额" prop="budget">
<div class="budget-yuan-wrap"> <div class="budget-yuan-wrap">
<el-input-number <el-input-number v-model="dataForm.budget" :min="0.01" :precision="2" placeholder="请输入金额" :controls="false" style="width: 100%" :disabled="flowFieldDisabled('budget')" />
v-model="dataForm.budget"
:min="0.01"
:precision="2"
placeholder="请输入金额"
:controls="false"
style="width: 100%"
:disabled="flowFieldDisabled('budget')" />
<span class="budget-unit"></span> <span class="budget-unit"></span>
</div> </div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="8" class="mb12">
<el-row :gutter="24">
<el-col :span="12" class="mb16">
<el-form-item label="是否集采" prop="isCentralized"> <el-form-item label="是否集采" prop="isCentralized">
<el-select <el-select v-model="dataForm.isCentralized" placeholder="请选择是否集采" clearable style="width: 100%" :disabled="flowFieldDisabled('isCentralized')">
v-model="dataForm.isCentralized" <el-option v-for="item in isCentralizedList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择是否集采"
clearable
style="width: 100%"
:disabled="flowFieldDisabled('isCentralized')">
<el-option
v-for="item in isCentralizedList"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="是否特殊情况" prop="isSpecial"> <el-form-item label="是否特殊情况" prop="isSpecial">
<el-select <el-select v-model="dataForm.isSpecial" placeholder="请选择是否特殊情况" clearable style="width: 100%" :disabled="flowFieldDisabled('isSpecial')">
v-model="dataForm.isSpecial" <el-option v-for="item in isSpecialList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择是否特殊情况"
clearable
style="width: 100%"
:disabled="flowFieldDisabled('isSpecial')">
<el-option
v-for="item in isSpecialList"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="24" class="mb12">
<el-row :gutter="24">
<el-col :span="24" class="mb16">
<el-form-item label="品目编码" prop="categoryCode"> <el-form-item label="品目编码" prop="categoryCode">
<el-cascader <el-cascader v-model="categoryCodePath" :options="categoryTreeData" :props="{ value: 'code', label: 'name', children: 'children', checkStrictly: false }" placeholder="请选择品目编码(仅最后一级)" clearable filterable :show-all-levels="true" style="width: 100%" :disabled="flowFieldDisabled('categoryCode')" @change="handleCategoryChange" />
v-model="categoryCodePath"
:options="categoryTreeData"
:props="{ value: 'code', label: 'name', children: 'children', checkStrictly: true }"
placeholder="请选择品目编码"
clearable
filterable
:show-all-levels="true"
style="width: 100%"
:disabled="flowFieldDisabled('categoryCode')"
@change="handleCategoryChange" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -135,24 +74,19 @@
<el-alert v-if="!showPurchaseDetailBlocks" type="info" :closable="false" class="mb16" show-icon> <el-alert v-if="!showPurchaseDetailBlocks" type="info" :closable="false" class="mb16" show-icon>
请先填写上方是否特殊情况是否集采预算金额系统将根据填写结果展示部门自行采购学校统一采购表单 请先填写上方是否特殊情况是否集采预算金额系统将根据填写结果展示部门自行采购学校统一采购表单
</el-alert> </el-alert>
<!-- 分支一部门自行采购单行两列流式布局条件显示的项自动填满两列 --> <!-- 分支一部门自行采购三列紧凑textarea 单独一行 -->
<div class="mb20" v-if="showPurchaseDetailBlocks && isDeptPurchase"> <div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && isDeptPurchase">
<div class="step-title mb16">部门自行采购</div> <div class="step-title mb12">部门自行采购</div>
<el-row :gutter="24"> <el-row :gutter="16">
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="采购内容" prop="projectContent" class="mb16"> <el-form-item label="采购途径" prop="purchaseChannel">
<el-input <el-select v-model="dataForm.purchaseChannel" placeholder="请选择采购途径" clearable :disabled="flowFieldDisabled('purchaseChannel')" style="width: 100%">
v-model="dataForm.projectContent" <el-option :label="'自行采购'" :value="PURCHASE_CHANNEL.SELF" />
type="textarea" <el-option :label="'委托采购中心采购'" :value="PURCHASE_CHANNEL.ENTRUST_CENTER" />
:rows="3" </el-select>
:maxlength="1000"
show-word-limit
placeholder="请输入采购内容限制1000字"
clearable
:disabled="flowFieldDisabled('projectContent')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12" v-if="!isEntrustCenterChannel || (isFlowEmbed && isPurchaseCenter)">
<el-form-item label="采购方式" prop="purchaseType" required class="mb16"> <el-form-item label="采购方式" prop="purchaseType" required class="mb16">
<el-select <el-select
v-model="dataForm.purchaseType" v-model="dataForm.purchaseType"
@@ -166,182 +100,69 @@
:label="item.label" :label="item.label"
:value="item.value" /> :value="item.value" />
</el-select> </el-select>
<div
v-if="isFlowEmbed && isPurchaseCenter && isEntrustCenterChannel && isAutoSelectPurchaseType"
class="template-note mt5"
>
<el-text type="info" size="small">服务网上商城</el-text>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.BUSINESS_NEGOTIATION)"> <el-col :span="24" class="mb12">
<el-form-item label="商务洽谈表" prop="businessNegotiationTable" required class="mb16"> <el-form-item label="采购内容" prop="projectContent">
<el-input v-model="dataForm.projectContent" type="textarea" :rows="3" :maxlength="1000" show-word-limit placeholder="请输入采购内容限制1000字" clearable :disabled="flowFieldDisabled('projectContent')" />
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.BUSINESS_NEGOTIATION)">
<el-form-item label="商务洽谈表" prop="businessNegotiationTable" required>
<upload-file v-model="dataForm.businessNegotiationTable" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.businessNegotiationTable }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('businessNegotiationTable')" /> <upload-file v-model="dataForm.businessNegotiationTable" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.businessNegotiationTable }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('businessNegotiationTable')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('business_negotiation')" style="margin-top: 8px; display: inline-block">下载商务洽谈表模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('business_negotiation')" style="margin-top: 8px; display: inline-block">下载商务洽谈表模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.MARKET_PURCHASE)"> <el-col :span="8" class="mb12" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.MARKET_PURCHASE)">
<el-form-item label="市场采购纪要" prop="marketPurchaseMinutes" required class="mb16"> <el-form-item label="市场采购纪要" prop="marketPurchaseMinutes" required>
<upload-file v-model="dataForm.marketPurchaseMinutes" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.marketPurchaseMinutes }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('marketPurchaseMinutes')" /> <upload-file v-model="dataForm.marketPurchaseMinutes" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.marketPurchaseMinutes }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('marketPurchaseMinutes')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('market_purchase_minutes')" style="margin-top: 8px; display: inline-block">下载市场采购纪要模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('market_purchase_minutes')" style="margin-top: 8px; display: inline-block">下载市场采购纪要模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ONLINE_MALL)"> <el-col :span="8" class="mb12" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ONLINE_MALL)">
<el-form-item label="网上商城采购相关材料" prop="onlineMallMaterials" required class="mb16"> <el-form-item label="网上商城采购相关材料" prop="onlineMallMaterials" required>
<upload-file v-model="dataForm.onlineMallMaterials" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.onlineMallMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('onlineMallMaterials')" /> <upload-file v-model="dataForm.onlineMallMaterials" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.onlineMallMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('onlineMallMaterials')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isInquiryPurchaseType"> <el-col :span="8" class="mb12" v-if="isInquiryPurchaseType">
<el-form-item label="询价模板" prop="inquiryTemplate" required class="mb16"> <el-form-item label="询价模板" prop="inquiryTemplate" required>
<upload-file v-model="dataForm.inquiryTemplate" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.inquiryTemplate }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('inquiryTemplate')" /> <upload-file v-model="dataForm.inquiryTemplate" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.inquiryTemplate }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('inquiryTemplate')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('inquiry')" style="margin-top: 8px; display: inline-block">下载部门采购询价模版模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('inquiry')" style="margin-top: 8px; display: inline-block">下载部门采购询价模版模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER)"> <el-col :span="8" class="mb12" v-if="isEntrustCenterChannel && dataForm.entrustCenterType === 'service_online' && categoryCodePath && categoryCodePath[0] === 'C'">
<el-form-item label="委托采购中心方式" prop="entrustCenterType" class="mb16"> <el-form-item label="是否有供应商" prop="hasSupplier">
<el-radio-group v-model="dataForm.entrustCenterType" disabled>
<el-radio label="service_online">服务类网上商城</el-radio>
<el-radio label="other">其他方式</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col
:span="12"
class="mb16"
v-if="
isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER) &&
dataForm.entrustCenterType === 'service_online' &&
categoryCodePath &&
categoryCodePath[0] === 'C'
"
>
<el-form-item label="是否有供应商" prop="hasSupplier" class="mb16">
<el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')"> <el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')">
<el-radio label="1"></el-radio> <el-radio label="1"></el-radio>
<el-radio label="0"></el-radio> <el-radio label="0"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER) && dataForm.entrustCenterType === 'service_online' && categoryCodePath && categoryCodePath[0] === 'C' && dataForm.hasSupplier === '1'"> <el-col :span="8" class="mb12" v-if="isEntrustCenterChannel && dataForm.entrustCenterType === 'service_online' && categoryCodePath && categoryCodePath[0] === 'C' && dataForm.hasSupplier === '1'">
<el-form-item label="需求文件" prop="serviceDirectSelect" required class="mb16"> <el-form-item label="需求文件" prop="serviceDirectSelect" required>
<upload-file v-model="dataForm.serviceDirectSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceDirectSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceDirectSelect')" /> <upload-file v-model="dataForm.serviceDirectSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceDirectSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceDirectSelect')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('direct_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板直选模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('direct_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板直选模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER) && dataForm.entrustCenterType === 'service_online' && categoryCodePath && categoryCodePath[0] === 'C' && dataForm.hasSupplier === '0'"> <el-col :span="8" class="mb12" v-if="isEntrustCenterChannel && dataForm.entrustCenterType === 'service_online' && categoryCodePath && categoryCodePath[0] === 'C' && dataForm.hasSupplier === '0'">
<el-form-item label="需求文件" prop="serviceInviteSelect" required class="mb16"> <el-form-item label="需求文件" prop="serviceInviteSelect" required>
<upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" /> <upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('public_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板公开比选模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('public_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板公开比选模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER) && dataForm.entrustCenterType === 'other' && categoryCodePath && categoryCodePath[0] === 'A'"> <el-col :span="8" class="mb12" v-if="isEntrustCenterChannel && dataForm.entrustCenterType === 'other' && categoryCodePath && categoryCodePath[0] === 'A'">
<el-form-item label="需求模板" prop="purchaseRequirementTemplate" required class="mb16"> <el-form-item label="需求模板" prop="purchaseRequirementTemplate" required>
<upload-file v-model="dataForm.purchaseRequirementTemplate" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.purchaseRequirementTemplate }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('purchaseRequirementTemplate')" /> <upload-file v-model="dataForm.purchaseRequirementTemplate" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.purchaseRequirementTemplate }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('purchaseRequirementTemplate')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('purchase_requirement')" style="margin-top: 8px; display: inline-block">下载表1需求模板模版</el-button> <el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('purchase_requirement')" style="margin-top: 8px; display: inline-block">下载表1需求模板模版</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="showAutoInviteSelect"> <el-col :span="8" class="mb12" v-if="showAutoInviteSelect">
<el-form-item label="是否有推荐供应商" prop="hasSupplier" class="mb16">
<el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')">
<el-radio label="1">有</el-radio>
<el-radio label="0">无</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<!-- <el-col :span="12" class="mb16" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
<el-form-item label="推荐供应商" prop="suppliers" class="mb16">
<el-input v-model="dataForm.suppliers" placeholder="请输入三家供应商名称,用逗号分隔" clearable />
<div class="template-note mt5"><el-text type="info" size="small">请输入三家供应商名称,用逗号分隔</el-text></div>
</el-form-item>
</el-col> -->
<el-col :span="12" class="mb16" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
<el-form-item label="服务商城项目需求模板(邀请比选)" prop="serviceInviteSelect" required class="mb16">
<upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('invite_select')" style="margin-top: 8px; display: inline-block">下载《服务商城项目需求模板(邀请比选)》模版</el-button>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="showAutoInviteSelect && dataForm.hasSupplier === '0'">
<el-form-item label="服务商城项目需求模板(公开比选)" prop="servicePublicSelectAuto" required class="mb16">
<upload-file v-model="dataForm.servicePublicSelectAuto" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.servicePublicSelectAuto }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('servicePublicSelectAuto')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('public_select')" style="margin-top: 8px; display: inline-block">下载《服务商城项目需求模板(公开比选)》模版</el-button>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16">
<el-form-item label="其他材料" prop="otherMaterials" class="mb16">
<upload-file v-model="dataForm.otherMaterials" :limit="1" :file-type="['zip']" :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('otherMaterials')" />
<div class="template-note">支持上传zip格式的压缩包文件</div>
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 分支二:学校统一采购(单行两列流式布局);申请时隐藏采购方式,由审批环节采购中心补充 -->
<div class="mb20" v-if="showPurchaseDetailBlocks && !isDeptPurchase">
<div class="step-title mb16">学校统一采购</div>
<el-row :gutter="24">
<el-col :span="12" class="mb16">
<el-form-item label="采购形式" prop="purchaseMode">
<el-radio-group v-model="dataForm.purchaseMode" :disabled="schoolUnifiedPurchaseFormDisabled">
<el-radio v-for="item in purchaseModeSchoolList" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
<!-- <div v-if="schoolUnifiedPurchaseFormDefault != null" class="template-note mt5"><el-text type="info" size="small">根据预算金额与是否集采由系统自动选择</el-text></div> -->
</el-form-item>
</el-col>
<!-- 学校统一采购时申请阶段不显示采购方式;审批环节(流程嵌入)时显示,由采购中心补充选择、其他节点只读 -->
<el-col :span="12" class="mb16" v-if="isDeptPurchase || isFlowEmbed">
<el-form-item label="采购方式" prop="purchaseType" :required="!isDeptPurchase">
<el-select v-model="dataForm.purchaseType" placeholder="请选择采购方式" clearable :disabled="(isFlowEmbed && isPurchaseCenter) ? false : (isAutoSelectPurchaseTypeUnion || flowFieldDisabled('purchaseType'))" style="width: 100%">
<el-option v-for="item in purchaseTypeUnionList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16">
<el-form-item label="业务分管处室" prop="deptClassifyUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.deptClassifyUserId" placeholder="请选择业务分管处室" clearable filterable @change="handleBusinessDeptChange" style="width: 100%" :disabled="flowFieldDisabled('deptClassifyUserId')">
<el-option v-for="item in businessDeptList" :key="item.id" :label="item.deptName" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16">
<el-form-item label="分管校领导" prop="schoolLeaderUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.schoolLeaderUserId" placeholder="请选择分管校领导" clearable filterable @change="handleSchoolLeaderChange" style="width: 100%" :disabled="flowFieldDisabled('schoolLeaderUserId')">
<el-option v-for="item in schoolLeaderList" :key="item.id" :label="item.name" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="dataForm.budget && dataForm.budget >= 300000">
<el-form-item label="项目可行性论证报告" prop="feasibilityReport" required>
<upload-file v-model="dataForm.feasibilityReport" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.feasibilityReport }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('feasibilityReport')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('feasibility_report')" style="margin-top: 8px; display: inline-block">下载《项目可行性论证报告模板.doc》</el-button>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="dataForm.budget && dataForm.budget >= 300000 && !isUrgentSpecial && !isSpecialType('2') && !isSpecialType('3')">
<el-form-item label="会议纪要" prop="meetingMinutes" required>
<upload-file v-model="dataForm.meetingMinutes" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutes }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutes')" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="isUrgentSpecial">
<el-form-item label="会议纪要" prop="meetingMinutesUrgent" required>
<upload-file v-model="dataForm.meetingMinutesUrgent" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesUrgent }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesUrgent')" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="isSpecialType('2')">
<el-form-item label="单一来源论专家证附件" prop="singleSourceProof" required>
<upload-file v-model="dataForm.singleSourceProof" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.singleSourceProof }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('singleSourceProof')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('single_source')" style="margin-top: 8px; display: inline-block">下载《单一来源论专家证附件.docx》</el-button>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="isSpecialType('2')">
<el-form-item label="会议纪要" prop="meetingMinutesSingle" required>
<upload-file v-model="dataForm.meetingMinutesSingle" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesSingle }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesSingle')" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="isSpecialType('3')">
<el-form-item label="进口产品申请及专家论证意见表" prop="importApplication" required>
<upload-file v-model="dataForm.importApplication" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.importApplication }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('importApplication')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('import_application')" style="margin-top: 8px; display: inline-block">下载《进口产品申请及专家论证意见表.doc》</el-button>
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="isSpecialType('3')">
<el-form-item label="会议纪要" prop="meetingMinutesImport" required>
<upload-file v-model="dataForm.meetingMinutesImport" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesImport }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesImport')" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb16" v-if="showAutoInviteSelectSchool">
<el-form-item label="是否有推荐供应商" prop="hasSupplier"> <el-form-item label="是否有推荐供应商" prop="hasSupplier">
<el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')"> <el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')">
<el-radio label="1"></el-radio> <el-radio label="1"></el-radio>
@@ -349,13 +170,119 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12" class="mb16" v-if="showAutoInviteSelectSchool && dataForm.hasSupplier === '1'"> <!-- <el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
<el-form-item label="推荐供应商" prop="suppliers" class="mb16">
<el-input v-model="dataForm.suppliers" placeholder="请输入三家供应商名称,用逗号分隔" clearable />
<div class="template-note mt5"><el-text type="info" size="small">请输入三家供应商名称用逗号分隔</el-text></div>
</el-form-item>
</el-col> -->
<el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
<el-form-item label="服务商城项目需求模板(邀请比选)" prop="serviceInviteSelect" required>
<upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('invite_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板邀请比选模版</el-button>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '0'">
<el-form-item label="服务商城项目需求模板(公开比选)" prop="servicePublicSelectAuto" required>
<upload-file v-model="dataForm.servicePublicSelectAuto" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.servicePublicSelectAuto }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('servicePublicSelectAuto')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('public_select')" style="margin-top: 8px; display: inline-block">下载服务商城项目需求模板公开比选模版</el-button>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12">
<el-form-item label="其他材料" prop="otherMaterials">
<upload-file v-model="dataForm.otherMaterials" :limit="1" :file-type="['zip']" :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('otherMaterials')" />
<div class="template-note">支持上传zip格式的压缩包文件</div>
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 分支二学校统一采购三列紧凑 -->
<div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && !isDeptPurchase">
<div class="step-title mb12">学校统一采购</div>
<el-row :gutter="16">
<el-col :span="8" class="mb12">
<el-form-item label="采购形式" prop="purchaseMode">
<el-radio-group v-model="dataForm.purchaseMode" :disabled="schoolUnifiedPurchaseFormDisabled">
<el-radio v-for="item in purchaseModeSchoolList" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
<!-- <div v-if="schoolUnifiedPurchaseFormDefault != null" class="template-note mt5"><el-text type="info" size="small">根据预算金额与是否集采由系统自动选择</el-text></div> -->
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isDeptPurchase || isFlowEmbed">
<el-form-item label="采购方式" prop="purchaseType" :required="!isDeptPurchase">
<el-select v-model="dataForm.purchaseType" placeholder="请选择采购方式" clearable :disabled="(isFlowEmbed && isPurchaseCenter) ? false : (isAutoSelectPurchaseTypeUnion || flowFieldDisabled('purchaseType'))" style="width: 100%">
<el-option v-for="item in purchaseTypeUnionList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12">
<el-form-item label="业务分管处室" prop="deptClassifyUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.deptClassifyUserId" placeholder="请选择业务分管处室" clearable filterable @change="handleBusinessDeptChange" style="width: 100%" :disabled="flowFieldDisabled('deptClassifyUserId')">
<el-option v-for="item in businessDeptList" :key="item.id" :label="item.deptName" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12">
<el-form-item label="分管校领导" prop="schoolLeaderUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.schoolLeaderUserId" placeholder="请选择分管校领导" clearable filterable @change="handleSchoolLeaderChange" style="width: 100%" :disabled="flowFieldDisabled('schoolLeaderUserId')">
<el-option v-for="item in schoolLeaderList" :key="item.id" :label="item.name" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="dataForm.budget && dataForm.budget >= BUDGET_FEASIBILITY_THRESHOLD">
<el-form-item label="项目可行性论证报告" prop="feasibilityReport" required>
<upload-file v-model="dataForm.feasibilityReport" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.feasibilityReport }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('feasibilityReport')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('feasibility_report')" style="margin-top: 8px; display: inline-block">下载项目可行性论证报告模板.doc</el-button>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="dataForm.budget && dataForm.budget >= BUDGET_FEASIBILITY_THRESHOLD && !isUrgentSpecial && !isSpecialType('2') && !isSpecialType('3')">
<el-form-item label="会议纪要" prop="meetingMinutes" required>
<upload-file v-model="dataForm.meetingMinutes" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutes }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutes')" />
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isUrgentSpecial">
<el-form-item label="会议纪要" prop="meetingMinutesUrgent" required>
<upload-file v-model="dataForm.meetingMinutesUrgent" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesUrgent }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesUrgent')" />
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isSpecialType('2')">
<el-form-item label="单一来源论专家证附件" prop="singleSourceProof" required>
<upload-file v-model="dataForm.singleSourceProof" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.singleSourceProof }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('singleSourceProof')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('single_source')" style="margin-top: 8px; display: inline-block">下载单一来源论专家证附件.docx</el-button>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isSpecialType('2')">
<el-form-item label="会议纪要" prop="meetingMinutesSingle" required>
<upload-file v-model="dataForm.meetingMinutesSingle" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesSingle }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesSingle')" />
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isSpecialType('3')">
<el-form-item label="进口产品申请及专家论证意见表" prop="importApplication" required>
<upload-file v-model="dataForm.importApplication" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.importApplication }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('importApplication')" />
<el-button type="primary" link icon="Download" size="small" @click="downloadTemplate('import_application')" style="margin-top: 8px; display: inline-block">下载进口产品申请及专家论证意见表.doc</el-button>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="isSpecialType('3')">
<el-form-item label="会议纪要" prop="meetingMinutesImport" required>
<upload-file v-model="dataForm.meetingMinutesImport" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.meetingMinutesImport }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('meetingMinutesImport')" />
</el-form-item>
</el-col>
<el-col :span="8" class="mb12" v-if="showAutoInviteSelectSchool">
<el-form-item label="是否有推荐供应商" prop="hasSupplier">
<el-radio-group v-model="dataForm.hasSupplier" :disabled="flowFieldDisabled('hasSupplier')">
<el-radio label="1"></el-radio>
<el-radio label="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<!-- <el-col :span="8" class="mb12" v-if="showAutoInviteSelectSchool && dataForm.hasSupplier === '1'">
<el-form-item label="推荐供应商" prop="suppliers"> <el-form-item label="推荐供应商" prop="suppliers">
<el-input v-model="dataForm.suppliers" type="textarea" :rows="2" placeholder="请输入至少三家供应商名称,用逗号或分号分隔" clearable :disabled="flowFieldDisabled('suppliers')" /> <el-input v-model="dataForm.suppliers" type="textarea" :rows="2" placeholder="请输入至少三家供应商名称,用逗号或分号分隔" clearable :disabled="flowFieldDisabled('suppliers')" />
<div class="template-note mt5"><el-text type="info" size="small">请输入至少三家供应商名称用逗号或分号分隔</el-text></div> <div class="template-note mt5"><el-text type="info" size="small">请输入至少三家供应商名称用逗号或分号分隔</el-text></div>
</el-form-item> </el-form-item>
</el-col> --> </el-col> -->
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="需求文件" :prop="getRequirementFileProp()" required class="mb16"> <el-form-item label="需求文件" :prop="getRequirementFileProp()" required class="mb16">
<template v-if="showAutoInviteSelectSchool"> <template v-if="showAutoInviteSelectSchool">
<template v-if="dataForm.hasSupplier === '1'"> <template v-if="dataForm.hasSupplier === '1'">
@@ -377,12 +304,12 @@
</template> </template>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="dataForm.budget && dataForm.budget >= 1000000"> <el-col :span="8" class="mb12" v-if="dataForm.budget && dataForm.budget >= BUDGET_GOV_PURCHASE_THRESHOLD">
<el-form-item label="政府采购意向申请表" prop="governmentPurchaseIntent" required> <el-form-item label="政府采购意向申请表" prop="governmentPurchaseIntent" required>
<upload-file v-model="dataForm.governmentPurchaseIntent" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.governmentPurchaseIntent }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('governmentPurchaseIntent')" /> <upload-file v-model="dataForm.governmentPurchaseIntent" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.governmentPurchaseIntent }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('governmentPurchaseIntent')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<el-form-item label="其他材料" prop="otherMaterials"> <el-form-item label="其他材料" prop="otherMaterials">
<upload-file v-model="dataForm.otherMaterials" :limit="1" :file-type="['zip']" :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('otherMaterials')" /> <upload-file v-model="dataForm.otherMaterials" :limit="1" :file-type="['zip']" :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('otherMaterials')" />
<div class="template-note">支持上传zip格式的压缩包文件</div> <div class="template-note">支持上传zip格式的压缩包文件</div>
@@ -392,16 +319,10 @@
</div> </div>
</div> </div>
<el-row :gutter="24"> <el-row :gutter="16">
<el-col :span="12" class="mb16"> <el-col :span="24" class="mb12">
<el-form-item label="备注" prop="remark" class="mb16"> <el-form-item label="备注" prop="remark">
<el-input <el-input v-model="dataForm.remark" type="textarea" :rows="2" placeholder="请输入备注" clearable :disabled="flowFieldDisabled('remark')" />
v-model="dataForm.remark"
type="textarea"
:rows="2"
placeholder="请输入备注"
clearable
:disabled="flowFieldDisabled('remark')" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -410,7 +331,7 @@
<div v-if="isViewMode && dataForm.agentName" class="implement-info-block mb20"> <div v-if="isViewMode && dataForm.agentName" class="implement-info-block mb20">
<el-divider content-position="left">招标代理</el-divider> <el-divider content-position="left">招标代理</el-divider>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12" class="mb16"> <el-col :span="8" class="mb12">
<div class="view-label">代理名称</div> <div class="view-label">代理名称</div>
<div class="view-value">{{ dataForm.agentName }}</div> <div class="view-value">{{ dataForm.agentName }}</div>
</el-col> </el-col>
@@ -421,11 +342,11 @@
<div v-if="isViewMode && (dataForm.implementType || viewImplementPurchaseFiles.length)" class="implement-info-block mb20"> <div v-if="isViewMode && (dataForm.implementType || viewImplementPurchaseFiles.length)" class="implement-info-block mb20">
<el-divider content-position="left">实施采购信息</el-divider> <el-divider content-position="left">实施采购信息</el-divider>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12" class="mb16" v-if="dataForm.implementType"> <el-col :span="8" class="mb12" v-if="dataForm.implementType">
<div class="view-label">实施采购方式</div> <div class="view-label">实施采购方式</div>
<div class="view-value">{{ dataForm.implementType === '1' ? '自行组织采购' : dataForm.implementType === '2' ? '委托代理采购' : dataForm.implementType || '—' }}</div> <div class="view-value">{{ dataForm.implementType === '1' ? '自行组织采购' : dataForm.implementType === '2' ? '委托代理采购' : dataForm.implementType || '—' }}</div>
</el-col> </el-col>
<el-col :span="12" class="mb16" v-if="dataForm.fileFlowInstId"> <el-col :span="8" class="mb12" v-if="dataForm.fileFlowInstId">
<div class="view-label">文件审批状态</div> <div class="view-label">文件审批状态</div>
<div class="view-value"> <div class="view-value">
<el-tag v-if="dataForm.fileFlowStatus === '-2'" type="info">撤回</el-tag> <el-tag v-if="dataForm.fileFlowStatus === '-2'" type="info">撤回</el-tag>
@@ -555,9 +476,10 @@ const flowSubmitDisabled = ref(false);
/** 流程嵌入时当前节点是否为采购中心(仅采购中心可编辑采购方式/采购形式) */ /** 流程嵌入时当前节点是否为采购中心(仅采购中心可编辑采购方式/采购形式) */
const isPurchaseCenter = ref(false); const isPurchaseCenter = ref(false);
/** 流程嵌入且为采购中心时,除采购方式/采购形式外其余字段均只读 */ /** 流程嵌入时:采购中心审核节点放开所有字段编辑;非采购中心节点只读 */
function flowFieldDisabled(key: string) { function flowFieldDisabled(_key: string) {
return isFlowEmbed.value && isPurchaseCenter.value && !['purchaseType', 'purchaseMode'].includes(key); if (isFlowEmbed.value && isPurchaseCenter.value) return false;
return !!isFlowEmbed.value;
} }
// 定义变量内容 // 定义变量内容
@@ -575,6 +497,7 @@ const dataForm = reactive({
purchaseMode: '', purchaseMode: '',
purchaseType: '', purchaseType: '',
purchaseTypeUnion: '', purchaseTypeUnion: '',
purchaseChannel: '',
categoryCode: '', categoryCode: '',
remark: '', remark: '',
status: '', status: '',
@@ -670,13 +593,19 @@ Object.entries(FILE_TYPE_MAP).forEach(([field, type]) => {
FILE_TYPE_TO_FIELDS[type].push(field); FILE_TYPE_TO_FIELDS[type].push(field);
}); });
// 金额阈值常量(与后端 PurchaseConstants 保持一致)
const BUDGET_DEPT_PURCHASE_THRESHOLD = 50000; // 部门自行采购上限(< 5 万)
const BUDGET_FEASIBILITY_THRESHOLD = 300000; // 可行性论证/会议纪要起点(≥ 30 万)
const BUDGET_PUBLIC_SELECT_THRESHOLD = 400000; // 公开比选起点(≥ 40 万)
const BUDGET_GOV_PURCHASE_THRESHOLD = 1000000; // 政府采购起点(≥ 100 万)
// 部门采购方式字典 value与 DeptPurchaseTypeEnum 一致) // 部门采购方式字典 value与 DeptPurchaseTypeEnum 一致)
const DEPT_PURCHASE_TYPE = { const DEPT_PURCHASE_TYPE = {
ONLINE_MALL: '1', ONLINE_MALL: '1',
MARKET_PURCHASE: '2', MARKET_PURCHASE: '2',
BUSINESS_NEGOTIATION: '3', BUSINESS_NEGOTIATION: '3',
ENTRUST_CENTER: '4', ENTRUST_CENTER: '4',
INQUIRY: '6', INQUIRY: '5',
} as const; } as const;
// 学校统一采购方式字典 value与 PurchaseTypeEnum 一致) // 学校统一采购方式字典 value与 PurchaseTypeEnum 一致)
@@ -700,6 +629,12 @@ const isSpecialType = (dictValue: string) => {
return item ? dataForm.isSpecial === item.value : dataForm.isSpecial === dictValue; return item ? dataForm.isSpecial === item.value : dataForm.isSpecial === dictValue;
}; };
// 采购途径(与后端 purchasing_apply.purchase_channel 一致1 自行采购 2 委托采购中心采购)
const PURCHASE_CHANNEL = {
SELF: '1',
ENTRUST_CENTER: '2',
} as const;
// 判断是否为部门自行采购 // 判断是否为部门自行采购
// 条件:特殊情况=否 且 集采=否 且 预算金额<5万 → 部门自行采购 // 条件:特殊情况=否 且 集采=否 且 预算金额<5万 → 部门自行采购
// 其他情况 → 学校统一采购 // 其他情况 → 学校统一采购
@@ -714,6 +649,9 @@ const isDeptPurchase = computed(() => {
dataForm.budget && dataForm.budget < 50000); dataForm.budget && dataForm.budget < 50000);
}); });
// 是否为“委托采购中心采购”途径
const isEntrustCenterChannel = computed(() => dataForm.purchaseChannel === PURCHASE_CHANNEL.ENTRUST_CENTER);
// 是否已填入“是否特殊情况”“是否集采”“预算金额”,从而能明确是部门自行采购还是学校统一采购(新增时先隐藏采购详情,填完后再显示) // 是否已填入“是否特殊情况”“是否集采”“预算金额”,从而能明确是部门自行采购还是学校统一采购(新增时先隐藏采购详情,填完后再显示)
const isPurchaseTypeDetermined = computed(() => { const isPurchaseTypeDetermined = computed(() => {
return dataForm.isSpecial !== '' && dataForm.isCentralized !== '' && return dataForm.isSpecial !== '' && dataForm.isCentralized !== '' &&
@@ -728,8 +666,8 @@ const showPurchaseDetailBlocks = computed(() => {
const schoolUnifiedPurchaseFormDefault = computed(() => { const schoolUnifiedPurchaseFormDefault = computed(() => {
if (isDeptPurchase.value || dataForm.budget == null) return null; if (isDeptPurchase.value || dataForm.budget == null) return null;
const budget = Number(dataForm.budget); const budget = Number(dataForm.budget);
if (budget >= 1000000) return '1'; // 政府采购 if (budget >= BUDGET_GOV_PURCHASE_THRESHOLD) return '1'; // 政府采购
if (budget >= 50000 && budget < 1000000) { if (budget >= BUDGET_DEPT_PURCHASE_THRESHOLD && budget < BUDGET_GOV_PURCHASE_THRESHOLD) {
if (dataForm.isCentralized === '0') return '2'; // 集采=否 → 学校自主采购 if (dataForm.isCentralized === '0') return '2'; // 集采=否 → 学校自主采购
if (dataForm.isCentralized === '1') return '1'; // 政府集中采购 → 政府采购 if (dataForm.isCentralized === '1') return '1'; // 政府集中采购 → 政府采购
if (dataForm.isCentralized === '2') return '2'; // 学校集中采购 → 学校自主采购 if (dataForm.isCentralized === '2') return '2'; // 学校集中采购 → 学校自主采购
@@ -737,8 +675,9 @@ const schoolUnifiedPurchaseFormDefault = computed(() => {
return null; return null;
}); });
// 学校统一采购时采购形式是否禁用(由规则自动选择,不由用户选择 // 学校统一采购时采购形式是否禁用(采购中心审核时放开;否则由规则自动选择时禁用
const schoolUnifiedPurchaseFormDisabled = computed(() => flowFieldDisabled('purchaseMode') || (schoolUnifiedPurchaseFormDefault.value != null)); const schoolUnifiedPurchaseFormDisabled = computed(() =>
(isFlowEmbed.value && isPurchaseCenter.value) ? false : (flowFieldDisabled('purchaseMode') || (schoolUnifiedPurchaseFormDefault.value != null)));
// 特殊情况字典 value0否 1紧急 2单一 3进口 // 特殊情况字典 value0否 1紧急 2单一 3进口
const isUrgentSpecial = computed(() => dataForm.isSpecial === '1'); const isUrgentSpecial = computed(() => dataForm.isSpecial === '1');
@@ -823,7 +762,7 @@ const isSpecialServiceCategory = computed(() => {
// - 服务类:若末级节点 isMallService=0 且 isMallProject=0则选“其他方式”否则选“服务类网上商城” // - 服务类:若末级节点 isMallService=0 且 isMallProject=0则选“其他方式”否则选“服务类网上商城”
// - 非服务类:默认选“其他方式” // - 非服务类:默认选“其他方式”
const calcEntrustCenterType = (): 'service_online' | 'other' | '' => { const calcEntrustCenterType = (): 'service_online' | 'other' | '' => {
if (!isPurchaseType(DEPT_PURCHASE_TYPE.ENTRUST_CENTER)) return ''; if (!isEntrustCenterChannel.value) return '';
if (!dataForm.categoryCode) return ''; if (!dataForm.categoryCode) return '';
const category = getCategoryInfo(); const category = getCategoryInfo();
@@ -839,9 +778,9 @@ const calcEntrustCenterType = (): 'service_online' | 'other' | '' => {
return 'other'; return 'other';
}; };
// 监听品目/采购方式变化,自动设置委托采购中心方式,并清理无关字段 // 监听品目/采购途径变化,自动设置委托采购中心方式,并清理无关字段
watch( watch(
[() => dataForm.purchaseType, () => dataForm.categoryCode, () => categoryTreeData.value], [() => dataForm.purchaseChannel, () => dataForm.categoryCode, () => categoryTreeData.value],
() => { () => {
const nextType = calcEntrustCenterType(); const nextType = calcEntrustCenterType();
if (!nextType) return; if (!nextType) return;
@@ -870,7 +809,7 @@ watch(
const isAutoSelectPurchaseType = computed(() => { const isAutoSelectPurchaseType = computed(() => {
if (!dataForm.budget) return false; if (!dataForm.budget) return false;
const budget = dataForm.budget; const budget = dataForm.budget;
return budget >= 50000 && budget < 400000 && isServiceCategory.value && isSpecialServiceCategory.value; return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD && budget < BUDGET_PUBLIC_SELECT_THRESHOLD && isServiceCategory.value && isSpecialServiceCategory.value;
}); });
// 判断是否显示自动邀请比选模版5万<=金额<40万服务类目特殊服务类目 // 判断是否显示自动邀请比选模版5万<=金额<40万服务类目特殊服务类目
@@ -878,7 +817,7 @@ const showAutoInviteSelect = computed(() => {
if (!isDeptPurchase.value) return false; if (!isDeptPurchase.value) return false;
if (!dataForm.budget) return false; if (!dataForm.budget) return false;
const budget = dataForm.budget; const budget = dataForm.budget;
return budget >= 50000 && budget < 400000 && isServiceCategory.value && isSpecialServiceCategory.value; return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD && budget < BUDGET_PUBLIC_SELECT_THRESHOLD && isServiceCategory.value && isSpecialServiceCategory.value;
}); });
// 判断是否显示学校统一采购的自动邀请比选模版5万<=金额<40万服务类目特殊服务类目 // 判断是否显示学校统一采购的自动邀请比选模版5万<=金额<40万服务类目特殊服务类目
@@ -886,7 +825,7 @@ const showAutoInviteSelectSchool = computed(() => {
if (isDeptPurchase.value) return false; if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false; if (!dataForm.budget) return false;
const budget = dataForm.budget; const budget = dataForm.budget;
return budget >= 50000 && budget < 400000 && isSpecialServiceCategory.value; return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD && budget < BUDGET_PUBLIC_SELECT_THRESHOLD && isSpecialServiceCategory.value;
}); });
// 判断是否显示自动公开比选模版40万<=金额<100万特殊服务类目isMallService=1、isProjectService=1 // 判断是否显示自动公开比选模版40万<=金额<100万特殊服务类目isMallService=1、isProjectService=1
@@ -894,7 +833,7 @@ const showAutoPublicSelect = computed(() => {
if (isDeptPurchase.value) return false; if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false; if (!dataForm.budget) return false;
const budget = dataForm.budget; const budget = dataForm.budget;
return budget >= 400000 && budget < 1000000 && isSpecialServiceCategory.value; return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD && budget < BUDGET_GOV_PURCHASE_THRESHOLD && isSpecialServiceCategory.value;
}); });
// 获取需求文件的 prop 名称(用于表单验证) // 获取需求文件的 prop 名称(用于表单验证)
@@ -916,25 +855,41 @@ const isAutoSelectPurchaseTypeUnion = computed(() => {
if (isDeptPurchase.value) return false; if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false; if (!dataForm.budget) return false;
const budget = dataForm.budget; const budget = dataForm.budget;
return budget >= 50000 && budget < 400000 && isSpecialServiceCategory.value; return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD && budget < BUDGET_PUBLIC_SELECT_THRESHOLD && isSpecialServiceCategory.value;
}); });
// 监听品目编码、预算金额采购类型变化,自动设置/清空采购方式 // 监听品目编码、预算金额采购类型及采购途径变化,自动设置/清空采购方式
watch([() => dataForm.categoryCode, () => dataForm.budget, () => isDeptPurchase.value, () => isFlowEmbed.value], () => { watch(
[() => dataForm.categoryCode, () => dataForm.budget, () => isDeptPurchase.value, () => isFlowEmbed.value, () => dataForm.purchaseChannel, () => isPurchaseCenter.value],
() => {
// 学校统一采购申请阶段:采购方式隐藏,由审批环节采购中心补充,此处不自动写入且清空已有值 // 学校统一采购申请阶段:采购方式隐藏,由审批环节采购中心补充,此处不自动写入且清空已有值
if (!isDeptPurchase.value && !isFlowEmbed.value) { if (!isDeptPurchase.value && !isFlowEmbed.value) {
dataForm.purchaseType = ''; dataForm.purchaseType = '';
return; return;
} }
// 部门自行采购:自动设置网上商城 // 部门自行采购 & 采购途径为“委托采购中心采购”且为申请阶段:采购方式隐藏且不设置
if (isAutoSelectPurchaseType.value && isDeptPurchase.value) { if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value) {
dataForm.purchaseType = '';
return;
}
// 部门自行采购 & 采购途径为“自行采购”:自动设置网上商城
if (isAutoSelectPurchaseType.value && isDeptPurchase.value && !isEntrustCenterChannel.value) {
const onlineMallOption = purchaseTypeDeptList.value.find(item => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL); const onlineMallOption = purchaseTypeDeptList.value.find(item => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value; dataForm.purchaseType = onlineMallOption.value;
} }
} }
// 部门自行采购 & 采购途径为“委托采购中心采购” & 采购中心审批节点:根据特殊服务类目自动设置网上商城
if (isAutoSelectPurchaseType.value && isDeptPurchase.value && isEntrustCenterChannel.value && isFlowEmbed.value && isPurchaseCenter.value) {
const onlineMallOption = purchaseTypeDeptList.value.find(item => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value;
}
}
// 学校统一采购审批阶段:自动设置网上商城采购方式 // 学校统一采购审批阶段:自动设置网上商城采购方式
if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value && isFlowEmbed.value) { if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value && isFlowEmbed.value) {
const onlineMallOption = purchaseTypeUnionList.value.find(item => item.value === UNION_PURCHASE_TYPE.ONLINE_MALL); const onlineMallOption = purchaseTypeUnionList.value.find(item => item.value === UNION_PURCHASE_TYPE.ONLINE_MALL);
@@ -942,7 +897,8 @@ watch([() => dataForm.categoryCode, () => dataForm.budget, () => isDeptPurchase.
dataForm.purchaseType = onlineMallOption.value; dataForm.purchaseType = onlineMallOption.value;
} }
} }
}, { immediate: true }); },
{ immediate: true });
// 学校统一采购:采购形式由规则默认选择,随预算与集采变化自动更新 // 学校统一采购:采购形式由规则默认选择,随预算与集采变化自动更新
watch([() => schoolUnifiedPurchaseFormDefault.value, () => isDeptPurchase.value], () => { watch([() => schoolUnifiedPurchaseFormDefault.value, () => isDeptPurchase.value], () => {
@@ -953,21 +909,21 @@ watch([() => schoolUnifiedPurchaseFormDefault.value, () => isDeptPurchase.value]
} }
}, { immediate: true }); }, { immediate: true });
// 下载模版 // 下载模版:统一走后端接口,按原始文件下载(避免前端静态资源被当成 HTML 返回)
const downloadTemplate = async (type: string) => { const downloadTemplate = async (type: string) => {
const templateMap: Record<string, { fileName: string, displayName: string }> = { const templateMap: Record<string, { displayName: string }> = {
'business_negotiation': { fileName: '商务洽谈表.xlsx', displayName: '商务洽谈表.xlsx' }, business_negotiation: { displayName: '商务洽谈表.doc' },
'market_purchase_minutes': { fileName: '市场采购纪要.xlsx', displayName: '市场采购纪要.xlsx' }, market_purchase_minutes: { displayName: '部门自行采购市场采购纪要.doc' },
'inquiry': { fileName: '部门采购询价模版.docx', displayName: '部门采购询价模版.docx' }, inquiry: { displayName: '部门采购询价模版.doc' },
'direct_select': { fileName: '服务商城项目需求模板(直选).doc', displayName: '服务商城项目需求模板(直选).doc' }, direct_select: { displayName: '服务商城项目需求模板(直选).doc' },
'public_select': { fileName: '服务商城项目需求模板(公开比选).doc', displayName: '服务商城项目需求模板(公开比选).doc' }, public_select: { displayName: '服务商城项目需求模板(公开比选).doc' },
'invite_select': { fileName: '服务商城项目需求模板(邀请比选).doc', displayName: '服务商城项目需求模板(邀请比选).doc' }, invite_select: { displayName: '服务商城项目需求模板(邀请比选).doc' },
'purchase_requirement': { fileName: '默认需求模板.doc', displayName: '默认需求模板.doc' }, purchase_requirement: { displayName: '采购需求填报模板.doc' },
'import_application': { fileName: '附件1进口产品申请及专家论证意见表.doc', displayName: '进口产品申请及专家论证意见表.doc' }, import_application: { displayName: '进口产品申请及专家论证意见表.doc' },
'single_source': { fileName: '表7单一来源论专家证附件.docx', displayName: '单一来源论专家证附件.docx' }, single_source: { displayName: '单一来源论专家证附件.docx' },
'feasibility_report': { fileName: '表6项目可行性论证报告模板.doc', displayName: '项目可行性论证报告模板.doc' }, feasibility_report: { displayName: '项目可行性论证报告模板.doc' },
}; };
const template = templateMap[type]; const template = templateMap[type];
if (!template) { if (!template) {
useMessage().error('模版不存在'); useMessage().error('模版不存在');
@@ -975,32 +931,14 @@ const downloadTemplate = async (type: string) => {
} }
try { try {
const fileUrl = new URL(`../../assets/file/${template.fileName}`, import.meta.url).href; await other.downBlobFile(
const response = await fetch(fileUrl); `/purchase/purchasingtemplate/download?type=${encodeURIComponent(type)}`,
if (!response.ok) { {},
throw new Error('文件下载失败'); template.displayName,
} );
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = template.displayName;
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(link);
useMessage().success('模版下载成功'); useMessage().success('模版下载成功');
} catch (error) { } catch (err) {
try { useMessage().error('模版下载失败,请联系管理员维护模版文件');
await other.downBlobFile(
`/purchase/purchasingfiles/downloadTemplate?type=${type}`,
{},
template.displayName
);
useMessage().success('模版下载成功');
} catch (err) {
useMessage().error('模版下载失败,请先维护模版文件');
}
} }
}; };
@@ -1031,8 +969,38 @@ const dataRules = reactive({
{ required: true, message: '采购内容不能为空', trigger: 'blur' }, { required: true, message: '采购内容不能为空', trigger: 'blur' },
{ max: 1000, message: '采购内容不能超过1000字', trigger: 'blur' } { max: 1000, message: '采购内容不能超过1000字', trigger: 'blur' }
], ],
purchaseChannel: [
{
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
if (!isDeptPurchase.value) {
callback();
return;
}
if (!value || String(value).trim() === '') {
callback(new Error('请选择采购途径'));
return;
}
callback();
},
trigger: 'change',
},
],
purchaseType: [ purchaseType: [
{ required: true, message: '请选择采购方式', trigger: 'change' } {
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
// 部门自行采购且采购途径为“委托采购中心采购”并且为申请阶段:此处不校验采购方式
if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value) {
callback();
return;
}
if (!value || String(value).trim() === '') {
callback(new Error('请选择采购方式'));
return;
}
callback();
},
trigger: 'change',
},
], ],
// 学校统一采购时必填 // 学校统一采购时必填
deptClassifyUserId: [ deptClassifyUserId: [
@@ -1098,7 +1066,8 @@ async function loadDetail(applyId: string | number) {
isCentralized: detail.isCentralized != null ? String(detail.isCentralized) : '', isCentralized: detail.isCentralized != null ? String(detail.isCentralized) : '',
isSpecial: detail.isSpecial != null ? String(detail.isSpecial) : '', isSpecial: detail.isSpecial != null ? String(detail.isSpecial) : '',
purchaseMode: detail.purchaseMode ?? '', purchaseMode: detail.purchaseMode ?? '',
purchaseType: detail.purchaseType ?? '', purchaseType: detail.purchaseType === DEPT_PURCHASE_TYPE.ENTRUST_CENTER ? '' : (detail.purchaseType ?? ''),
purchaseChannel: (detail as any).purchaseChannel ?? (detail.purchaseType === DEPT_PURCHASE_TYPE.ENTRUST_CENTER ? PURCHASE_CHANNEL.ENTRUST_CENTER : ''),
purchaseTypeUnion: detail.purchaseTypeUnion ?? '', purchaseTypeUnion: detail.purchaseTypeUnion ?? '',
categoryCode: detail.categoryCode ?? '', categoryCode: detail.categoryCode ?? '',
remark: detail.remark ?? '', remark: detail.remark ?? '',
@@ -1346,16 +1315,18 @@ const getIsSpecialDict = async () => {
} }
}; };
// 获取部门采购方式字典 // 获取部门采购方式字典(过滤掉“委托采购中心采购”,由采购途径字段控制)
const getPurchaseTypeDeptDict = async () => { const getPurchaseTypeDeptDict = async () => {
try { try {
const res = await getDicts('PURCHASE_TYPE_DEPT'); const res = await getDicts('PURCHASE_TYPE_DEPT');
purchaseTypeDeptList.value = res.data && Array.isArray(res.data) purchaseTypeDeptList.value = res.data && Array.isArray(res.data)
? res.data.map((item: any) => ({ ? res.data
id: item.id, .map((item: any) => ({
label: item.label || item.dictLabel || item.name, id: item.id,
value: item.value || item.dictValue || item.code label: item.label || item.dictLabel || item.name,
})) value: item.value || item.dictValue || item.code,
}))
.filter((item: any) => item.value !== DEPT_PURCHASE_TYPE.ENTRUST_CENTER)
: []; : [];
} catch (err) { } catch (err) {
purchaseTypeDeptList.value = []; purchaseTypeDeptList.value = [];

View File

@@ -0,0 +1,242 @@
<template>
<div class="modern-page-container">
<div class="page-wrapper">
<el-card class="content-card" shadow="never">
<template #header>
<div class="card-header">
<div class="header-actions">
<el-button type="primary" icon="FolderAdd" @click="openUploadDialog()">
新增模板
</el-button>
</div>
</div>
</template>
<el-table :data="tableData" v-loading="loading" stripe class="modern-table">
<el-table-column type="index" label="序号" width="70" align="center">
<template #header>
<el-icon><List /></el-icon>
</template>
</el-table-column>
<el-table-column prop="templateTitle" label="模板类型名称" min-width="180" show-overflow-tooltip />
<el-table-column prop="templateType" label="模板类型编码" min-width="180" show-overflow-tooltip />
<el-table-column prop="templateName" label="模板名称" min-width="220" show-overflow-tooltip />
<el-table-column prop="updateTime" label="更新时间" width="180" show-overflow-tooltip />
<el-table-column label="操作" width="260" align="center" fixed="right">
<template #default="{ row }">
<el-button type="primary" link icon="Download" @click="handleDownload(row)">
下载
</el-button>
<el-button type="primary" link icon="UploadFilled" @click="openUploadDialog(row)">
重新上传
</el-button>
<el-button type="primary" link icon="Edit" @click="openEditDialog(row)">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="uploadDialogVisible" title="上传模板" width="450px" destroy-on-close>
<el-form :model="uploadForm" label-width="100px">
<el-form-item label="模板类型编码" required>
<el-input
v-model="uploadForm.templateType"
placeholder="例如: business_negotiation, inquiry"
:disabled="!!uploadForm.lockType"
/>
</el-form-item>
<el-form-item label="模板类型名称">
<el-input
v-model="uploadForm.templateTitle"
placeholder="例如: 部门采购询价模版"
/>
</el-form-item>
<el-form-item label="模板文件" required>
<el-upload
class="upload-block"
:auto-upload="false"
:limit="1"
:file-list="fileList"
:on-change="handleFileChange"
:on-remove="handleFileRemove"
>
<el-button type="primary" icon="UploadFilled">选择文件</el-button>
<template #tip>
<div class="el-upload__tip">支持 docdocx Word 模板文件上传后前端下载将使用该文件</div>
</template>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="uploadDialogVisible = false"> </el-button>
<el-button type="primary" :loading="uploading" @click="handleUploadConfirm"> </el-button>
</template>
</el-dialog>
<el-dialog v-model="editDialogVisible" title="编辑模板" width="420px" destroy-on-close>
<el-form :model="editForm" label-width="100px">
<el-form-item label="模板类型编码">
<el-input v-model="editForm.templateType" disabled />
</el-form-item>
<el-form-item label="模板类型名称" required>
<el-input v-model="editForm.templateTitle" placeholder="请输入模板类型名称" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editDialogVisible = false"> </el-button>
<el-button type="primary" :loading="editing" @click="handleEditConfirm"> </el-button>
</template>
</el-dialog>
</div>
</div>
</template>
<script setup lang="ts" name="PurchasingTemplateManage">
import { ref, reactive, onMounted } from 'vue';
import { Document, List, UploadFilled, Download, Edit } from '@element-plus/icons-vue';
import { listTemplates, uploadTemplate, getTemplateDownloadUrl, updateTemplateTitle } from '/@/api/finance/purchasingtemplate';
import { useMessage } from '/@/hooks/message';
const loading = ref(false);
const tableData = ref<any[]>([]);
const uploadDialogVisible = ref(false);
const uploading = ref(false);
const uploadForm = reactive<{
templateType: string;
templateTitle: string;
lockType?: boolean;
}>({
templateType: '',
templateTitle: '',
lockType: false,
});
const editDialogVisible = ref(false);
const editing = ref(false);
const editForm = reactive<{
id: number | null;
templateType: string;
templateTitle: string;
}>({
id: null,
templateType: '',
templateTitle: '',
});
const fileList = ref<any[]>([]);
const currentFile = ref<File | null>(null);
const fetchData = async () => {
loading.value = true;
try {
const res = await listTemplates();
tableData.value = (res && res.data) || [];
} catch (e) {
tableData.value = [];
} finally {
loading.value = false;
}
};
onMounted(fetchData);
const openUploadDialog = (row?: any) => {
uploadDialogVisible.value = true;
uploadForm.templateType = row?.templateType || '';
uploadForm.templateTitle = row?.templateTitle || '';
uploadForm.lockType = !!row?.templateType;
fileList.value = [];
currentFile.value = null;
};
const handleFileChange = (file: any, files: any[]) => {
fileList.value = files.slice(-1);
currentFile.value = file.raw || null;
};
const handleFileRemove = () => {
fileList.value = [];
currentFile.value = null;
};
const handleUploadConfirm = async () => {
if (!uploadForm.templateType || !uploadForm.templateType.trim()) {
useMessage().error('请填写模板类型编码');
return;
}
if (!currentFile.value) {
useMessage().error('请选择要上传的模板文件');
return;
}
uploading.value = true;
try {
const formData = new FormData();
formData.append('type', uploadForm.templateType.trim());
if (uploadForm.templateTitle && uploadForm.templateTitle.trim()) {
formData.append('title', uploadForm.templateTitle.trim());
}
formData.append('file', currentFile.value);
await uploadTemplate(formData);
useMessage().success('模板上传成功');
uploadDialogVisible.value = false;
await fetchData();
} catch (e) {
useMessage().error('模板上传失败');
} finally {
uploading.value = false;
}
};
const handleDownload = (row: any) => {
if (!row?.templateType) {
useMessage().error('缺少模板类型编码');
return;
}
const url = getTemplateDownloadUrl(row.templateType);
window.open(url, '_blank');
};
const openEditDialog = (row: any) => {
editDialogVisible.value = true;
editForm.id = row?.id ?? null;
editForm.templateType = row?.templateType || '';
editForm.templateTitle = row?.templateTitle || '';
};
const handleEditConfirm = async () => {
if (!editForm.id) {
useMessage().error('缺少模板ID');
return;
}
if (!editForm.templateTitle || !editForm.templateTitle.trim()) {
useMessage().error('请输入模板类型名称');
return;
}
editing.value = true;
try {
await updateTemplateTitle({
id: editForm.id,
templateTitle: editForm.templateTitle.trim(),
});
useMessage().success('保存成功');
editDialogVisible.value = false;
await fetchData();
} catch (e) {
useMessage().error('保存失败');
} finally {
editing.value = false;
}
};
</script>
<style scoped>
.upload-block {
display: inline-block;
}
</style>