diff --git a/src/components/Upload/index.vue b/src/components/Upload/index.vue index 179cb7a..e456b13 100644 --- a/src/components/Upload/index.vue +++ b/src/components/Upload/index.vue @@ -503,7 +503,7 @@ const handlePreview = async (file: any) => { const ext = fileName.split('.').pop()?.toLowerCase() || ''; // 判断是否是图片 - const imageExts = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']; + const imageExts = ['png', 'jpg', 'jpeg']; // 判断是否是PDF const isPdf = ext === 'pdf'; diff --git a/src/views/purchase/purchasingrequisition/add.vue b/src/views/purchase/purchasingrequisition/add.vue index f276f1a..53b7a1a 100644 --- a/src/views/purchase/purchasingrequisition/add.vue +++ b/src/views/purchase/purchasingrequisition/add.vue @@ -2,24 +2,17 @@
- +
-
- 帮助 -
+ + + @@ -31,7 +24,7 @@ v-model="dataForm.projectName" placeholder="请输入采购项目名称" clearable - :disabled="flowFieldDisabled('projectName')" + :disabled="false" /> @@ -44,7 +37,7 @@ format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width: 100%" - :disabled="flowFieldDisabled('applyDate')" + :disabled="false" /> @@ -55,7 +48,7 @@ placeholder="请选择资金来源" clearable style="width: 100%" - :disabled="flowFieldDisabled('fundSource')" + :disabled="false" > @@ -71,7 +64,7 @@ placeholder="请输入金额" :controls="false" style="width: 100%" - :disabled="flowFieldDisabled('budget')" + :disabled="false" />
@@ -84,7 +77,7 @@ placeholder="请选择是否集采" clearable style="width: 100%" - :disabled="flowFieldDisabled('isCentralized')" + :disabled="false" > @@ -97,20 +90,12 @@ placeholder="请选择是否特殊情况" clearable style="width: 100%" - :disabled="flowFieldDisabled('isSpecial')" + :disabled="false" > - - - - - - - - @@ -130,51 +115,35 @@
- -
- - 请先填写上方「是否特殊情况」「是否集采」「预算金额」,系统将根据填写结果展示「部门自行采购」或「学校统一采购」表单。 - - - - - - - - - - -
-
部门自行采购
- - - - - - - + +
+ +
+
{{ stepTwoTitle }}
+ + + + + + + + + @@ -182,26 +151,33 @@ - - + + + + + + {{ item.label }} + + + + + + + - + - - - - + + - + + + + + + + + + + + + + - + + - + + - + + - - - - - - - - - - - - 下载《服务商城项目需求模板(直选)》模版 - - - - - - - 下载《服务商城项目需求模板(公开比选)》模版 - - - - - - - 下载《表1:需求模板》模版 - - - - - - - - 下载《表1:需求模板》模版 - - - - - - - - 下载《表1:需求模板》模版 - - - - - - - - - - - - - - - 下载《服务商城项目需求模板(邀请比选)》模版 - - - - - - - 下载《服务商城项目需求模板(公开比选)》模版 - - - - - - -
支持上传zip格式的压缩包文件
-
-
-
-
- -
-
学校统一采购
- - - - - - {{ item.label }} - - - - - - - - - - - - + + + + + + + - - - + + - - + + + + + - - + + - + + + + + + + + - + + - - + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + 下载《{{ requirementFileConfig.templateName }}》模版 + + + +
支持上传zip格式的压缩包文件
@@ -844,14 +508,14 @@ :rows="2" placeholder="请输入备注" clearable - :disabled="flowFieldDisabled('remark')" + :disabled="false" />
-
+
招标代理 @@ -861,7 +525,7 @@
-
+
采购代表/评委 @@ -876,59 +540,10 @@
- - - - 以下规则仅作为自动推荐与必填校验依据,实际录入时可在允许范围内调整。 - - -
    -
  • - 部门自行采购 / 学校统一采购划分: 当「是否特殊情况 = 否」「是否集采 = 否」且预算金额 < 5 万({{ - BUDGET_DEPT_PURCHASE_THRESHOLD - }} - 元)时,系统判定为「部门自行采购」,否则为「学校统一采购」。 -
  • -
  • - 学校统一采购 - 采购形式默认值: 当预算金额 ≥ 100 万({{ BUDGET_GOV_PURCHASE_THRESHOLD }} 元)时默认「政府采购」; - 当 5 万 ≤ 预算金额 < 100 万时,根据「是否集采」自动推荐「政府采购」或「学校自主采购」, 但申请人可以在界面上自行修改。 -
  • -
  • - 部门自行采购 - 自动网上商城: - 在「部门自行采购」且为服务类特殊品目时,系统会自动将采购方式推荐为「网上商城」(服务类),同时要求上传相应模板文件。 -
  • -
  • - 学校统一采购 - 自动邀请/公开比选模板: 对服务类特殊品目: 当 5 万 ≤ 预算金额 < 40 - 万时,系统根据「是否有推荐供应商」在邀请比选 / 公开比选模板之间自动切换必填文件; 当 40 万 ≤ 预算金额 < 100 - 万时,系统默认要求使用公开比选模板。 -
  • -
  • - 可行性论证与会议纪要(学校统一采购): 当预算金额 ≥ 30 万({{ - BUDGET_FEASIBILITY_THRESHOLD - }} - 元)且不是紧急/单一/进口等特殊情况时, - 需要上传「项目可行性论证报告」和「会议纪要」;紧急、单一来源、进口等特殊情况对应有单独的证明材料与会议纪要要求。 -
  • -
  • - 政府采购意向表: 当预算金额 ≥ 100 万({{ - BUDGET_GOV_PURCHASE_THRESHOLD - }} - 元),需要填写政府采购意向表并上传对应模板文件。 -
  • -
  • - 委托采购中心采购: - 在「部门自行采购」中选择「委托采购中心采购」作为采购途径时,申请阶段隐藏采购方式,由采购中心在审核环节选择; - 对服务类特殊品目,采购中心会优先推荐「网上商城(服务网上商城)」方式。 -
  • -
-
- -
+ -
+
实施采购信息 @@ -976,21 +591,10 @@
- +
@@ -1005,93 +609,34 @@ import { addObj, tempStore, getObj, editObj, getApplyFiles } from '/@/api/purcha import { getTree } from '/@/api/purchase/purchasingcategory'; import { getDicts } from '/@/api/admin/dict'; import { useMessage } from '/@/hooks/message'; -import { useUserInfo } from '/@/stores/userInfo'; + import { usePurchaseRulesSingleton } from '/@/hooks/usePurchaseRules'; import UploadFile from '/@/components/Upload/index.vue'; import other from '/@/utils/other'; -import { Document, Download, QuestionFilled } from '@element-plus/icons-vue'; +import { Session } from '/@/utils/storage'; +import { Document } from '@element-plus/icons-vue'; import { fetchList as getBusinessDeptList } from '/@/api/purchase/purchasingBusinessDept'; import { getPage as getSchoolLeaderPage } from '/@/api/purchase/purchasingschoolleader'; import { fetchList as getPurchasingManagerList } from '/@/api/purchase/purchasingPurchaseManager'; import { fetchList as getBusinessLeaderList } from '/@/api/purchase/purchasingBusinessLeader'; -import { Session } from '/@/utils/storage'; -import * as orderVue from '/@/api/order/order-key-vue'; -/** 采购中心角色编码:审批时仅该角色可编辑采购方式/采购形式 */ -const PURCHASE_CENTER_ROLE_CODE = 'PURCHASE_CENTER'; -const PURCHASE_DEPT_APPLY_ROLE_CODE = 'ROLE_PURCHASE_DEPT_APPLY'; - -// 兼容流程 dynamic-link 引用:接收 currJob / currElTab,并支持 handleJob 事件 -const props = defineProps({ - currJob: { type: Object, default: null }, - currElTab: { type: Object, default: null }, -}); -const emit = defineEmits(['handleJob']); - -// 路由 const router = useRouter(); const route = useRoute(); -/** 是否被流程 handle 页通过 dynamic-link 嵌入 */ -const isFlowEmbed = computed(() => !!props.currJob); - -/** 当前使用的申请单 ID:优先来自流程 currJob.orderId,否则来自 route.query.id */ +// 当前使用的申请单 ID const effectiveQueryId = computed(() => { - if (props.currJob?.orderId != null && props.currJob?.orderId !== '') { - return String(props.currJob.orderId); - } const q = route.query.id; return q ? String(q) : ''; }); -// 模式:add | edit | view(URL 参数 或 流程嵌入时的 currJob/currElTab) -const isEditMode = computed(() => { - if (isFlowEmbed.value && props.currElTab) { - return !!effectiveQueryId.value && props.currElTab.isFormEdit !== '0' && !props.currJob?.hiJob; - } - return String(route.query.mode) === 'edit'; -}); -const isViewMode = computed(() => { - if (isFlowEmbed.value && props.currJob) { - if (props.currJob.hiJob) return true; - if (props.currElTab?.isFormEdit === '0') return true; - return false; - } - return String(route.query.mode) === 'view'; -}); +// 模式:add | edit | view const pageTitle = computed(() => { - if (isViewMode.value) return '查看采购申请'; - if (isEditMode.value) return '编辑采购申请'; + const mode = String(route.query.mode); + if (mode === 'view') return '查看采购申请'; + if (mode === 'edit') return '编辑采购申请'; return '新增采购申请'; }); -/** 流程嵌入时,由 currElTabIsView 控制的只读/禁用提交 */ -const flowFormDisabled = ref(false); -const flowSubmitDisabled = ref(false); - -/** 流程嵌入时当前节点是否为采购中心(仅采购中心可编辑采购方式/采购形式) */ -const isPurchaseCenter = ref(false); - -/** 流程嵌入时:采购中心审核节点放开所有字段编辑;非采购中心节点只读 */ -function flowFieldDisabled(_key: string) { - if (isFlowEmbed.value && isPurchaseCenter.value) return false; - if (isFlowEmbed.value && isApplicant.value) return false; - return !!isFlowEmbed.value; -} - -/** 当前用户是否为申请人(在流程中可编辑) */ -const isApplicant = computed(() => { - - const stores = useUserInfo(); - const currentUser = stores.userInfos?.user || {}; - console.log(currentUser) - if (!dataForm.createBy) return false; - - // const stores = useUserInfo(); - // const currentUser = stores.userInfos?.user || {}; - return dataForm.createBy === currentUser.username; -}); - // 定义变量内容 const formRef = ref(); const dataForm = reactive({ @@ -1118,31 +663,17 @@ const dataForm = reactive({ marketPurchaseMinutes: '', onlineMallMaterials: '', inquiryTemplate: '', // 询价模板 - entrustCenterType: '', hasSupplier: '0', suppliers: '', // 供应商名称(逗号或分号分隔) - serviceDirectSelect: '', - servicePublicSelect: '', purchaseRequirementTemplate: '', - - serviceInviteSelect: '', - servicePublicSelectAuto: '', deptSelfMeetingMinutes: '', // 部门自行采购会议纪要 // 学校统一采购字段 purchaseRequirement: '', meetingMinutes: '', feasibilityReport: '', - meetingMinutesUrgent: '', - meetingMinutesSingle: '', - meetingMinutesImport: '', singleSourceProof: '', importApplication: '', governmentPurchaseIntent: '', - servicePublicSelectSchool: '', - // 学校统一采购特殊规则字段(5万<=金额<40万) - - serviceInviteSelectSchool: '', - servicePublicSelectSchoolAuto: '', // 业务分管处室和分管校领导 deptClassifyUserId: '', deptClassifyName: '', @@ -1188,32 +719,22 @@ const loading = ref(false); const helpDialogVisible = ref(false); // 文件类型映射(对应数据库 file_type 字段) -// 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140: 部门自行采购会议纪要 +// 附件类型 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品申请及专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140:部门自行采购会议纪要 150:部门询价模 const FILE_TYPE_MAP: Record = { businessNegotiationTable: '10', // 商务洽谈纪要 marketPurchaseMinutes: '20', // 市场采购纪要 - inquiryTemplate: '20', // 询价模板(归类到市场采购纪要) onlineMallMaterials: '30', // 网上商城采购相关材料 feasibilityReport: '40', // 可行性论证报告 meetingMinutes: '50', // 会议记录 - meetingMinutesUrgent: '50', // 会议记录 - meetingMinutesSingle: '50', // 会议记录 - meetingMinutesImport: '50', // 会议记录 otherMaterials: '60', // 其他材料 singleSourceProof: '70', // 单一来源专家论证表 importApplication: '90', // 进口产品申请表 governmentPurchaseIntent: '100', // 政府采购意向表 // 需求文件相关 - 所有需求模板都应该是 120(采购需求表) - serviceDirectSelect: '120', // 服务商城项目需求模板(直选)- 采购需求表 - serviceInviteSelect: '120', // 服务商城项目需求模板(邀请比选)- 采购需求表 - servicePublicSelect: '120', // 服务商城项目需求模板(公开比选)- 采购需求表 - servicePublicSelectAuto: '120', // 服务商城项目需求模板(公开比选 - 自动)- 采购需求表 - purchaseRequirementTemplate: '120', // 需求模板 - 采购需求表 + // 需求文件(统一)- 采购需求表 purchaseRequirement: '120', // 需求模板 - 采购需求表 - serviceInviteSelectSchool: '120', // 服务商城项目需求模板(邀请比选 - 学校)- 采购需求表 - servicePublicSelectSchoolAuto: '120', // 服务商城项目需求模板(公开比选 - 学校 - 自动)- 采购需求表 - servicePublicSelectSchool: '120', // 服务商城项目需求模板(公开比选 - 学校)- 采购需求表 deptSelfMeetingMinutes: '140', // 部门自行采购会议纪要 + inquiryTemplate: '150' // 询价模板 }; // fileType -> 表单字段名数组(顺序与回填分配一致,同类型多字段时按此顺序分配) @@ -1276,6 +797,41 @@ const PURCHASE_CHANNEL = { ENTRUST_CENTER: '2', } as const; +// 角色常量 +const PURCHASE_DEPT_APPLY_ROLE_CODE = 'PURCHASE_DEPT_APPLY'; + +// 判断当前登录用户是否为部门申请角色 +const roleCode = computed(() => Session.getRoleCode() || ''); +const isDeptApplyRole = computed(() => roleCode.value === PURCHASE_DEPT_APPLY_ROLE_CODE); + +// 部门申请角色 + 委托采购中心采购:隐藏采购方式 +const isHidePurchaseType = computed(() => { + return isDeptApplyRole.value && (isEntrustCenterChannel.value || !isDeptPurchase.value); +}); + +// 部门申请角色 + 学校统一采购:隐藏采购方式 +const isHidePurchaseSchool = computed(() => { + return isDeptApplyRole || ( isDeptApplyRole.value && !isDeptPurchase.value); +}); + + +// 学校统一采购 && 非特殊 && 预算小于30万 显示业务分管校领导 +const isShowPurchaseManagerUserId = computed(() => { + return !isDeptPurchase.value && isSpecialType("0") && Number(dataForm.budget) < BUDGET_PUBLIC_SELECT_THRESHOLD.value; +}); +// 学校统一采购 && 非特殊 显示业务分管校领导 +const isShowSchoolLeaderUserId = computed(() => { + return !isDeptPurchase.value && (!isSpecialType("0") || Number(dataForm.budget) >= BUDGET_PUBLIC_SELECT_THRESHOLD.value); +}); + +// 部门申请角色 + 自行采购 + 服务类网上商城品目:采购方式默认网上商城且disabled +const isPurchaseTypeLockedToOnlineMall = computed(() => { + return isDeptApplyRole.value && isEntrustSelfChannel.value && isMallServiceCategory.value; +}); + +// 判断是否为自行采购 +const isEntrustSelfChannel = computed(() => dataForm.purchaseChannel === PURCHASE_CHANNEL.SELF); + // 判断是否为部门自行采购 // 条件:特殊情况=否 且 集采=否 且 预算金额<5万 → 部门自行采购 // 其他情况 → 学校统一采购 @@ -1297,16 +853,20 @@ const isDeptPurchase = computed(() => { // 是否为“委托采购中心采购”途径 const isEntrustCenterChannel = computed(() => dataForm.purchaseChannel === PURCHASE_CHANNEL.ENTRUST_CENTER); -// 是否已填入“是否特殊情况”“是否集采”“预算金额”,从而能明确是部门自行采购还是学校统一采购(新增时先隐藏采购详情,填完后再显示) +// 第二步标题 +const stepTwoTitle = computed(() => { + return isDeptPurchase.value ? '部门自行采购' : '学校统一采购'; +}); + const isPurchaseTypeDetermined = computed(() => { return dataForm.isSpecial !== '' && dataForm.isCentralized !== '' && dataForm.budget != null && Number(dataForm.budget) > 0; }); -// 是否显示“部门自行采购/学校统一采购”区块:查看/编辑/流程嵌入/已保存过 时直接显示;新增时仅当类型已明确后显示 +// 是否显示“部门自行采购/学校统一采购”区块:查看/编辑/已保存过 时直接显示;新增时仅当类型已明确后显示 const showPurchaseDetailBlocks = computed(() => { - return !!isViewMode.value || !!isFlowEmbed.value || !!dataForm.id || isPurchaseTypeDetermined.value; + return !!dataForm.id || isPurchaseTypeDetermined.value; }); -// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1');5万~100万且集采=学校集中采购→学校自主('2') +// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1'); const schoolUnifiedPurchaseFormDefault = computed(() => { if (isDeptPurchase.value || dataForm.budget == null) return null; const budget = Number(dataForm.budget); @@ -1314,39 +874,19 @@ const schoolUnifiedPurchaseFormDefault = computed(() => { if (budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value) { if (dataForm.isCentralized === '0') return '2'; // 集采=否 → 学校自主采购 if (dataForm.isCentralized === '1') return '1'; // 政府集中采购 → 政府采购 - if (dataForm.isCentralized === '2') return '2'; // 学校集中采购 → 学校自主采购 + } - return null; + return '2'; }); -// 学校统一采购时采购形式是否禁用 -// 申请阶段:始终可选(根据默认值自动选中后,允许用户自行修改) -// 流程嵌入:采购中心节点可编辑,其他节点只读 -const schoolUnifiedPurchaseFormDisabled = computed(() => { - // if (!isFlowEmbed.value) { - // return false; - // } - // 流程嵌入且为采购中心:放开编辑 - if (isPurchaseCenter.value) { - return false; - } - // 其他流程节点只读 - return true; -}); -// 特殊情况字典 value:0否 1紧急 2单一 3进口 -const isUrgentSpecial = computed(() => dataForm.isSpecial === '1'); + // 是否为特殊情况(非0即为特殊情况:紧急、单一、进口) const isSpecialCase = computed(() => { return dataForm.isSpecial && dataForm.isSpecial !== '0'; }); -// 第二步标题 -const stepTwoTitle = computed(() => { - return isDeptPurchase.value ? '部门自行采购' : '学校统一采购'; -}); - // 根据 code 查找完整路径(用于回显) const findCategoryPath = (data: any[], targetCode: string, path: string[] = []): string[] | null => { for (const item of data) { @@ -1411,66 +951,31 @@ const isGoodsCategory = computed(() => { return category.type === 'A'; }); -// 判断是否为特殊服务类目(isMallService=1、isProjectService=1) -const isSpecialServiceCategory = computed(() => { +// 判断是否为服务类网上商城品目(isMallService=1、isProjectService=1) +const isMallServiceCategory = computed(() => { const category = getCategoryInfo(); if (!category) return false; return Number(category.isMallService) === 1 || Number(category.isProjectService) === 1; }); -// 部门自行采购 & 采购途径=自行采购 & 特殊服务类目 → 采购方式固定网上商城 +// 部门自行采购 & 采购途径=自行采购 & 服务类网上商城品目 → 采购方式固定网上商城 const isDeptSelfMallLocked = computed(() => { - return isDeptPurchase.value && !isEntrustCenterChannel.value && isSpecialServiceCategory.value; + return isDeptPurchase.value && !isEntrustCenterChannel.value && isMallServiceCategory.value; }); -// 委托采购中心方式自动判断: -// - 服务类:若末级节点 isMallService=0 且 isMallProject=0,则选“其他方式”,否则选“服务类网上商城” -// - 非服务类:默认选“其他方式” -const calcEntrustCenterType = (): 'service_online' | 'other' | '' => { - if (!isEntrustCenterChannel.value) return ''; - if (!dataForm.categoryCode) return ''; - - const category = getCategoryInfo(); - if (!category) return ''; - - // 兼容字段:接口可能为 isMallProject,也可能历史字段为 isProjectService - const mallService = Number(category.isMallService ?? 0); - const mallProject = Number(category.isMallProject ?? category.isProjectService ?? 0); - - if (isServiceCategory.value) { - return mallService === 0 && mallProject === 0 ? 'other' : 'service_online'; - } - return 'other'; -}; - -// 监听品目/采购途径变化,自动设置委托采购中心方式,并清理无关字段 +// 监听 isDeptPurchase 变化:当从部门自行采购切换到学校统一采购(或反向)时,清空采购方式 watch( - [() => dataForm.purchaseChannel, () => dataForm.categoryCode, () => categoryTreeData.value], - () => { - const nextType = calcEntrustCenterType(); - if (!nextType) return; + () => isDeptPurchase.value, + (newVal, oldVal) => { - const prevType = dataForm.entrustCenterType as any; - if (prevType === nextType) return; - - dataForm.entrustCenterType = nextType; - - // 切换时清理不相关字段,避免脏数据 - if (nextType === 'other') { - dataForm.hasSupplier = '0'; - dataForm.suppliers = ''; - dataForm.serviceDirectSelect = ''; - dataForm.serviceInviteSelect = ''; - dataForm.servicePublicSelect = ''; - dataForm.servicePublicSelectAuto = ''; - } else if (nextType === 'service_online') { - dataForm.purchaseRequirementTemplate = ''; + // 仅当模式真正发生变化时(从 true 变为 false,或从 false 变为 true)才清空 + if (oldVal !== undefined && newVal !== oldVal) { + dataForm.purchaseType = ''; } - }, - { immediate: true } + } ); -// 判断是否自动选择网上商城采购方式(5万<=金额<40万,服务类目,特殊服务类目) +// 判断是否自动选择网上商城采购方式(5万<=金额<30万,服务类目,服务类网上商城品目) const isAutoSelectPurchaseType = computed(() => { if (!dataForm.budget) return false; const budget = dataForm.budget; @@ -1478,59 +983,78 @@ const isAutoSelectPurchaseType = computed(() => { budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isServiceCategory.value && - isSpecialServiceCategory.value + isMallServiceCategory.value ); }); -// 判断是否显示自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目) +// 部门采购 && 委托采购 && 服务商城品目,判断是否需要显示供应商 const showAutoInviteSelect = computed(() => { - if (!isDeptPurchase.value) return false; - if (!dataForm.budget) return false; - const budget = dataForm.budget; - return ( - budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && - budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && - isServiceCategory.value && - isSpecialServiceCategory.value - ); + return isDeptPurchase.value && isEntrustCenterChannel.value && isMallServiceCategory.value; }); -// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目) +// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<30万,服务类目,服务类网上商城品目) const showAutoInviteSelectSchool = computed(() => { if (isDeptPurchase.value) return false; if (!dataForm.budget) return false; const budget = dataForm.budget; - return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isSpecialServiceCategory.value; + return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value; }); -// 判断是否显示自动公开比选模版(40万<=金额<100万,特殊服务类目:isMallService=1、isProjectService=1) +// 判断是否显示自动公开比选模版(30万<=金额<100万,服务类网上商城品目:isMallService=1、isProjectService=1) const showAutoPublicSelect = computed(() => { if (isDeptPurchase.value) return false; if (!dataForm.budget) return false; const budget = dataForm.budget; - return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value && isSpecialServiceCategory.value; + return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value && isMallServiceCategory.value; }); -// 获取需求文件的 prop 名称(用于表单验证) -const getRequirementFileProp = () => { - if (showAutoInviteSelectSchool.value) { - if (dataForm.hasSupplier === '1') { - return 'serviceInviteSelectSchool'; - } else if (dataForm.hasSupplier === '0') { - return 'servicePublicSelectSchoolAuto'; - } - } else if (showAutoPublicSelect.value) { - return 'servicePublicSelectSchool'; - } - return 'purchaseRequirement'; -}; +// 需求文件配置:统一使用 purchaseRequirement 字段,根据不同场景显示不同的模板 +const requirementFileConfig = computed(() => { + const config = { + field: 'purchaseRequirement', + label: '需求文件', + templateType: 'purchase_requirement', + templateName: '需求模板', + }; -// 判断学校统一采购是否需要自动设置采购方式(5万<=金额<40万,服务类目,特殊服务类目) + // (部门自行采购 + 委托 ) + 有供应商 + if (showAutoInviteSelect.value && dataForm.hasSupplier === '1') { + return { ...config, label: '需求文件', templateType: 'invite_select', templateName: '服务商城项目需求模板(邀请比选)' }; + } + + //(部门自行采购 + 委托 ) + 无供应商 + if ( showAutoInviteSelect.value && dataForm.hasSupplier === '0') { + return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' }; + } + + // // 学校统一采购 + 5万~30万服务商城类目(有供应商) + if (!isDeptPurchase.value && showAutoInviteSelectSchool.value && dataForm.hasSupplier === '1') { + return { ...config, label: '需求文件', templateType: 'invite_select', templateName: '服务商城项目需求模板(邀请比选)' }; + } + + // 学校统一采购 + 5万~30万服务类商城类目(无供应商) + if (!isDeptPurchase.value && showAutoInviteSelectSchool.value && dataForm.hasSupplier === '0') { + return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' }; + } + // 学校统一采购 + 30万~100万服务类特殊类目 + if (!isDeptPurchase.value && showAutoPublicSelect.value) { + return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' }; + } + // 学校统一采购 + 100万以上 待定 + // if (!isDeptPurchase.value && showAutoPublicSelect.value) { + // return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' }; + // } + return config; +}); + + + +// 判断学校统一采购是否需要自动设置采购方式(5万<=金额<30万,服务类目,服务类网上商城品目) const isAutoSelectPurchaseTypeUnion = computed(() => { if (isDeptPurchase.value) return false; if (!dataForm.budget) return false; const budget = dataForm.budget; - return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isSpecialServiceCategory.value; + return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value; }); // 监听品目编码、预算金额、采购类型及采购途径变化,自动设置/清空采购方式 @@ -1539,19 +1063,34 @@ watch( () => dataForm.categoryCode, () => dataForm.budget, () => isDeptPurchase.value, - () => isFlowEmbed.value, + () => dataForm.purchaseChannel, - () => isPurchaseCenter.value, + ], () => { - // 部门自行采购 & 采购途径为”委托采购中心采购”且为新增申请阶段:采购方式隐藏且不设置 - // 注意:查看模式和编辑模式不清空已有的采购方式 - if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value && !isViewMode.value && !isEditMode.value) { + // 部门申请角色 + 委托采购中心采购:清空采购方式(已隐藏) + if (isDeptApplyRole.value && isEntrustCenterChannel.value) { dataForm.purchaseType = ''; return; } - // 部门自行采购 & 采购途径为“自行采购” & 特殊服务类目:固定网上商城(无论金额区间) + // 部门申请角色 + 自行采购 + 服务类网上商城品目:固定网上商城 + if (isDeptApplyRole.value && isEntrustSelfChannel.value && isMallServiceCategory.value) { + const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL); + if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { + dataForm.purchaseType = onlineMallOption.value; + } + return; + } + + // 部门自行采购 & 采购途径为"委托采购中心采购"且为新增申请阶段:采购方式隐藏且不设置 + // 注意:查看模式和编辑模式不清空已有的采购方式 + if (isDeptPurchase.value && isEntrustCenterChannel.value ) { + dataForm.purchaseType = ''; + return; + } + + // 部门自行采购 & 采购途径为"自行采购" & 服务类网上商城品目:固定网上商城(无论金额区间) if (isDeptSelfMallLocked.value) { const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL); if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { @@ -1561,7 +1100,7 @@ watch( return; } - // 其他部门自行采购 & 采购途径为“自行采购”:在金额区间内自动推荐网上商城 + // 其他部门自行采购 & 采购途径为"自行采购":在金额区间内自动推荐网上商城 if (isAutoSelectPurchaseType.value && isDeptPurchase.value && !isEntrustCenterChannel.value) { const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL); if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { @@ -1569,8 +1108,8 @@ watch( } } - // 部门自行采购 & 采购途径为”委托采购中心采购” & 采购中心审批节点:默认设置为网上商城 - if (isDeptPurchase.value && isEntrustCenterChannel.value && isFlowEmbed.value && isPurchaseCenter.value) { + // 部门自行采购 & 采购途径为"委托采购中心采购" & 采购中心审批节点:默认设置为网上商城 + if (isDeptPurchase.value && isEntrustCenterChannel.value) { const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL); if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { dataForm.purchaseType = onlineMallOption.value; @@ -1579,7 +1118,7 @@ watch( } // 学校统一采购审批阶段:自动设置网上商城采购方式 - if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value && isFlowEmbed.value) { + if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value) { const onlineMallOption = purchaseTypeUnionList.value.find((item) => item.value === UNION_PURCHASE_TYPE.ONLINE_MALL); if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) { dataForm.purchaseType = onlineMallOption.value; @@ -1671,8 +1210,8 @@ const dataRules = reactive({ callback(); return; } - // 部门自行采购且采购途径为"委托采购中心采购"并且为申请阶段:此处不校验采购方式 - if (isEntrustCenterChannel.value && !isFlowEmbed.value) { + // 部门自行采购且采购途径为"委托采购中心采购"此处不校验采购方式 + if (isEntrustCenterChannel.value ) { callback(); return; } @@ -1773,14 +1312,80 @@ const dataRules = reactive({ trigger: 'blur', }, ], + // 需求模板:委托采购中心采购时,货物类/工程类/服务类必填 + purchaseRequirementTemplate: [ + { + validator: (_rule: any, value: string, callback: (e?: Error) => void) => { + // 仅在委托采购中心采购且品目编码为A/B/C类时校验 + if (isEntrustCenterChannel.value && categoryCodePath.value && categoryCodePath.value.length > 0) { + const firstCode = categoryCodePath.value[0]; + if ((firstCode === 'A' || firstCode === 'B' || firstCode === 'C') && (!value || String(value).trim() === '')) { + callback(new Error('需求模板不能为空')); + return; + } + } + callback(); + }, + trigger: 'change', + }, + ], + // 商务洽谈表:采购方式为商务洽谈时必填 + businessNegotiationTable: [ + { + validator: (_rule: any, value: string, callback: (e?: Error) => void) => { + if (isPurchaseType(DEPT_PURCHASE_TYPE.BUSINESS_NEGOTIATION) && (!value || String(value).trim() === '')) { + callback(new Error('商务洽谈表不能为空')); + return; + } + callback(); + }, + trigger: 'change', + }, + ], + // 市场采购纪要:采购方式为市场采购时必填 + marketPurchaseMinutes: [ + { + validator: (_rule: any, value: string, callback: (e?: Error) => void) => { + if (isPurchaseType(DEPT_PURCHASE_TYPE.MARKET_PURCHASE) && (!value || String(value).trim() === '')) { + callback(new Error('市场采购纪要不能为空')); + return; + } + callback(); + }, + trigger: 'change', + }, + ], + // 网上商城采购相关材料:采购方式为网上商城时必填 + onlineMallMaterials: [ + { + validator: (_rule: any, value: string, callback: (e?: Error) => void) => { + if (isPurchaseType(DEPT_PURCHASE_TYPE.ONLINE_MALL) && (!value || String(value).trim() === '')) { + callback(new Error('网上商城采购相关材料不能为空')); + return; + } + callback(); + }, + trigger: 'change', + }, + ], + // 询价模板:采购方式为询价时必填 + inquiryTemplate: [ + { + validator: (_rule: any, value: string, callback: (e?: Error) => void) => { + if (isInquiryPurchaseType.value && (!value || String(value).trim() === '')) { + callback(new Error('询价模板不能为空')); + return; + } + callback(); + }, + trigger: 'change', + }, + ], }); // 取消 const handleCancel = () => { - // 流程嵌入时由流程页处理返回,不 postMessage - if (isFlowEmbed.value) { - return; - } + if (window.parent !== window) { window.parent.postMessage( { @@ -1830,26 +1435,15 @@ async function loadDetail(applyId: string | number) { marketPurchaseMinutes: detail.marketPurchaseMinutes ?? '', onlineMallMaterials: detail.onlineMallMaterials ?? '', inquiryTemplate: detail.inquiryTemplate ?? '', - entrustCenterType: detail.entrustCenterType ?? '', hasSupplier: detail.hasSupplier != null && detail.hasSupplier !== '' ? detail.hasSupplier : '0', suppliers: detail.suppliers ?? '', - serviceDirectSelect: detail.serviceDirectSelect ?? '', - servicePublicSelect: detail.servicePublicSelect ?? '', purchaseRequirementTemplate: detail.purchaseRequirementTemplate ?? '', - serviceInviteSelect: detail.serviceInviteSelect ?? '', - servicePublicSelectAuto: detail.servicePublicSelectAuto ?? '', purchaseRequirement: detail.purchaseRequirement ?? '', meetingMinutes: detail.meetingMinutes ?? '', feasibilityReport: detail.feasibilityReport ?? '', - meetingMinutesUrgent: detail.meetingMinutesUrgent ?? '', - meetingMinutesSingle: detail.meetingMinutesSingle ?? '', - meetingMinutesImport: detail.meetingMinutesImport ?? '', singleSourceProof: detail.singleSourceProof ?? '', importApplication: detail.importApplication ?? '', governmentPurchaseIntent: detail.governmentPurchaseIntent ?? '', - servicePublicSelectSchool: detail.servicePublicSelectSchool ?? '', - serviceInviteSelectSchool: detail.serviceInviteSelectSchool ?? '', - servicePublicSelectSchoolAuto: detail.servicePublicSelectSchoolAuto ?? '', deptClassifyUserId: detail.deptClassifyUserId ?? '', deptClassifyName: detail.deptClassifyName ?? '', schoolLeaderUserId: detail.schoolLeaderUserId ?? '', @@ -1944,88 +1538,7 @@ function downloadImplementFile(file: { id?: string; remark?: string; fileTitle?: other.downBlobFile(url, {}, file.fileTitle || '招标文件'); return; } - useMessage().warning('无法获取文件信息'); -} - -/** 流程嵌入时提供给 orderVue.currElTabIsView 的 methods(只读/禁用提交) */ -const flowMethods = { - disableForm(disabled?: boolean) { - flowFormDisabled.value = !!disabled; - }, - disableSubmit() { - flowSubmitDisabled.value = true; - }, - enableSubmit() { - flowSubmitDisabled.value = false; - }, -}; - -/** 流程嵌入时采购申请权限:根据前端缓存的角色(cloud-ui:roleCode)判断,非采购中心整表只读,采购中心仅采购方式/采购形式可编辑;申请人在流程中可编辑 */ -function applyPurchaseApplyFormPerm() { - if (!isFlowEmbed.value) return; - const roleCode = Session.getRoleCode() || ''; - isPurchaseCenter.value = roleCode === PURCHASE_CENTER_ROLE_CODE; - if (isApplicant.value) { - flowFormDisabled.value = false; - } else { - flowFormDisabled.value = !isPurchaseCenter.value; - } -} - -/** 流程嵌入时的“保存”回调:校验后调用 editObj,并通知流程已保存 */ -async function flowSubmitForm() { - if (loading.value) return; - loading.value = true; - try { - const valid = await formRef.value?.validate().catch(() => false); - if (!valid) { - loading.value = false; - return; - } - const submitData: any = { ...dataForm }; - const fileFields = [ - 'businessNegotiationTable', - 'marketPurchaseMinutes', - 'onlineMallMaterials', - 'inquiryTemplate', - 'serviceDirectSelect', - 'servicePublicSelect', - 'purchaseRequirementTemplate', - 'serviceInviteSelect', - 'servicePublicSelectAuto', - 'deptSelfMeetingMinutes', // 部门自行采购会议纪要 - 'purchaseRequirement', - 'meetingMinutes', - 'feasibilityReport', - 'meetingMinutesUrgent', - 'meetingMinutesSingle', - 'meetingMinutesImport', - 'singleSourceProof', - 'importApplication', - 'governmentPurchaseIntent', - 'servicePublicSelectSchool', - 'serviceInviteSelectSchool', - 'servicePublicSelectSchoolAuto', - 'otherMaterials', - ]; - const allFileIds: string[] = []; - fileFields.forEach((field) => { - if (submitData[field]) { - allFileIds.push(...getFileIdsArray(submitData[field])); - delete submitData[field]; - } - }); - if (allFileIds.length > 0) submitData.fileIds = allFileIds; - await editObj(submitData); - useMessage().success('保存成功'); - if (props.currJob && props.currElTab?.id) { - orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emit); - } - } catch (err: any) { - if (!err?.msg) useMessage().error('保存失败'); - } finally { - loading.value = false; - } +useMessage().warning('无法获取文件信息'); } // 获取品目树形数据 @@ -2398,106 +1911,6 @@ const getFileIdsArray = (fileIds: string | string[] | { id?: string; name?: stri return ids; }; -// 提交 -const handleSubmit = async () => { - if (loading.value) return; - loading.value = true; - - try { - const valid = await formRef.value?.validate().catch(() => {}); - if (!valid) { - loading.value = false; - return false; - } - - const submitData: any = { - ...dataForm, - }; - - // 学校统一采购申请阶段:采购方式由审批环节补充,提交时不写入 - if (!isFlowEmbed.value && !isDeptPurchase.value) { - submitData.purchaseType = ''; - } - - // 处理所有文件字段 - 收集所有文件ID到fileIds数组中 - const fileFields = [ - 'businessNegotiationTable', - 'marketPurchaseMinutes', - 'onlineMallMaterials', - 'inquiryTemplate', - 'serviceDirectSelect', - 'servicePublicSelect', - 'purchaseRequirementTemplate', - 'serviceInviteSelect', - 'servicePublicSelectAuto', - 'deptSelfMeetingMinutes', // 部门自行采购会议纪要 - 'purchaseRequirement', - 'meetingMinutes', - 'feasibilityReport', - 'meetingMinutesUrgent', - 'meetingMinutesSingle', - 'meetingMinutesImport', - 'singleSourceProof', - 'importApplication', - 'governmentPurchaseIntent', - 'servicePublicSelectSchool', - 'serviceInviteSelectSchool', - 'servicePublicSelectSchoolAuto', - 'otherMaterials', - ]; - - // 收集所有文件ID到一个数组中 - const allFileIds: string[] = []; - - fileFields.forEach((field) => { - if (submitData[field]) { - const ids = getFileIdsArray(submitData[field]); - console.log(`字段 ${field} 的文件ID:`, ids); - // 收集到总数组中 - allFileIds.push(...ids); - // 清空原字段,不再单独传递 - delete submitData[field]; - } - }); - - // 将所有文件ID统一放到fileIds字段中 - if (allFileIds.length > 0) { - submitData.fileIds = allFileIds; - console.log('所有文件ID (fileIds):', allFileIds); - } - - console.log('提交数据:', submitData); - - if (dataForm.id) { - await editObj(submitData); - useMessage().success('保存成功'); - } else { - await addObj(submitData); - useMessage().success('提交成功'); - } - - // 如果是在 iframe 中,向父窗口发送消息 - if (window.parent !== window) { - window.parent.postMessage( - { - type: 'purchasingrequisition:submitSuccess', - }, - '*' - ); - } else { - router.push('/purchase/purchasingrequisition'); - } - } catch (err: any) { - // 全局拦截器已经显示了错误提示,这里不需要再次显示 - // 只有当错误没有 msg 时才显示默认错误提示 - if (!err?.msg) { - useMessage().error('提交失败'); - } - } finally { - loading.value = false; - } -}; - // 暂存 const handleTempStore = async () => { if (loading.value) return; @@ -2515,7 +1928,7 @@ const handleTempStore = async () => { }; // 学校统一采购申请阶段:采购方式由审批环节补充,暂存时不写入 - if (!isFlowEmbed.value && !isDeptPurchase.value) { + if (!isDeptPurchase.value) { submitData.purchaseType = ''; } @@ -2525,24 +1938,14 @@ const handleTempStore = async () => { 'marketPurchaseMinutes', 'onlineMallMaterials', 'inquiryTemplate', - 'serviceDirectSelect', - 'servicePublicSelect', 'purchaseRequirementTemplate', - 'serviceInviteSelect', - 'servicePublicSelectAuto', 'deptSelfMeetingMinutes', // 部门自行采购会议纪要 'purchaseRequirement', 'meetingMinutes', 'feasibilityReport', - 'meetingMinutesUrgent', - 'meetingMinutesSingle', - 'meetingMinutesImport', 'singleSourceProof', 'importApplication', 'governmentPurchaseIntent', - 'servicePublicSelectSchool', - 'serviceInviteSelectSchool', - 'servicePublicSelectSchoolAuto', 'otherMaterials', ]; @@ -2566,18 +1969,16 @@ const handleTempStore = async () => { await tempStore(submitData); useMessage().success('暂存成功'); - // 流程嵌入时不关闭、不跳转 - if (!isFlowEmbed.value) { - if (window.parent !== window) { - window.parent.postMessage( - { - type: 'purchasingrequisition:submitSuccess', - }, - '*' - ); - } else { - router.push('/purchase/purchasingrequisition'); - } + // 暂存后跳转 + if (window.parent !== window) { + window.parent.postMessage( + { + type: 'purchasingrequisition:submitSuccess', + }, + '*' + ); + } else { + router.push('/purchase/purchasingrequisition'); } } catch (err: any) { if (!err?.msg) { @@ -2613,17 +2014,6 @@ watch( { deep: true } ); -// 流程嵌入:切换工单时重新加载该 tab 对应的申请单 -watch( - () => props.currJob?.id, - async (newVal, oldVal) => { - if (!isFlowEmbed.value || !props.currJob?.orderId) return; - if (newVal !== oldVal) { - await loadDetail(props.currJob.orderId); - } - } -); - // 初始化 onMounted(async () => { // 检测是否在 iframe 中,如果是,则修改相关元素的 overflow 样式以支持滚动 @@ -2666,19 +2056,12 @@ onMounted(async () => { getBusinessLeaderListData(), ]); - // 编辑/查看:从 URL 或流程 currJob.orderId 加载详情 + // 编辑/查看:从 URL 加载详情 const queryId = effectiveQueryId.value; if (queryId) { await loadDetail(queryId); } - // 流程嵌入:注册 tab 显隐与保存回调,供审批页调用 - if (isFlowEmbed.value && props.currJob && props.currElTab?.id) { - orderVue.currElTabIsExist(props.currJob, props.currElTab.id); - await orderVue.currElTabIsView(flowMethods, props.currJob, props.currElTab.id, flowSubmitForm); - applyPurchaseApplyFormPerm(); - } - // 新增模式下设置默认值(只有在没有 id 的情况下才设置) if (!dataForm.id) { // 填报日期默认为当天 diff --git a/src/views/purchase/purchasingrequisition/form.vue b/src/views/purchase/purchasingrequisition/form.vue index c896d96..55d1f43 100644 --- a/src/views/purchase/purchasingrequisition/form.vue +++ b/src/views/purchase/purchasingrequisition/form.vue @@ -3,7 +3,6 @@ v-model="visible" :title="dialogTitle" width="90%" - :style="{ maxWidth: '1600px' }" :close-on-click-modal="false" destroy-on-close class="form-iframe-dialog"