From 3100dcbd38f99c9678d4be10d398287a2f5eeb38 Mon Sep 17 00:00:00 2001 From: hwj Date: Fri, 30 Jan 2026 18:12:30 +0800 Subject: [PATCH] =?UTF-8?q?style=EF=BC=9A=E4=BF=AE=E6=94=B9upload=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E8=BF=94=E5=9B=9E=E5=80=BC=E6=A0=BC=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?fileName=E5=92=8CfileUrl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/UploadFile/src/UploadFile.vue | 115 ++++++++++++++++--- 1 file changed, 102 insertions(+), 13 deletions(-) diff --git a/src/components/UploadFile/src/UploadFile.vue b/src/components/UploadFile/src/UploadFile.vue index a225953f..39062935 100644 --- a/src/components/UploadFile/src/UploadFile.vue +++ b/src/components/UploadFile/src/UploadFile.vue @@ -202,6 +202,91 @@ const getDisplayNameByUrl = (url: string): string => { return idx !== -1 ? url.substring(idx + 1) : url } +const parseModelValueToInfos = (val: string | string[]): { fileName: string; fileUrl: string }[] => { + const result: { fileName: string; fileUrl: string }[] = [] + + const addFromUrl = (url: string) => { + const trimmed = url.trim() + if (!trimmed) return + const idx = trimmed.lastIndexOf('/') + const name = idx !== -1 ? trimmed.substring(idx + 1) : trimmed + result.push({ fileName: name, fileUrl: trimmed }) + } + + const handleString = (text: string) => { + const trimmed = text.trim() + if (!trimmed) return + if (trimmed.startsWith('{') || trimmed.startsWith('[')) { + try { + const parsed = JSON.parse(trimmed) + if (Array.isArray(parsed)) { + parsed.forEach((item) => { + if (item && typeof item === 'object' && item.fileUrl) { + const u = String(item.fileUrl) + const n = item.fileName ? String(item.fileName) : undefined + const idx = u.lastIndexOf('/') + const name = n || (idx !== -1 ? u.substring(idx + 1) : u) + result.push({ fileName: name, fileUrl: u }) + } + }) + return + } + if (parsed && typeof parsed === 'object' && parsed.fileUrl) { + const u = String(parsed.fileUrl) + const n = parsed.fileName ? String(parsed.fileName) : undefined + const idx = u.lastIndexOf('/') + const name = n || (idx !== -1 ? u.substring(idx + 1) : u) + result.push({ fileName: name, fileUrl: u }) + return + } + } catch {} + } + trimmed + .split(',') + .map((s) => s.trim()) + .filter((s) => !!s) + .forEach((u) => addFromUrl(u)) + } + + const handleAny = (v: any) => { + if (!v) return + if (typeof v === 'string') { + handleString(v) + return + } + if (Array.isArray(v)) { + v.forEach((item) => handleAny(item)) + return + } + if (typeof v === 'object' && v.fileUrl) { + const u = String(v.fileUrl) + const n = v.fileName ? String(v.fileName) : undefined + const idx = u.lastIndexOf('/') + const name = n || (idx !== -1 ? u.substring(idx + 1) : u) + result.push({ fileName: name, fileUrl: u }) + } + } + + handleAny(val as any) + return result +} + +const buildInfosFromFileList = (): { fileName: string; fileUrl: string }[] => { + const infos: { fileName: string; fileUrl: string }[] = [] + fileList.value.forEach((file) => { + if (!file.url) return + const url = file.url as string + const cached = nameMap.value[url] + let name = cached || file.name || '' + if (!name) { + const idx = url.lastIndexOf('/') + name = idx !== -1 ? url.substring(idx + 1) : url + } + infos.push({ fileName: String(name), fileUrl: url }) + }) + return infos +} + // 监听模型绑定值变动 watch( () => props.modelValue, @@ -211,27 +296,31 @@ watch( return } - fileList.value = [] // 保障数据为空 - // 情况1:字符串 - if (isString(val)) { - const urls = val.split(',').filter((u) => !!u) - fileList.value.push(...urls.map((url) => ({ name: getDisplayNameByUrl(url), url }))) - return - } - // 情况2:数组 + fileList.value = [] + nameMap.value = {} + const infos = parseModelValueToInfos(val) + if (!infos.length) return fileList.value.push( - ...(val as string[]).map((url) => ({ name: getDisplayNameByUrl(url), url })) + ...infos.map((item) => { + nameMap.value[item.fileUrl] = item.fileName + return { name: item.fileName, url: item.fileUrl } + }) ) }, { immediate: true, deep: true } ) // 发送文件链接列表更新 const emitUpdateModelValue = () => { - // 情况1:数组结果 - let result: string | string[] = fileList.value.map((file) => file.url!) - // 情况2:逗号分隔的字符串 + const infos = buildInfosFromFileList() + let result: string | string[] if (props.limit === 1 || isString(props.modelValue)) { - result = result.join(',') + if (!infos.length) { + result = '' + } else { + result = JSON.stringify(infos[0]) + } + } else { + result = JSON.stringify(infos) } emit('update:modelValue', result) }