优化
This commit is contained in:
@@ -9,14 +9,106 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import StatusBadge from '@/shared/components/StatusBadge.vue'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { getDomesticContainerInventory } from '../api/domesticContainers'
|
||||
import type { InventoryDetail, TransactionRecord } from '../types'
|
||||
import type { InventoryDetail, InventoryStatus, TransactionRecord } from '../types'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const loading = ref(false)
|
||||
const error = ref<ApiErrorDetails | null>(null)
|
||||
const detail = ref<InventoryDetail | null>(null)
|
||||
|
||||
const transactionColumns: DataTableColumn[] = [
|
||||
{ prop: 'businessType', label: '业务类型', width: 110, slotName: 'businessType' },
|
||||
{ prop: 'orderNo', label: '单号', minWidth: 210 },
|
||||
{ prop: 'quantity', label: '数量', width: 110, align: 'right', formatter: (row: TransactionRecord) => `${row.quantity} 箱` },
|
||||
{ prop: 'operationTime', label: '操作时间', width: 170, formatter: (row: TransactionRecord) => displayTime(row.operationTime) },
|
||||
{ prop: 'remark', label: '备注', minWidth: 180, formatter: (row: TransactionRecord) => row.remark || '—' },
|
||||
]
|
||||
|
||||
function inventoryStatus(status: InventoryStatus) {
|
||||
return ({ IN_STOCK: '在库', PARTIALLY_OUTBOUND: '部分出库', OUTBOUND: '已出库' } as const)[status]
|
||||
}
|
||||
|
||||
function displayTime(value: string) {
|
||||
return value ? value.replace('T', ' ').slice(0, 16) : '—'
|
||||
}
|
||||
|
||||
function back() {
|
||||
void router.push({ name: 'domestic-containers' })
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
detail.value = await getDomesticContainerInventory(String(route.params.inventoryId))
|
||||
} catch (cause) {
|
||||
error.value = getApiErrorDetails(cause, '整柜库存详情加载失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const route = useRoute(); const router = useRouter(); const loading = ref(false); const error = ref<ApiErrorDetails | null>(null); const detail = ref<InventoryDetail | null>(null)
|
||||
const transactionColumns: DataTableColumn[] = [{ prop: 'businessType', label: '类型', width: 100, slotName: 'businessType' }, { prop: 'orderNo', label: '单号', minWidth: 160 }, { prop: 'quantity', label: '数量', width: 100, align: 'right', formatter: (row: TransactionRecord) => `${row.quantity} 箱` }, { prop: 'operationTime', label: '操作时间', minWidth: 170, formatter: (row: TransactionRecord) => row.operationTime.replace('T', ' ').slice(0, 16) }, { prop: 'remark', label: '备注', minWidth: 180, formatter: (row: TransactionRecord) => row.remark || '—' }]
|
||||
function inventoryStatus(status: string) { return ({ IN_STOCK: '在库', PARTIALLY_OUTBOUND: '部分出库', OUTBOUND: '已出库' } as Record<string, string>)[status] || status }
|
||||
async function load() { loading.value = true; error.value = null; try { detail.value = await getDomesticContainerInventory(String(route.params.inventoryId)) } catch (cause) { error.value = getApiErrorDetails(cause, '整柜库存详情加载失败') } finally { loading.value = false } }
|
||||
function back() { void router.push({ name: 'domestic-containers' }) }
|
||||
onMounted(load)
|
||||
</script>
|
||||
<template><AdminPage as="div" class="inventory-detail-page"><header class="detail-header"><div><el-button aria-label="返回整柜业务" @click="back"><ArrowLeft :size="16" />返回</el-button><h1>{{ detail?.inventory.containerNo || '整柜库存详情' }}</h1><StatusBadge v-if="detail" :status="inventoryStatus(detail.inventory.inventoryStatus)" /></div><p>查看整柜库存快照与不可变交易记录</p></header><LoadErrorState v-if="error" title="整柜库存详情加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState><template v-else-if="detail"><section class="detail-grid"><div class="surface-panel detail-section"><h2>货物信息</h2><dl><div><dt>货物名称</dt><dd>{{ detail.inventory.cargoName }}</dd></div><div><dt>集装箱号</dt><dd>{{ detail.inventory.containerNo }}</dd></div><div><dt>国内仓</dt><dd>{{ detail.inventory.warehouseName }}</dd></div><div><dt>入库单数量</dt><dd>{{ detail.inboundOrderCount }}</dd></div><div><dt>出库单数量</dt><dd>{{ detail.outboundOrderCount }}</dd></div><div><dt>累计入库体积</dt><dd>{{ detail.inventory.inboundVolumeCbm.toFixed(2) }} m³</dd></div></dl></div><div class="surface-panel detail-section"><h2>库存信息</h2><dl><div><dt>入库箱数</dt><dd>{{ detail.inventory.inboundBoxes }} 箱</dd></div><div><dt>已出库箱数</dt><dd>{{ detail.inventory.outboundBoxes }} 箱</dd></div><div><dt>当前库存</dt><dd>{{ detail.inventory.availableBoxes }} 箱</dd></div><div><dt>库存状态</dt><dd>{{ inventoryStatus(detail.inventory.inventoryStatus) }}</dd></div><div><dt>最后更新时间</dt><dd>{{ detail.inventory.updatedAt.replace('T', ' ').slice(0, 16) }}</dd></div><div><dt>库存版本</dt><dd>{{ detail.inventory.version }}</dd></div></dl></div></section><section class="surface-panel table-panel transactions"><h2>进销存交易记录</h2><DataTable :data="detail.transactions" :columns="transactionColumns" row-key="id" stripe column-settings-mode="hide" empty-text="暂无进销存流水"><template #businessType="{ row }"><StatusBadge :status="row.businessType === 'INBOUND' ? '入库' : '出库'" /></template></DataTable></section></template><div v-else class="surface-panel detail-loading" v-loading="loading">正在加载整柜库存详情</div></AdminPage></template>
|
||||
<style scoped>.inventory-detail-page{display:grid;min-width:0;gap:16px}.detail-header{padding:18px 20px;background:#fff;border:1px solid var(--cc-border)}.detail-header>div{display:flex;align-items:center;flex-wrap:wrap;gap:12px}.detail-header h1{margin:0;font-size:20px;letter-spacing:0}.detail-header p{margin:10px 0 0;color:var(--cc-muted)}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.detail-section{padding:18px}.detail-section h2,.transactions h2{margin:0 0 16px;font-size:16px;letter-spacing:0}.detail-section dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));margin:0;border-top:1px solid var(--cc-border);border-left:1px solid var(--cc-border)}.detail-section dl>div{min-width:0;padding:12px;border-right:1px solid var(--cc-border);border-bottom:1px solid var(--cc-border)}dt{font-size:12px;color:var(--cc-muted)}dd{margin:5px 0 0;overflow-wrap:anywhere}.transactions{padding:18px}.detail-loading{min-height:180px;padding:24px;color:var(--cc-muted)}@media(max-width:720px){.detail-grid{grid-template-columns:1fr}}@media(max-width:360px){.detail-header,.detail-section,.transactions{padding:12px}.detail-section dl{grid-template-columns:1fr}.detail-header h1{font-size:18px;width:100%}}</style>
|
||||
|
||||
<template>
|
||||
<AdminPage as="div" class="inventory-detail-page">
|
||||
<header class="detail-header">
|
||||
<el-button aria-label="返回整柜业务" @click="back"><ArrowLeft :size="16" />返回</el-button>
|
||||
<h1>{{ detail?.inventory.containerNo || '整柜库存详情' }}</h1>
|
||||
<StatusBadge v-if="detail" :status="inventoryStatus(detail.inventory.inventoryStatus)" />
|
||||
</header>
|
||||
|
||||
<LoadErrorState v-if="error" title="整柜库存详情加载失败" :message="error.message" :loading="loading" @retry="load">
|
||||
<template #details><ApiErrorMeta :details="error" /></template>
|
||||
</LoadErrorState>
|
||||
|
||||
<template v-else-if="detail">
|
||||
<section class="detail-section" aria-labelledby="inventory-basic-heading">
|
||||
<h2 id="inventory-basic-heading">整柜信息</h2>
|
||||
<dl class="detail-fields">
|
||||
<div><dt>货物名称</dt><dd>{{ detail.inventory.cargoName }}</dd></div>
|
||||
<div><dt>集装箱号</dt><dd>{{ detail.inventory.containerNo }}</dd></div>
|
||||
<div><dt>国内仓</dt><dd>{{ detail.inventory.warehouseName }}</dd></div>
|
||||
<div><dt>库存状态</dt><dd>{{ inventoryStatus(detail.inventory.inventoryStatus) }}</dd></div>
|
||||
<div><dt>入库单数量</dt><dd>{{ detail.inboundOrderCount }}</dd></div>
|
||||
<div><dt>出库单数量</dt><dd>{{ detail.outboundOrderCount }}</dd></div>
|
||||
<div><dt>入库箱数</dt><dd>{{ detail.inventory.inboundBoxes }} 箱</dd></div>
|
||||
<div><dt>已出库箱数</dt><dd>{{ detail.inventory.outboundBoxes }} 箱</dd></div>
|
||||
<div><dt>当前库存</dt><dd>{{ detail.inventory.availableBoxes }} 箱</dd></div>
|
||||
<div><dt>累计入库体积</dt><dd>{{ detail.inventory.inboundVolumeCbm.toFixed(2) }} m³</dd></div>
|
||||
<div><dt>最后更新时间</dt><dd>{{ displayTime(detail.inventory.updatedAt) }}</dd></div>
|
||||
<div><dt>库存版本</dt><dd>{{ detail.inventory.version }}</dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="transactions" aria-labelledby="transactions-heading">
|
||||
<h2 id="transactions-heading">进销存交易记录</h2>
|
||||
<DataTable :data="detail.transactions" :columns="transactionColumns" row-key="id" stripe column-settings-mode="hide" empty-text="暂无进销存流水">
|
||||
<template #businessType="{ row }"><StatusBadge :status="row.businessType === 'INBOUND' ? '入库' : '出库'" /></template>
|
||||
</DataTable>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<div v-else class="detail-loading" v-loading="loading">正在加载整柜库存详情</div>
|
||||
</AdminPage>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.inventory-detail-page { display: grid; min-width: 0; gap: 16px; }
|
||||
.detail-header { display: flex; align-items: center; gap: 12px; min-height: 40px; }
|
||||
.detail-header h1 { margin: 0; font-size: 20px; letter-spacing: 0; }
|
||||
.detail-section, .transactions { min-width: 0; border: 1px solid var(--cc-border); background: #fff; }
|
||||
.detail-section { padding: 16px 18px 18px; }
|
||||
.detail-section h2, .transactions h2 { margin: 0; font-size: 15px; letter-spacing: 0; }
|
||||
.detail-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 14px 0 0; border-top: 1px solid var(--cc-border); border-left: 1px solid var(--cc-border); }
|
||||
.detail-fields > div { min-width: 0; min-height: 58px; padding: 10px 12px; border-right: 1px solid var(--cc-border); border-bottom: 1px solid var(--cc-border); }
|
||||
.detail-fields dt { color: var(--cc-muted); font-size: 12px; }
|
||||
.detail-fields dd { margin: 4px 0 0; overflow-wrap: anywhere; }
|
||||
.transactions { padding-top: 16px; overflow: hidden; }
|
||||
.transactions h2 { margin: 0 18px 14px; }
|
||||
.detail-loading { min-height: 180px; padding: 24px; border: 1px solid var(--cc-border); background: #fff; color: var(--cc-muted); }
|
||||
@media (max-width: 960px) { .detail-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||
@media (max-width: 520px) { .detail-header { flex-wrap: wrap; } .detail-header h1 { width: 100%; font-size: 18px; } .detail-fields { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user