feat(admin): synchronize fleet photos and multi-image loading documents

This commit is contained in:
2026-10-26 17:12:38 +08:00
parent e399f3f76f
commit acb90007de
29 changed files with 556 additions and 95 deletions
@@ -0,0 +1,15 @@
import { expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import { getResourcePhoto, uploadResourcePhoto, downloadResourcePhoto } from './resourcePhotos'
vi.mock('@/shared/api/http', async original => ({ ...(await original<typeof import('@/shared/api/http')>()), http: { get: vi.fn(), post: vi.fn() } }))
it('preserves long identifiers and versions and submits the correct resource scope', async () => {
const id = '9223372036854775701', fileId = '9223372036854775702', version = '9007199254740993'
const wire = { code: '200', data: { recordVersion: version, photo: { fileId, fileName: 'photo.png', contentType: 'image/png', sizeBytes: '3' } } }
vi.mocked(http.get).mockResolvedValue(wire); vi.mocked(http.post).mockResolvedValue(wire)
expect(await getResourcePhoto('VEHICLE', id)).toMatchObject({ recordVersion: version, photo: { fileId, sizeBytes: 3 } })
await uploadResourcePhoto('VEHICLE', id, version, new File(['png'], 'photo.png', { type: 'image/png' }))
expect(http.post).toHaveBeenCalledWith(`/platform/v1/last-leg/fleet/resource-photos/VEHICLE/${id}`, expect.any(FormData))
expect((vi.mocked(http.post).mock.calls[0]![1] as FormData).get('recordVersion')).toBe(version)
vi.mocked(http.get).mockResolvedValue(new Blob(['{"code":"A0403"}'], { type: 'application/json' }))
await expect(downloadResourcePhoto('VEHICLE', id, fileId)).rejects.toThrow('读取失败')
})
@@ -0,0 +1,22 @@
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
export type ResourcePhotoKind = 'VEHICLE' | 'DRIVER'
export interface ResourcePhoto { fileId: string; fileName: string; contentType: string; sizeBytes: number }
export interface ResourcePhotoDetail { recordVersion: string; photo: ResourcePhoto | null }
const path = (kind: ResourcePhotoKind, id: string) => `/platform/v1/last-leg/fleet/resource-photos/${kind}/${encodeURIComponent(id)}`
type Wire = { recordVersion: string | number; photo: (Omit<ResourcePhoto, 'sizeBytes'> & { sizeBytes: number | string }) | null }
function normalize(value: Wire): ResourcePhotoDetail {
return { recordVersion: String(value.recordVersion), photo: value.photo ? { ...value.photo, sizeBytes: Number(value.photo.sizeBytes) } : null }
}
export async function getResourcePhoto(kind: ResourcePhotoKind, id: string) {
return normalize(unwrapApiResponse(await http.get<ApiEnvelope<Wire>, ApiEnvelope<Wire>>(path(kind, id))))
}
export async function uploadResourcePhoto(kind: ResourcePhotoKind, id: string, version: string, file: File) {
const body = new FormData(); body.append('recordVersion', version); body.append('file', file)
return normalize(unwrapApiResponse(await http.post<ApiEnvelope<Wire>, ApiEnvelope<Wire>>(path(kind, id), body)))
}
export async function downloadResourcePhoto(kind: ResourcePhotoKind, id: string, fileId: string) {
const blob = await http.get<Blob, Blob>(`${path(kind, id)}/${encodeURIComponent(fileId)}/content`, { responseType: 'blob' })
if (!(blob instanceof Blob) || !['image/jpeg', 'image/png'].includes(blob.type) || !blob.size || blob.size > 10 * 1024 * 1024) throw new Error('档案照片读取失败,请重新核对')
return blob
}