diff --git a/apps/frontend/src/pages/admin/panels/AfterSalesPanel.tsx b/apps/frontend/src/pages/admin/panels/AfterSalesPanel.tsx index 13486555..492fb3a5 100644 --- a/apps/frontend/src/pages/admin/panels/AfterSalesPanel.tsx +++ b/apps/frontend/src/pages/admin/panels/AfterSalesPanel.tsx @@ -28,6 +28,7 @@ import { import type { UploadedFile, WorkerAfterSalesCase, WorkOrder } from '@/types/worker-platform' import { ADMIN_DEFAULT_PAGE_SIZE, buildAdminTablePagination } from '@/utils/admin-pagination' import { formatAdminDateTime } from '@/utils/admin-time' +import { uniqueUploadedFiles } from '@/utils/image-identity' import { asRecord, formatMoney } from './shared' type AfterSalesCreateFormValues = { @@ -447,24 +448,28 @@ function getAfterSalesSnapshotFiles(item: WorkerAfterSalesCase): UploadedFile[] const acceptance = asRecord(snapshot.acceptance) const files = Array.isArray(acceptance.files) ? acceptance.files : [] const imageUrls = Array.isArray(acceptance.imageUrls) ? acceptance.imageUrls : [] - return [ - ...files.map((value) => asRecord(value)), - ...imageUrls.map((url) => asRecord({ url: String(url || '') })), - ] - .map((file) => { - const url = String(file.url || '').trim() - if (!url) return null - return { - objectKey: String(file.objectKey || file.object_key || ''), - url, - thumbnailUrl: String(file.thumbnailUrl || file.thumbnail_url || url), - mediumUrl: String(file.mediumUrl || file.medium_url || url), - filename: String(file.filename || '验收图片'), - contentType: String(file.contentType || ''), - size: Number(file.size || 0), - } satisfies UploadedFile - }) - .filter((file): file is UploadedFile => file !== null) + // 验收资料里同一张图会同时存在于 files 与 imageUrls(历史冗余表示), + // 必须按图片身份去重,否则固化验收图会把同一张图重复渲染多次。 + return uniqueUploadedFiles( + [ + ...files.map((value) => asRecord(value)), + ...imageUrls.map((url) => asRecord({ url: String(url || '') })), + ] + .map((file) => { + const url = String(file.url || '').trim() + if (!url) return null + return { + objectKey: String(file.objectKey || file.object_key || ''), + url, + thumbnailUrl: String(file.thumbnailUrl || file.thumbnail_url || url), + mediumUrl: String(file.mediumUrl || file.medium_url || url), + filename: String(file.filename || '验收图片'), + contentType: String(file.contentType || ''), + size: Number(file.size || 0), + } satisfies UploadedFile + }) + .filter((file): file is UploadedFile => file !== null), + ) } export default AfterSalesPanel