Files
admin-web/src/modules/overseas-master-data/components/DriverLicensePreview.vue
T
2026-10-20 23:34:11 +08:00

49 lines
2.5 KiB
Vue

<script setup lang="ts">
import '@/styles/adminWorkbench.css'
import { onBeforeUnmount, ref, watch } from 'vue'
import AppDialog from '@/shared/components/AppDialog.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { downloadDriverLicense } from '../api/drivers'
const open = defineModel<boolean>({ default: false })
const props = defineProps<{ driverId: string; fileId: string; driverName: string }>()
const url = ref(''), contentType = ref(''), loading = ref(false), error = ref<ApiErrorDetails | null>(null)
let request = 0
function release() { if (url.value) URL.revokeObjectURL(url.value); url.value = '' }
async function load() {
const current = ++request
release(); error.value = null; loading.value = true
try {
const blob = await downloadDriverLicense(props.driverId, props.fileId)
if (current !== request || !open.value) return
contentType.value = blob.type; url.value = URL.createObjectURL(blob)
} catch (cause) { if (current === request) error.value = getApiErrorDetails(cause, '驾驶证读取失败') }
finally { if (current === request) loading.value = false }
}
watch([open, () => props.driverId, () => props.fileId], () => {
if (open.value && props.driverId && props.fileId) void load()
else { request++; release(); loading.value = false }
})
onBeforeUnmount(() => { request++; release() })
</script>
<template>
<AppDialog v-model="open" class="admin-density-dialog admin-workbench is-dialog" title="驾驶证附件" width="620px" :show-confirm="false" cancel-text="关闭">
<p>{{ driverName }} · 驾驶证附件</p>
<LoadErrorState v-if="error" title="驾驶证读取失败" :message="error.message" @retry="load" ><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
<div v-loading="loading" class="license-preview">
<iframe v-if="url && contentType === 'application/pdf'" :src="url" title="驾驶证 PDF 预览" />
<img v-else-if="url" :src="url" :alt="`${driverName}的驾驶证`" />
</div>
<a v-if="url" :href="url" :download="`驾驶证.${contentType === 'application/pdf' ? 'pdf' : contentType === 'image/png' ? 'png' : 'jpg'}`">下载驾驶证</a>
</AppDialog>
</template>
<style scoped>
.license-preview { min-height: 160px; }
.license-preview iframe { width: 100%; height: 560px; border: 0; }
.license-preview img { display: block; max-width: 100%; max-height: 560px; margin: auto; object-fit: contain; }
</style>