65 lines
2.1 KiB
Vue
65 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
import { onBeforeUnmount, ref, watch } from 'vue'
|
|
import { ImageOff } from '@lucide/vue'
|
|
import { downloadWeightThumbnail } from '../api/weightOcr'
|
|
|
|
const props = defineProps<{
|
|
customerId: string
|
|
inboundId: string
|
|
fileId: string
|
|
alt: string
|
|
}>()
|
|
|
|
defineEmits<{ open: [] }>()
|
|
|
|
const imageUrl = ref('')
|
|
const loading = ref(false)
|
|
const failed = ref(false)
|
|
let requestId = 0
|
|
|
|
function releaseImage() {
|
|
if (imageUrl.value) URL.revokeObjectURL(imageUrl.value)
|
|
imageUrl.value = ''
|
|
}
|
|
|
|
async function load() {
|
|
const currentRequest = ++requestId
|
|
releaseImage()
|
|
failed.value = false
|
|
loading.value = true
|
|
try {
|
|
const blob = await downloadWeightThumbnail(props.customerId, props.inboundId, props.fileId)
|
|
if (currentRequest !== requestId) return
|
|
imageUrl.value = URL.createObjectURL(blob)
|
|
} catch {
|
|
if (currentRequest === requestId) failed.value = true
|
|
} finally {
|
|
if (currentRequest === requestId) loading.value = false
|
|
}
|
|
}
|
|
|
|
watch(() => [props.customerId, props.inboundId, props.fileId], load, { immediate: true })
|
|
onBeforeUnmount(() => {
|
|
requestId += 1
|
|
releaseImage()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<button class="weight-thumb" type="button" :aria-label="`查看${alt}`" @click="$emit('open')">
|
|
<img v-if="imageUrl" :src="imageUrl" :alt="alt" loading="lazy" />
|
|
<span v-else class="weight-thumb__state" :class="{ 'is-loading': loading }">
|
|
<ImageOff v-if="failed" :size="22" aria-hidden="true" />
|
|
<span>{{ failed ? '图片加载失败' : '图片加载中' }}</span>
|
|
</span>
|
|
</button>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.weight-thumb { display: block; width: 100%; aspect-ratio: 4 / 3; overflow: hidden; padding: 0; border: 0; border-radius: 6px 6px 0 0; background: #f2f4f7; cursor: zoom-in; }
|
|
.weight-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
.weight-thumb__state { display: grid; width: 100%; height: 100%; place-items: center; align-content: center; gap: 7px; color: #667085; font-size: 12px; }
|
|
.weight-thumb__state.is-loading { color: #98a2b3; }
|
|
.weight-thumb:focus-visible { outline: 2px solid var(--cc-primary); outline-offset: 2px; }
|
|
</style>
|