优化
This commit is contained in:
@@ -9,14 +9,16 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import { ApiResponseError, getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { getDispatchEvidence, getDispatchEvidenceContent, uploadDispatchEvidence } from '../api/dispatches'
|
||||
import { downloadDriverLicense } from '@/modules/overseas-master-data'
|
||||
import { DispatchInputError, type DispatchEvidenceFile, type DispatchEvidenceKind } from '../dispatchContracts'
|
||||
const props = defineProps<{ dispatchNo: string; kind: DispatchEvidenceKind; disabled?: boolean; readonly?: boolean; photoCard?: boolean; label?: string; saveHint?: string; referenceIds?: string[] }>()
|
||||
const props = defineProps<{ dispatchNo: string; kind: DispatchEvidenceKind; disabled?: boolean; readonly?: boolean; photoCard?: boolean; label?: string; saveHint?: string; referenceIds?: string[]; masterLicense?: { driverId: string; fileId: string } | null }>()
|
||||
const ids = defineModel<string[]>({ required: true })
|
||||
const allIds = computed(() => [...new Set([...(props.referenceIds || []), ...ids.value])])
|
||||
const emit = defineEmits<{ busy: [value: boolean] }>()
|
||||
const metadata = ref<Record<string, DispatchEvidenceFile>>({}), error = ref<ApiErrorDetails | null>(null), uploading = ref(false), input = ref<HTMLInputElement | null>(null)
|
||||
const imageOpen = ref(false), imageUrl = ref(''), imageName = ref(''), previewLoading = ref(false)
|
||||
const thumbnails = ref<Record<string, string>>({})
|
||||
let masterBlob: { fileId: string; blob: Blob } | null = null
|
||||
const previewId = ref(''), imageDecoding = ref(false), imageFailure = ref('')
|
||||
const previewBusy = computed(() => previewLoading.value || imageDecoding.value)
|
||||
const label = computed(() => props.label || (props.kind === 'VEHICLE' ? '本趟车辆证据' : props.kind === 'DRIVER_PHOTO' ? '司机照片' : '本趟司机证照'))
|
||||
@@ -45,9 +47,18 @@ async function load() {
|
||||
const current = ++generation, no = props.dispatchNo, kind = props.kind, values = [...allIds.value]
|
||||
for (const url of Object.values(thumbnails.value)) { URL.revokeObjectURL(url); urls.delete(url) }
|
||||
thumbnails.value = {}
|
||||
closePreview(); metadata.value = {}; error.value = null
|
||||
closePreview(); metadata.value = {}; error.value = null; masterBlob = null
|
||||
if (!no) return
|
||||
const results = await Promise.allSettled(values.map(async id => valid(await getDispatchEvidence(no, kind, id), id)))
|
||||
const master = props.kind === 'DRIVER' ? props.masterLicense : null
|
||||
const results = await Promise.allSettled(values.map(async id => {
|
||||
// 未保存的司机主档证照按司机身份读取;本车补传仍走排车文件归属。
|
||||
if (master && master.fileId === id) {
|
||||
const blob = await downloadDriverLicense(master.driverId, id)
|
||||
if (current === generation) masterBlob = { fileId: id, blob }
|
||||
return valid({ fileId: id, fileName: '驾驶证照片', contentType: blob.type, sizeBytes: blob.size }, id)
|
||||
}
|
||||
return valid(await getDispatchEvidence(no, kind, id), id)
|
||||
}))
|
||||
if (current !== generation) return
|
||||
results.forEach(result => { if (result.status === 'fulfilled') metadata.value[result.value.fileId] = result.value; else fail(result.reason, '附件资料读取失败,请重试;原引用已保留') })
|
||||
if (props.photoCard) await Promise.all(values.map(async id => {
|
||||
@@ -78,7 +89,7 @@ async function upload(event: Event) {
|
||||
}
|
||||
function remove(id: string) { if (!props.readonly && !props.disabled && !uploading.value) ids.value = ids.value.filter(value => value !== id) }
|
||||
async function readContent(no: string, kind: DispatchEvidenceKind, id: string, file: DispatchEvidenceFile) {
|
||||
const blob = await getDispatchEvidenceContent(no, kind, id)
|
||||
const blob = kind === 'DRIVER' && masterBlob?.fileId === id ? masterBlob.blob : await getDispatchEvidenceContent(no, kind, id)
|
||||
const type = blob.type.split(';')[0]?.toLowerCase()
|
||||
if (type?.includes('json')) {
|
||||
let body: Partial<{ code: string; message: string; requestId: string; traceId: string }>
|
||||
@@ -104,7 +115,7 @@ async function preview(id: string) {
|
||||
} catch (cause) { if (current === previewGeneration) { closePreview(); fail(cause, '本车附件预览失败,原引用已保留') } }
|
||||
finally { if (current === previewGeneration) previewLoading.value = false }
|
||||
}
|
||||
watch(() => JSON.stringify([props.dispatchNo, props.kind, allIds.value]), load, { immediate: true })
|
||||
watch(() => JSON.stringify([props.dispatchNo, props.kind, allIds.value, props.masterLicense]), load, { immediate: true })
|
||||
onBeforeUnmount(() => { generation++; closePreview(); for (const url of urls) URL.revokeObjectURL(url); urls.clear(); emit('busy', false) })
|
||||
</script>
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user