refactor(srm): 优化投标模块获奖信息获取和文件上传组件
- 替换 getAward 接口调用为 getAwardByProject 以按项目获取获奖信息
- 移除文件上传组件中冗余的注释和变量声明
- 重构表单初始化逻辑,统一设置字段值的方式
- 优化表单API中文件上传字段的值格式化处理
- 简化文件上传组件中的校验和上传流程
| | |
| | | return requestClient.get<SrmTenderApi.BidAwardVO>(`/srm/bid-award/get?id=${id}`); |
| | | } |
| | | |
| | | export function getAwardByProject(tenderProjectId: number) { |
| | | return requestClient.get<SrmTenderApi.BidAwardVO>(`/srm/bid-award/get-by-project?tenderProjectId=${tenderProjectId}`); |
| | | } |
| | | |
| | | export function approveAward(id: number) { |
| | | return requestClient.put(`/srm/bid-award/approve?id=${id}`); |
| | | } |
| | |
| | | maxSizeRef: maxSize, |
| | | }); |
| | | |
| | | /** 计算当前绑定的值,优先使用 modelValue */ |
| | | const currentValue = computed(() => { |
| | | return props.modelValue === undefined ? props.value : props.modelValue; |
| | | }); |
| | | |
| | | /** 判断是否使用 modelValue */ |
| | | const isUsingModelValue = computed(() => { |
| | | return props.modelValue !== undefined; |
| | | }); |
| | | |
| | | const fileList = ref<UploadProps['fileList']>([]); |
| | | const isLtMsg = ref<boolean>(true); // 文件大小错误提示 |
| | | const isActMsg = ref<boolean>(true); // 文件类型错误提示 |
| | | const isFirstRender = ref<boolean>(true); // 是否第一次渲染 |
| | | const uploadNumber = ref<number>(0); // 上传文件计数器 |
| | | const uploadList = ref<any[]>([]); // 临时上传列表 |
| | | const isLtMsg = ref<boolean>(true); |
| | | const isActMsg = ref<boolean>(true); |
| | | const isFirstRender = ref<boolean>(true); |
| | | const uploadNumber = ref<number>(0); |
| | | const uploadList = ref<any[]>([]); |
| | | |
| | | watch( |
| | | currentValue, |
| | |
| | | function handleUploadError(error: any) { |
| | | console.error('上传错误:', error); |
| | | message.error($t('ui.upload.uploadError')); |
| | | // 上传失败时减少计数器 |
| | | uploadNumber.value = Math.max(0, uploadNumber.value - 1); |
| | | } |
| | | |
| | | /** |
| | | * 上传前校验 |
| | | * @param file 待上传的文件 |
| | | * @returns 是否允许上传 |
| | | */ |
| | | async function beforeUpload(file: File) { |
| | | // 检查文件数量限制 |
| | | if (fileList.value!.length >= props.maxNumber) { |
| | | message.error($t('ui.upload.maxNumber', [props.maxNumber])); |
| | | return Upload.LIST_IGNORE; |
| | |
| | | if (!isAct) { |
| | | message.error($t('ui.upload.acceptUpload', [accept])); |
| | | isActMsg.value = false; |
| | | // 防止弹出多个错误提示 |
| | | setTimeout(() => (isActMsg.value = true), 1000); |
| | | return Upload.LIST_IGNORE; |
| | | } |
| | |
| | | if (isLt) { |
| | | message.error($t('ui.upload.maxSizeMultiple', [maxSize])); |
| | | isLtMsg.value = false; |
| | | // 防止弹出多个错误提示 |
| | | setTimeout(() => (isLtMsg.value = true), 1000); |
| | | return Upload.LIST_IGNORE; |
| | | } |
| | | |
| | | // 只有在验证通过后才增加计数器 |
| | | uploadNumber.value++; |
| | | if (props.returnText) { |
| | | const fileContent = await file.text(); |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** 自定义上传请求 */ |
| | | async function customRequest(info: UploadRequestOption) { |
| | | let { api } = props; |
| | | if (!api || !isFunction(api)) { |
| | | api = useUpload(props.directory).httpRequest; |
| | | } |
| | | try { |
| | | // 上传文件 |
| | | const progressEvent: AxiosProgressEvent = (e) => { |
| | | const percent = Math.trunc((e.loaded / e.total!) * 100); |
| | | info.onProgress!({ percent }); |
| | | }; |
| | | const res = await api?.(info.file as File, progressEvent); |
| | | |
| | | // 处理上传成功后的逻辑 |
| | | handleUploadSuccess(res, info.file as File); |
| | | |
| | | info.onSuccess!(res); |
| | | message.success($t('ui.upload.uploadSuccess')); |
| | | } catch (error: any) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理上传成功 |
| | | * @param res 上传响应结果 |
| | | * @param file 上传的文件 |
| | | */ |
| | | function handleUploadSuccess(res: any, file: File) { |
| | | // 删除临时文件 |
| | | const index = fileList.value?.findIndex((item) => item.name === file.name); |
| | | if (index !== -1) { |
| | | fileList.value?.splice(index!, 1); |
| | | } |
| | | |
| | | // 添加到临时上传列表 |
| | | const fileUrl = res?.url || res?.data || res; |
| | | uploadList.value.push({ |
| | | name: res?.name || file.name, |
| | |
| | | uid: file.name + Date.now(), |
| | | }); |
| | | |
| | | // 检查是否所有文件都上传完成 |
| | | if (uploadList.value.length >= uploadNumber.value) { |
| | | fileList.value?.push(...uploadList.value); |
| | | uploadList.value = []; |
| | | uploadNumber.value = 0; |
| | | |
| | | // 更新值 |
| | | const value = getValue(); |
| | | isInnerOperate.value = true; |
| | | emit('update:value', value); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取当前文件列表的值 |
| | | * @returns 文件 URL 列表或字符串 |
| | | */ |
| | | function getValue() { |
| | | const list = (fileList.value || []) |
| | | .filter((item) => item?.status === UploadResultStatus.DONE) |
| | |
| | | return props.valuePrefix ? `${props.valuePrefix}${val}` : val; |
| | | }); |
| | | |
| | | // 单个文件的情况,根据输入参数类型决定返回格式 |
| | | if (props.maxNumber === 1) { |
| | | const singleValue = list.length > 0 ? list[0] : ''; |
| | | // 如果原始值是字符串或 modelValue 是字符串,返回字符串 |
| | | if ( |
| | | isString(props.value) || |
| | | (isUsingModelValue.value && isString(props.modelValue)) |
| | |
| | | return singleValue; |
| | | } |
| | | |
| | | // 多文件情况,根据输入参数类型决定返回格式 |
| | | if (isUsingModelValue.value) { |
| | | return Array.isArray(props.modelValue) ? list : list.join(','); |
| | | } |
| | |
| | | </style> |
| | | |
| | | <style> |
| | | /* 文件上传列表显示手型光标样式失效。不知道为啥. 先这里加上 */ |
| | | .ant-upload-list-text .ant-upload-list-item { |
| | | cursor: pointer; |
| | | } |
| | |
| | | const values = form.values |
| | | ? this.handleRangeTimeValue(cloneDeep(toRaw(form.values))) |
| | | : {}; |
| | | return this.handleValueFormat(values) as T; |
| | | const result = this.handleValueFormat(values); |
| | | // 自动提取 FileUpload/Upload 字段中的文件 ID,避免提交时携带完整文件对象 |
| | | const currentSchema = this.state?.schema ?? []; |
| | | for (const schema of currentSchema) { |
| | | // 兼容字符串类型和已解析的 Vue Component 对象 |
| | | const compName: string = |
| | | typeof schema.component === 'string' |
| | | ? schema.component |
| | | : (schema.component as any)?.name ?? ''; |
| | | if (compName !== 'FileUpload' && compName !== 'Upload') { |
| | | continue; |
| | | } |
| | | if (schema.valueFormat) continue; |
| | | const fieldName = schema.fieldName; |
| | | const rawValue = result[fieldName]; |
| | | if ( |
| | | rawValue == null || |
| | | !Array.isArray(rawValue) || |
| | | rawValue.length === 0 |
| | | ) { |
| | | continue; |
| | | } |
| | | if ( |
| | | typeof rawValue[0] !== 'object' || |
| | | !('status' in rawValue[0]) |
| | | ) { |
| | | continue; |
| | | } |
| | | const props = (schema.componentProps || {}) as Record<string, any>; |
| | | const valueKey = props.valueKey || 'url'; |
| | | const maxNumber = props.maxNumber ?? 1; |
| | | const resultField = props.resultField; |
| | | const valuePrefix = props.valuePrefix || ''; |
| | | const list = rawValue |
| | | .filter((item: any) => item?.status === 'done') |
| | | .map((item: any) => { |
| | | if (resultField && item?.response) return item.response; |
| | | const v = |
| | | item?.response?.[valueKey] ?? |
| | | item?.[valueKey] ?? |
| | | item?.url ?? |
| | | item?.response?.url ?? |
| | | item?.response; |
| | | return valuePrefix ? `${valuePrefix}${v}` : v; |
| | | }); |
| | | result[fieldName] = maxNumber === 1 ? (list[0] ?? '') : list; |
| | | } |
| | | return result as T; |
| | | } |
| | | |
| | | async isFieldValid(fieldName: string) { |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getFinancePayment(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getFinanceReceipt(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseIn(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseOrder(data.id); |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseRequest(data.id); |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseReturn(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleOrder(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleOut(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleReturn(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getStockCheck(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getStockIn(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getStockMove(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getStockOut(data.id); |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | getQuoteList, createQuote, updateQuote, |
| | | createBidOpen, getBidOpen, |
| | | getEvaluationList, createBidEvaluation, calculateRanking, |
| | | createAward, getAward, approveAward, generatePurchaseOrder, |
| | | createAward, getAward, getAwardByProject, approveAward, generatePurchaseOrder, |
| | | } from '#/api/srm/tender'; |
| | | import { getSupplierSimpleList } from '#/api/srm/supplier'; |
| | | import { getItemSimpleList } from '#/api/mdm/item'; |
| | |
| | | const awardForm = ref<SrmTenderApi.BidAwardVO>({ tenderProjectId: projectId, supplierId: 0, bidId: 0, awardNo: '' }); |
| | | |
| | | async function loadAward() { |
| | | try { award.value = await getAward(projectId); } catch { award.value = undefined; } |
| | | try { award.value = await getAwardByProject(projectId); } catch { award.value = undefined; } |
| | | } |
| | | async function handleCreateAward() { |
| | | await createAward(awardForm.value); |