53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { UploadedFile } from '@/types/worker-platform'
|
|
|
|
/**
|
|
* 归一化图片身份标识,用于跨来源去重(files 与 imageUrls 可能同时包含同一张图)。
|
|
*
|
|
* 本项目的图片地址有两种形态:
|
|
* - 对象存储签名链接:`/api/v1/files/object?key=<objectKey>&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<string>()
|
|
return files.filter((file) => {
|
|
const identity = getImageIdentity(file)
|
|
if (!identity || seen.has(identity)) return false
|
|
seen.add(identity)
|
|
return true
|
|
})
|
|
}
|