|
|
|
|
@ -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)
|
|
|
|
|
}
|
|
|
|
|
|