fix(admin): preserve tail-leg references

This commit is contained in:
2026-09-01 11:03:45 +08:00
parent 0cf4a93f9c
commit 4711bcc4e6
10 changed files with 80 additions and 16 deletions
@@ -11,7 +11,7 @@ import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.v
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import OperationErrorToast from '@/shared/components/OperationErrorToast.vue'
import { createLastMileOrderFee, getLastMileOrder, type LastMileOrderDetailDto } from '../api/lastMileOrders'
import { formatOverseasDateTime, lastMileOrderTypeLabel, lastMileStatusLabel } from '../lastMilePresentation'
import { formatOverseasDateTime, lastMileOrderReference, lastMileOrderTypeLabel, lastMileStatusLabel } from '../lastMilePresentation'
import { overseasWarehousePermissions as permission } from '../permissions'
import OverseasDetailShell from '../components/OverseasDetailShell.vue'
import OrderReferenceText from '../components/OrderReferenceText.vue'
@@ -39,7 +39,7 @@ function text(value: unknown) { return String(value ?? '').trim() || '—' }
function yesNo(value: boolean | null | undefined) { return value == null ? '—' : value ? '是' : '否' }
function feeStatusLabel(value: string) { return ({ PENDING_REVIEW: '待审核', APPROVED: '审核通过', REJECTED: '已驳回' } as Record<string, string>)[value] || value }
const referenceValue = computed(() => text(detail.value?.order.orderNo || '订单编码待补充'))
const referenceValue = computed(() => lastMileOrderReference(detail.value?.order.orderNo, '订单编码待补充'))
const orderFields = computed<DetailField[]>(() => {
const order = detail.value?.order
return [
@@ -151,7 +151,7 @@ onMounted(load)
<template>
<OverseasDetailShell title="尾程订单详情" reference-label="尾程单号" :reference-value="referenceValue" back-label="返回尾程订单" domain="尾程订单详情" :pending="false" :status-text="detail ? lastMileStatusLabel(detail.order.currentStatus) : '加载中'" @back="back">
<template #reference><OrderReferenceText :value="referenceValue" /></template>
<template #reference><OrderReferenceText :value="referenceValue" copyable /></template>
<OperationErrorToast :details="mutationError" />
<LoadErrorState v-if="loadError" title="尾程订单详情加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
<section v-else v-loading="loading" class="detail-surface" :aria-busy="loading">
@@ -406,7 +406,7 @@ onMounted(() => { void load() })
<section v-else-if="!loadError" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="overseas-last-mile-orders" row-key="id" empty-text="暂无尾程订单" @selection-change="onSelectionChange" @update:page="load()" @update:page-size="page = 1; load()">
<template #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" plain :disabled="selectedRows.length !== 1 || actionLoading" @click="convertInboundPlan">生成入库计划</el-button><el-button v-if="statusTab === '待分配' && access.can(permission.inboundOrderCreate)" type="primary" :disabled="actionLoading" @click="openContainerConversion">按柜批量生成</el-button></template>
<template #actions="{ row }"><el-button size="small" plain type="primary" @click="openDetail(row)"><Eye :size="15" />查看</el-button></template>
<template #orderNo="{ row }"><OrderReferenceText :value="String(row.orderNo || '')" /></template>
<template #orderNo="{ row }"><OrderReferenceText :value="String(row.orderNo || '')" copyable /></template>
<template #pagination-left>共 {{ total }} 条尾程订单 · 已选 {{ selectedRows.length }} 条</template>
</DataTable></section>
</ListPageLayout></AdminPage>
@@ -128,6 +128,16 @@ describe('overseas warehouse first-batch prototype contract', () => {
expect(value).not.toContain('海外派送')
})
it('renders and copies the server-provided tail-leg short number in list and detail', () => {
const list = source('LastMileOrdersView.vue')
const detail = source('LastMileOrderDetailView.vue')
expect(list).toContain('<OrderReferenceText :value="String(row.orderNo || \'\')" copyable />')
expect(detail).toContain('lastMileOrderReference(detail.value?.order.orderNo')
expect(detail).toContain('<OrderReferenceText :value="referenceValue" copyable />')
expect(list).not.toMatch(/padStart|LMO-\$\{|slice\([^)]*orderNo/)
expect(detail).not.toMatch(/padStart|LMO-\$\{|slice\([^)]*orderNo/)
})
it('connects the tail-leg detail to the real overseas API and keeps missing contracts pending', () => {
const tailLeg = source('LastMileOrderDetailView.vue')
expect(tailLeg).toContain('getLastMileOrder')
@@ -137,6 +147,8 @@ describe('overseas warehouse first-batch prototype contract', () => {
expect(tailLeg).toContain('label="费用明细"')
expect(tailLeg).toContain('label="操作记录"')
expect(tailLeg).toContain('title="新增费用"')
expect(tailLeg).toContain('lastMileOrderReference(detail.value?.order.orderNo')
expect(tailLeg).toContain('<OrderReferenceText :value="referenceValue" copyable />')
const inbound = source('InboundOrderDetailView.vue')
expect(inbound).toContain('getInboundPlan')
expect(inbound).toContain('sourceOrderId')