Files
client-web/src/modules/overseas-warehouse/components/TransferPickupProgressPanel.vue
T
2026-10-29 10:53:47 +08:00

39 lines
4.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { onBeforeUnmount, ref, watch } from 'vue'
import { getTransferPickupProgress, downloadTransferPickupEvidence, type PickupProgress } from '../api/transferPickups'
const props = defineProps<{ transferNo: string }>()
const progress = ref<PickupProgress | null>(null), error = ref(''), loading = ref(false)
const labels: Record<string, string> = { PENDING_REVIEW: '待审核', WAITING: '待安排取货', ASSIGNED: '已安排取货', PICKED: '已取货', ARRIVED: '已送仓' }
const time = (value: string | null) => value ? new Date(value).toLocaleString('zh-CN', { hour12: false }) : '—'
let sequence = 0
/** 业务号变化后忽略旧响应,客户之间不复用取货数据。 */
async function load() {
const current = ++sequence; progress.value = null; error.value = ''; loading.value = true
try { const value = await getTransferPickupProgress(props.transferNo); if (current === sequence) progress.value = value }
catch (cause) { if (current === sequence) error.value = cause instanceof Error ? cause.message : '取货进度加载失败' }
finally { if (current === sequence) loading.value = false }
}
/** 凭证读取必须经过原单鉴权。 */
async function download(file: { fileId: string; fileName: string }) {
try { const blob = await downloadTransferPickupEvidence(props.transferNo, file.fileId); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = file.fileName; link.click(); setTimeout(() => URL.revokeObjectURL(url), 1000) }
catch (cause) { error.value = cause instanceof Error ? cause.message : '取货凭证下载失败' }
}
watch(() => props.transferNo, load, { immediate: true }); onBeforeUnmount(() => { sequence++ })
</script>
<template>
<section v-if="loading || progress || error" v-loading="loading" class="pickup-progress" aria-label="取货安排">
<div class="pickup-heading"><h3>取货安排</h3><el-button size="small" :disabled="loading" @click="load">刷新进度</el-button></div>
<el-alert v-if="error" :title="error" type="error" :closable="false" />
<dl v-if="progress" class="pickup-fields">
<div><dt>取货进度</dt><dd>{{ labels[progress.status] || progress.status }}</dd></div><div><dt>车次号</dt><dd>{{ progress.tripNo || '待安排' }}</dd></div>
<div><dt>车牌</dt><dd>{{ progress.vehiclePlate || '待分配' }}</dd></div><div><dt>司机</dt><dd>{{ progress.driverName || '待分配' }}</dd></div>
<div><dt>司机电话</dt><dd>{{ progress.driverPhone || '—' }}</dd></div><div><dt>计划取货发车</dt><dd>{{ time(progress.plannedDepartureAt) }}</dd></div>
<div><dt>实际取货数量(箱)</dt><dd>{{ progress.actualPackages ?? '待取货' }}</dd></div><div><dt>取货时间</dt><dd>{{ time(progress.pickedAt) }}</dd></div>
<div><dt>送仓时间</dt><dd>{{ time(progress.arrivedAt) }}</dd></div><div v-if="progress.remark"><dt>取货备注</dt><dd>{{ progress.remark }}</dd></div>
</dl>
<div v-if="progress?.evidence.length" class="pickup-files"><span>取货凭证</span><el-button v-for="file in progress.evidence" :key="file.fileId" link type="primary" @click="download(file)">{{ file.fileName }}</el-button></div>
</section>
</template>
<style scoped>.pickup-progress{padding:0 16px 10px;border:1px solid var(--border,#e5e7eb);border-radius:6px;margin:16px 0}.pickup-heading{display:flex;min-height:40px;justify-content:space-between;align-items:center}.pickup-heading h3{margin:0;font-size:14px}.pickup-fields{display:grid;max-width:1408px;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px 18px;margin:8px 0 0}.pickup-fields>div{display:flex;min-height:24px;align-items:center;gap:8px;padding:1px 0}.pickup-fields dt{flex:0 0 84px;min-width:0;color:#8a95a5;font-size:12px}.pickup-fields dd{min-width:0;margin:0;overflow-wrap:anywhere;color:#334157;font-size:13px;font-weight:700}.pickup-files{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:8px}.pickup-files>span{color:#8a95a5;font-size:12px}@media(max-width:1100px){.pickup-fields{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:720px){.pickup-fields{grid-template-columns:1fr;gap:2px}}</style>