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