优化
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { shallowMount, flushPromises } from '@vue/test-utils'
|
||||
import TransferPickupProgressPanel from './TransferPickupProgressPanel.vue'
|
||||
import { getTransferPickupProgress, type PickupProgress } from '../api/transferPickups'
|
||||
|
||||
vi.mock('../api/transferPickups', () => ({ getTransferPickupProgress: vi.fn(), downloadTransferPickupEvidence: vi.fn() }))
|
||||
const progress = (tripNo: string): PickupProgress => ({ tripNo, status: 'ARRIVED', vehiclePlate: 'TEST-1', driverName: '验收司机', driverPhone: '000', plannedDepartureAt: null, actualPackages: 5, pickedAt: null, arrivedAt: null, remark: null, evidence: [] })
|
||||
it('ignores an old customer response after switching the order identity', async () => {
|
||||
let resolve!: (value: PickupProgress) => void
|
||||
vi.mocked(getTransferPickupProgress).mockImplementationOnce(() => new Promise(done => { resolve = done })).mockResolvedValueOnce(progress('TR-NEW'))
|
||||
const wrapper = shallowMount(TransferPickupProgressPanel, { props: { customerId: 'C1', transferNo: 'WT-OLD' }, global: { stubs: { ElButton: { template: '<button><slot/></button>' } } } })
|
||||
await wrapper.setProps({ customerId: 'C2', transferNo: 'WT-NEW' }); await flushPromises(); resolve(progress('TR-OLD')); await flushPromises()
|
||||
expect(wrapper.text()).toContain('TR-NEW'); expect(wrapper.text()).not.toContain('TR-OLD')
|
||||
expect(getTransferPickupProgress).toHaveBeenLastCalledWith('WT-NEW', 'C2'); wrapper.unmount()
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { getApiErrorDetails } from '@/shared/api/http'
|
||||
import { getTransferPickupProgress, downloadTransferPickupEvidence, type PickupProgress } from '../api/transferPickups'
|
||||
|
||||
const props = defineProps<{ transferNo: string; customerId: 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, props.customerId); if (current === sequence) progress.value = value }
|
||||
catch (cause) { if (current === sequence) error.value = getApiErrorDetails(cause, '取货进度加载失败').message }
|
||||
finally { if (current === sequence) loading.value = false }
|
||||
}
|
||||
/** 凭证读取必须经过原单鉴权。 */
|
||||
async function download(file: { fileId: string; fileName: string }) {
|
||||
try { const blob = await downloadTransferPickupEvidence(props.transferNo, props.customerId, 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 = getApiErrorDetails(cause, '取货凭证下载失败').message }
|
||||
}
|
||||
watch(() => [props.customerId, 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:16px;border:1px solid var(--border,#e5e7eb);border-radius:6px;margin:16px 0}.pickup-heading{display:flex;justify-content:space-between;align-items:center}.pickup-heading h3{margin:0;font-size:15px}.pickup-fields{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 20px;margin:16px 0 0}.pickup-fields>div{display:flex;gap:10px}.pickup-fields dt{color:var(--muted,#64748b);flex-shrink:0}.pickup-fields dd{margin:0;overflow-wrap:anywhere}.pickup-files{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:14px}</style>
|
||||
Reference in New Issue
Block a user