diff --git a/src/assets/file/江苏省常州技师学院商务洽谈纪要.docx b/src/assets/file/江苏省常州技师学院商务洽谈纪要.docx new file mode 100644 index 0000000..4520def Binary files /dev/null and b/src/assets/file/江苏省常州技师学院商务洽谈纪要.docx differ diff --git a/src/assets/file/部门自行采购市场采购纪要.docx b/src/assets/file/部门自行采购市场采购纪要.docx new file mode 100644 index 0000000..f8ed17e Binary files /dev/null and b/src/assets/file/部门自行采购市场采购纪要.docx differ diff --git a/src/assets/file/部门采购询价模版.docx b/src/assets/file/部门采购询价模版.docx new file mode 100644 index 0000000..7765bb3 Binary files /dev/null and b/src/assets/file/部门采购询价模版.docx differ diff --git a/src/components/Upload/index.vue b/src/components/Upload/index.vue index c57874c..d5817ff 100644 --- a/src/components/Upload/index.vue +++ b/src/components/Upload/index.vue @@ -22,45 +22,74 @@ - - - -
- {{ $t('excel.operationNotice') }} - {{ $t('excel.clickUpload') }} -
- -
+ + @@ -171,12 +171,13 @@ v-model="dataForm.businessNegotiationTable" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.businessNegotiationTable }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -192,12 +193,13 @@ v-model="dataForm.marketPurchaseMinutes" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.marketPurchaseMinutes }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -205,11 +207,12 @@ v-model="dataForm.onlineMallMaterials" :limit="1" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.onlineMallMaterials }" upload-file-url="/purchase/purchasingfiles/upload" /> - @@ -300,6 +305,7 @@ v-model="dataForm.purchaseRequirementTemplate" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.purchaseRequirementTemplate }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -342,6 +348,7 @@ v-model="dataForm.serviceInviteSelect" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -363,6 +370,7 @@ v-model="dataForm.servicePublicSelectAuto" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.servicePublicSelectAuto }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -373,6 +381,7 @@ v-model="dataForm.otherMaterials" :limit="5" :file-type="['zip']" + :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" />
支持上传zip格式的压缩包文件
@@ -461,6 +470,7 @@ v-model="dataForm.feasibilityReport" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.feasibilityReport }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -468,6 +478,7 @@ v-model="dataForm.meetingMinutes" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.meetingMinutes }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -479,12 +490,13 @@ v-model="dataForm.meetingMinutesUrgent" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.meetingMinutesUrgent }" upload-file-url="/purchase/purchasingfiles/upload" /> - @@ -625,6 +643,7 @@ v-model="dataForm.servicePublicSelectSchool" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.servicePublicSelectSchool }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -644,6 +663,7 @@ v-model="dataForm.purchaseRequirement" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.purchaseRequirement }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -658,6 +678,7 @@ v-model="dataForm.governmentPurchaseIntent" :limit="5" :file-type="['doc', 'docx', 'pdf']" + :data="{ fileType: FILE_TYPE_MAP.governmentPurchaseIntent }" upload-file-url="/purchase/purchasingfiles/upload" /> @@ -667,6 +688,7 @@ v-model="dataForm.otherMaterials" :limit="5" :file-type="['zip']" + :data="{ fileType: FILE_TYPE_MAP.otherMaterials }" upload-file-url="/purchase/purchasingfiles/upload" />
支持上传zip格式的压缩包文件
@@ -808,6 +830,61 @@ const PURCHASE_TYPE_IDS = { ENTRUST_CENTER: '981bf052a0b30b028a4a89ae490c9b1d' // 委托采购中心 }; +// 文件类型映射(对应数据库 file_type 字段) +// 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 80:进口产品申请表 90:进口产品专家论证表 100:政府采购意向表 110:履约验收单 +const FILE_TYPE_MAP: Record = { + businessNegotiationTable: '10', // 商务洽谈纪要 + marketPurchaseMinutes: '20', // 市场采购纪要 + onlineMallMaterials: '30', // 网上商城采购相关材料 + feasibilityReport: '40', // 可行性论证报告 + meetingMinutes: '50', // 会议记录 + meetingMinutesUrgent: '50', // 会议记录 + meetingMinutesSingle: '50', // 会议记录 + meetingMinutesImport: '50', // 会议记录 + otherMaterials: '60', // 其他材料 + singleSourceProof: '70', // 单一来源专家论证表 + importApplication: '80', // 进口产品申请表 + governmentPurchaseIntent: '100', // 政府采购意向表 + // 需求文件相关(暂时使用默认值,可根据实际需求调整) + serviceDirectSelect: '30', // 服务商城项目需求模板(直选)- 归类到网上商城采购相关材料 + serviceInviteSelect: '30', // 服务商城项目需求模板(邀请比选) + servicePublicSelect: '30', // 服务商城项目需求模板(公开比选) + servicePublicSelectAuto: '30', // 服务商城项目需求模板(公开比选-自动) + purchaseRequirementTemplate: '30', // 采购需求填报模板 + purchaseRequirement: '30', // 采购需求填报模板 + serviceInviteSelectSchool: '30', // 服务商城项目需求模板(邀请比选-学校) + servicePublicSelectSchoolAuto: '30', // 服务商城项目需求模板(公开比选-学校-自动) + servicePublicSelectSchool: '30', // 服务商城项目需求模板(公开比选-学校) +}; + +// 辅助函数:判断当前采购方式是否为指定类型(通过 id 或 value 匹配) +const isPurchaseType = (purchaseTypeId: string) => { + if (!dataForm.purchaseType) return false; + // 在字典中查找匹配的项 + const item = purchaseTypeDeptList.value.find(item => + item.id === purchaseTypeId || item.value === purchaseTypeId + ); + if (item) { + return dataForm.purchaseType === item.value; + } + // 如果字典中找不到,直接比较 value(兼容性处理) + return dataForm.purchaseType === purchaseTypeId; +}; + +// 辅助函数:判断特殊情况是否为指定类型(通过 id 或 value 匹配) +const isSpecialType = (specialIdOrValue: string) => { + if (!dataForm.isSpecial) return false; + // 在字典中查找匹配的项 + const item = isSpecialList.value.find(item => + item.id === specialIdOrValue || item.value === specialIdOrValue + ); + if (item) { + return dataForm.isSpecial === item.value; + } + // 如果字典中找不到,直接比较 value(兼容性处理) + return dataForm.isSpecial === specialIdOrValue; +}; + // 判断是否为部门自行采购 // 条件:特殊情况=否 且 集采=否 且 预算金额<5万 → 部门自行采购 // 其他情况 → 学校统一采购 @@ -978,7 +1055,7 @@ const isAutoSelectPurchaseTypeUnion = computed(() => { watch([() => dataForm.categoryCode, () => dataForm.budget], () => { // 部门自行采购:自动设置网上商城 if (isAutoSelectPurchaseType.value && isDeptPurchase.value) { - // 查找网上商城选项(通过 id 或 label 匹配) + // 查找网上商城选项(通过 id、value 或 label 匹配) const onlineMallOption = purchaseTypeDeptList.value.find(item => { const label = item.label || item.dictLabel || item.name || ''; return item.id === PURCHASE_TYPE_IDS.ONLINE_MALL || @@ -1360,6 +1437,7 @@ const handleSchoolLeaderChange = (value: string) => { }; // 处理文件ID字符串转数组 +// 从上传返回的URL中提取文件ID,拼成数组格式:["id1", "id2"] const getFileIdsArray = (fileIds: string | string[]): string[] => { if (!fileIds) return []; if (Array.isArray(fileIds)) return fileIds; @@ -1369,19 +1447,41 @@ const getFileIdsArray = (fileIds: string | string[]): string[] => { urls.forEach(url => { try { + // 尝试解析为URL const urlObj = new URL(url, window.location.origin); - const id = urlObj.searchParams.get('id') || urlObj.searchParams.get('fileName'); + // 优先从URL参数中获取id + let id = urlObj.searchParams.get('id'); + + // 如果没有id参数,尝试从路径中提取(可能是直接的文件ID) + if (!id) { + const pathParts = urlObj.pathname.split('/').filter(p => p); + // 检查最后一个路径段是否是32位十六进制字符串(文件ID格式) + const lastPart = pathParts[pathParts.length - 1]; + if (lastPart && /^[a-f0-9]{32}$/i.test(lastPart)) { + id = lastPart; + } else if (lastPart) { + id = lastPart; + } + } + if (id) { ids.push(id); } else { - const pathParts = urlObj.pathname.split('/'); - const lastPart = pathParts[pathParts.length - 1]; - if (lastPart) { - ids.push(lastPart); + // 如果URL解析失败,检查原始字符串是否是ID格式 + if (/^[a-f0-9]{32}$/i.test(url.trim())) { + ids.push(url.trim()); + } else { + ids.push(url); } } } catch { - ids.push(url); + // URL解析失败,检查是否是直接的ID格式(32位十六进制) + if (/^[a-f0-9]{32}$/i.test(url.trim())) { + ids.push(url.trim()); + } else { + // 否则直接使用原始字符串 + ids.push(url); + } } }); @@ -1411,7 +1511,8 @@ const handleSubmit = async () => { 'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement', 'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent', 'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication', - 'governmentPurchaseIntent', 'servicePublicSelectSchool', 'otherMaterials' + 'governmentPurchaseIntent', 'servicePublicSelectSchool', 'serviceInviteSelectSchool', + 'servicePublicSelectSchoolAuto', 'otherMaterials' ]; fileFields.forEach(field => { @@ -1460,7 +1561,8 @@ const handleTempStore = async () => { 'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement', 'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent', 'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication', - 'governmentPurchaseIntent', 'servicePublicSelectSchool', 'otherMaterials' + 'governmentPurchaseIntent', 'servicePublicSelectSchool', 'serviceInviteSelectSchool', + 'servicePublicSelectSchoolAuto', 'otherMaterials' ]; fileFields.forEach(field => {