89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import { fetchAttachmentDownloadUrl } from '@/api/business'
|
|
import { attachmentFullUrl } from '@/composables/useAttachmentActions'
|
|
|
|
export { attachmentFullUrl }
|
|
|
|
export function sanitizeZipPathSegment(value: string, fallback = '未命名') {
|
|
const cleaned = String(value || '')
|
|
.replace(/[\\/:*?"<>|]/g, '_')
|
|
.replace(/\s+/g, ' ')
|
|
.trim()
|
|
return cleaned || fallback
|
|
}
|
|
|
|
export function getAttachmentExtension(file: { fileName?: string; fileUrl?: string }) {
|
|
const raw = String(file.fileName || file.fileUrl?.split('/').pop() || '')
|
|
.split('?')[0]
|
|
.trim()
|
|
const dot = raw.lastIndexOf('.')
|
|
if (dot > 0 && dot < raw.length - 1) {
|
|
return raw.slice(dot + 1).toLowerCase()
|
|
}
|
|
return ''
|
|
}
|
|
|
|
export function resolveAttachmentFileName(
|
|
file: { fileName?: string; fileUrl?: string },
|
|
index = 0
|
|
) {
|
|
const name = String(file.fileName || '').trim()
|
|
if (name) return name
|
|
const fromUrl = String(file.fileUrl || '')
|
|
.split('?')[0]
|
|
.split('/')
|
|
.pop()
|
|
if (fromUrl) return fromUrl
|
|
const ext = getAttachmentExtension(file)
|
|
return ext ? `附件${index + 1}.${ext}` : `附件${index + 1}`
|
|
}
|
|
|
|
export function ensureUniqueZipEntryName(name: string, used: Set<string>) {
|
|
if (!used.has(name)) {
|
|
used.add(name)
|
|
return name
|
|
}
|
|
const dot = name.lastIndexOf('.')
|
|
const base = dot > 0 ? name.slice(0, dot) : name
|
|
const ext = dot > 0 ? name.slice(dot) : ''
|
|
let n = 2
|
|
while (used.has(`${base}(${n})${ext}`)) n += 1
|
|
const unique = `${base}(${n})${ext}`
|
|
used.add(unique)
|
|
return unique
|
|
}
|
|
|
|
export function formatZipDateStamp(date = new Date()) {
|
|
const y = date.getFullYear()
|
|
const m = String(date.getMonth() + 1).padStart(2, '0')
|
|
const d = String(date.getDate()).padStart(2, '0')
|
|
return `${y}${m}${d}`
|
|
}
|
|
|
|
export async function fetchAttachmentBlob(
|
|
fileUrl: string,
|
|
fileName: string,
|
|
options?: { signal?: AbortSignal }
|
|
) {
|
|
const url = String(fileUrl || '').trim()
|
|
if (!url) return null
|
|
try {
|
|
const res = await fetchAttachmentDownloadUrl({ fileUrl: url, fileName })
|
|
if (res?.downloadUrl) {
|
|
const response = await fetch(res.downloadUrl, { signal: options?.signal })
|
|
if (response.ok) return await response.blob()
|
|
}
|
|
} catch (err) {
|
|
if (options?.signal?.aborted) throw err
|
|
}
|
|
const href = attachmentFullUrl(url)
|
|
if (!href) return null
|
|
try {
|
|
const response = await fetch(href, { signal: options?.signal })
|
|
if (response.ok) return await response.blob()
|
|
} catch (err) {
|
|
if (options?.signal?.aborted) throw err
|
|
return null
|
|
}
|
|
return null
|
|
}
|