import type { UploadedFile } from '@/types/worker-platform' /** * 归一化图片身份标识,用于跨来源去重(files 与 imageUrls 可能同时包含同一张图)。 * * 本项目的图片地址有两种形态: * - 对象存储签名链接:`/api/v1/files/object?key=&expires=...&signature=...` * (对象 key 在 query 里,路径对所有文件相同,不能只取路径) * - 普通外链:`https://cdn.example.com/a.png` * * 优先级:objectKey 字段 > URL 中的 key 参数 > 去掉临时签名参数后的完整地址。 */ export function getImageIdentity(file: { objectKey?: string url?: string mediumUrl?: string thumbnailUrl?: string }): string { const objectKey = String(file?.objectKey || '').trim() if (objectKey) return objectKey const url = String(file?.url || file?.mediumUrl || file?.thumbnailUrl || '').trim() return getImageIdentityFromUrl(url) } export function getImageIdentityFromUrl(value: string): string { const url = String(value || '').trim() if (!url) return '' const keyMatch = url.match(/[?&]key=([^&#]+)/) if (keyMatch?.[1]) { try { return decodeURIComponent(keyMatch[1]) } catch { return keyMatch[1] } } // 普通地址:仅去掉临时签名参数(expires/signature),保留路径与其它参数 return url .split('#', 1)[0] .replace(/[?&](expires|signature)=[^&#]*/gi, '') .replace(/[?&]+$/, '') } /** 供 UploadedFile 数组去重:按图片身份去重,保留第一张 */ export function uniqueUploadedFiles(files: UploadedFile[]): UploadedFile[] { const seen = new Set() return files.filter((file) => { const identity = getImageIdentity(file) if (!identity || seen.has(identity)) return false seen.add(identity) return true }) }