This commit is contained in:
2026-09-06 18:11:35 +08:00
parent 12e63b1dcb
commit b31c37951f
4 changed files with 57 additions and 1 deletions
@@ -81,6 +81,12 @@ export interface RelabelItemDto {
labelRequirement?: string | null
relabelFileName?: string | null
relabelFileUrl?: string | null
shipmentNo?: string | null
trackingCode?: string | null
remark?: string | null
cartonMark?: string | null
fbaCartonMark?: string | null
destinationWarehouseId?: string | null
}
export interface RelabelHistoryDto {
@@ -40,6 +40,7 @@ defineEmits<{ back: [] }>()
<h2>{{ group.title }}</h2>
<dl class="detail-fields"><div v-for="field in group.fields" :key="field"><dt>{{ field }}</dt><dd>{{ fieldValues?.[field] ?? '—' }}</dd></div></dl>
</section>
<slot name="content-after" />
</section>
</OverseasDetailShell>
</template>
@@ -0,0 +1,16 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const source = readFileSync(resolve(process.cwd(), 'src/modules/overseas-warehouse/pages/RelabelOrderDetailView.vue'), 'utf8')
describe('RelabelOrderDetailView', () => {
it('renders carton relabel mappings as a row list instead of summary form fields', () => {
expect(source).toContain('<template #content-after>')
expect(source).toContain('<h2>箱唛换标信息</h2>')
expect(source).toContain('v-for="item in detail?.items || []"')
expect(source).toContain('text(item.cartonMark)')
expect(source).toContain('text(item.fbaCartonMark)')
expect(source).not.toContain("{ title: '箱唛换标信息', fields:")
})
})
@@ -59,4 +59,37 @@ function back() { void router.push({ name: 'overseas-relabel-orders' }) }
onMounted(load)
</script>
<template><OverseasReadOnlyDetail title="换标单详情" reference-label="换标单号" :reference-value="referenceValue" back-label="返回换标单" domain="换标单详情" :groups="groups" :field-values="fieldValues" :pending="false" :status-text="detail ? status(detail.application.status) : '加载中'" :loading="loading" :show-content="!loadError" @back="back"><template #state><LoadErrorState v-if="loadError" title="换标单详情加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState></template></OverseasReadOnlyDetail></template>
<template>
<OverseasReadOnlyDetail title="换标单详情" reference-label="换标单号" :reference-value="referenceValue" back-label="返回换标单" domain="换标单详情" :groups="groups" :field-values="fieldValues" :pending="false" :status-text="detail ? status(detail.application.status) : '加载中'" :loading="loading" :show-content="!loadError" @back="back">
<template #state><LoadErrorState v-if="loadError" title="换标单详情加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState></template>
<template #content-after>
<section class="relabel-mark-list" aria-label="箱唛换标信息">
<div class="relabel-mark-list__head"><h2>箱唛换标信息</h2><span>共 {{ detail?.items.length || 0 }} 条</span></div>
<div class="relabel-mark-list__scroll">
<table>
<thead><tr><th>我方箱唛</th><th>FBA 箱唛</th><th>商品 SKU</th><th>中文品名</th><th>FBA 货件编号</th><th>换标新 SKU</th><th>目的仓</th><th>备注</th></tr></thead>
<tbody>
<tr v-for="item in detail?.items || []" :key="item.id"><td class="mark-code">{{ text(item.cartonMark) }}</td><td class="mark-code">{{ text(item.fbaCartonMark) }}</td><td>{{ text(item.skuCode) }}</td><td>{{ text(item.productNameZh) }}</td><td>{{ text(item.shipmentNo) }}</td><td>{{ text(item.newSkuCode) }}</td><td>{{ text(item.destinationWarehouseId) }}</td><td>{{ text(item.remark) }}</td></tr>
<tr v-if="!detail?.items.length"><td class="empty-cell" colspan="8">暂无箱唛换标信息</td></tr>
</tbody>
</table>
</div>
</section>
</template>
</OverseasReadOnlyDetail>
</template>
<style scoped>
.relabel-mark-list { min-width: 0; grid-column: 1 / -1; padding: 18px; }
.relabel-mark-list__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.relabel-mark-list__head h2 { margin: 0; color: var(--cc-text); font-size: 15px; }
.relabel-mark-list__head span { color: var(--cc-muted); font-size: 12px; }
.relabel-mark-list__scroll { overflow-x: auto; border: 1px solid var(--cc-border); border-radius: 4px; }
table { width: 100%; min-width: 1120px; border-collapse: collapse; font-size: 13px; }
th { height: 42px; padding: 0 12px; border-bottom: 1px solid var(--cc-border); background: #f8fafc; color: var(--cc-muted); font-size: 12px; font-weight: 600; text-align: left; white-space: nowrap; }
td { min-height: 46px; padding: 12px; border-bottom: 1px solid var(--cc-border); color: var(--cc-text); overflow-wrap: anywhere; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: #fafcff; }
.mark-code { color: #245b9e; font-weight: 600; }
.empty-cell { height: 96px; color: var(--cc-muted); text-align: center; }
</style>