优化
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed } from 'vue'
|
||||
import { ArrowLeft, Check, Pencil } from '@lucide/vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
@@ -146,7 +147,7 @@ function formatNumber(value?: number | null, digits = 3) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section v-loading="loading" class="loading-detail-content" :aria-label="title" :aria-busy="loading">
|
||||
<section v-loading="loading" class="loading-detail-content" :class="{ 'admin-density preload-density': mode === 'preload' }" :aria-label="title" :aria-busy="loading">
|
||||
<section class="detail-overview" aria-label="清单概览">
|
||||
<header class="detail-page-header" :class="{ 'detail-page-header--embedded': embedded }">
|
||||
<el-button link type="primary" class="detail-page-header__back" @click="emit('back')"><ArrowLeft :size="16" />返回列表</el-button>
|
||||
@@ -155,7 +156,7 @@ function formatNumber(value?: number | null, digits = 3) {
|
||||
<p>{{ mode === 'preload' ? '核对运输信息、确认预装并维护逐条仓库备注' : '查看已完成装柜明细和柜次费用' }}</p>
|
||||
</div>
|
||||
<div v-if="detail && summary" class="detail-page-header__actions">
|
||||
<PalletLabelPrintDialog v-if="summary.warehouseId" :plan-id="summary.planId" :warehouse-id="summary.warehouseId" :disabled="!summary.containerNo || summary.status === 'EDITING'" />
|
||||
<PalletLabelPrintDialog :dense="mode === 'preload'" v-if="summary.warehouseId" :plan-id="summary.planId" :warehouse-id="summary.warehouseId" :disabled="!summary.containerNo || summary.status === 'EDITING'" />
|
||||
<template v-if="canEditItemRemark">
|
||||
<el-button v-if="canEditTransport" @click="emit('edit')"><Pencil :size="16" />{{ summary.containerNo ? '纠正集装箱号 / 航次' : '补录集装箱号 / 航次' }}</el-button>
|
||||
<el-button type="primary" :loading="confirmSaving" :disabled="!preloadSummary?.readiness.canConfirm" @click="emit('confirmPreload')"><Check :size="16" />确认预装</el-button>
|
||||
@@ -219,16 +220,13 @@ function formatNumber(value?: number | null, digits = 3) {
|
||||
|
||||
<section class="history-section" aria-label="操作历史">
|
||||
<header><h2>操作历史</h2><span>{{ visibleHistories.length }} 条</span></header>
|
||||
<el-empty v-if="visibleHistories.length === 0" description="暂无操作历史" :image-size="72" />
|
||||
<el-timeline v-else>
|
||||
<el-timeline-item v-for="history in visibleHistories" :key="historyEventKey(history) || history.historyId" :timestamp="formatDateTime(history.occurredAt)" placement="top">
|
||||
<div class="history-entry">
|
||||
<strong>{{ actionLabel(history.actionType) }}</strong>
|
||||
<span v-if="history.fromStatus || history.toStatus">{{ loadingListStatusLabel(history.fromStatus) }} → {{ loadingListStatusLabel(history.toStatus) }}</span>
|
||||
<p>{{ history.operatorName || '操作人信息缺失' }}<template v-if="history.operationReason"> · {{ history.operationReason }}</template></p>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<el-table :data="visibleHistories" border stripe empty-text="暂无操作历史" aria-label="清单操作历史">
|
||||
<el-table-column label="时间" width="170"><template #default="{ row }">{{ formatDateTime(row.occurredAt) }}</template></el-table-column>
|
||||
<el-table-column label="事件" width="140"><template #default="{ row }">{{ actionLabel(row.actionType) }}</template></el-table-column>
|
||||
<el-table-column label="状态变化" min-width="200"><template #default="{ row }"><span v-if="row.fromStatus || row.toStatus">{{ loadingListStatusLabel(row.fromStatus) }} → {{ loadingListStatusLabel(row.toStatus) }}</span><span v-else>—</span></template></el-table-column>
|
||||
<el-table-column label="操作人" min-width="160"><template #default="{ row }">{{ row.operatorName || '操作人信息缺失' }}</template></el-table-column>
|
||||
<el-table-column label="原因 / 备注" min-width="240"><template #default="{ row }">{{ row.operationReason || '—' }}</template></el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</DetailPageLayout>
|
||||
</div>
|
||||
@@ -273,7 +271,21 @@ function formatNumber(value?: number | null, digits = 3) {
|
||||
.history-section header { display: flex; align-items: baseline; gap: 10px; margin-bottom: 18px; }
|
||||
.history-section h2 { margin: 0; font-size: 16px; }
|
||||
.history-section header span { color: var(--cc-muted); font-size: 12px; }
|
||||
.history-entry { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
||||
.history-entry > span { color: var(--cc-muted); font-size: 12px; }
|
||||
.history-entry p { width: 100%; margin: 5px 0 0; color: var(--cc-muted); font-size: 12px; }
|
||||
.preload-density { gap: 12px; padding: 12px; border-radius: 4px; }
|
||||
.preload-density .detail-page-header { gap: 12px; padding: 0 0 8px; }
|
||||
.preload-density .detail-page-header__identity h1 { font-size: 16px; overflow-wrap: anywhere; }
|
||||
.preload-density .detail-page-header__actions { flex-wrap: wrap; }
|
||||
.preload-density .detail-summary { gap: 0; padding: 0; border-left: 1px solid var(--cc-border); }
|
||||
.preload-density .detail-summary > div { gap: 0; align-items: stretch; min-height: 36px; border-bottom: 1px solid var(--cc-border); border-right: 1px solid var(--cc-border); }
|
||||
.preload-density .detail-summary > div > span:first-child { display: flex; align-items: center; flex: 0 0 96px; padding: 6px 8px; background: #f8fafc; }
|
||||
.preload-density .detail-summary > div > span:first-child::after { content: none; }
|
||||
.preload-density .detail-summary strong, .preload-density .detail-summary :deep(.status-badge) { align-self: center; margin: 6px 8px; font-weight: 400; }
|
||||
.preload-density .detail-summary__wide { grid-column: span 2; }
|
||||
.preload-density .detail-layout :deep(.detail-page-layout__content) { gap: 12px; }
|
||||
.preload-density .detail-section, .preload-density .history-section { padding-top: 8px; }
|
||||
.preload-density .detail-section__heading h2 { font-size: 14px; }
|
||||
.preload-density .detail-section__heading p, .preload-density small { font-size: 12px; }
|
||||
.preload-density .readiness-note { align-items: baseline; }
|
||||
.preload-density .readiness-note span { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
|
||||
@media (max-width: 720px) { .preload-density .detail-summary { grid-template-columns: 1fr; } .preload-density .detail-summary__wide { grid-column: auto; } }
|
||||
</style>
|
||||
|
||||
@@ -229,9 +229,9 @@ describe('LoadingListsView', () => {
|
||||
expect(source).toContain("item.customerName || '客户信息缺失'")
|
||||
expect(source).not.toContain('item.customerName || item.accountId')
|
||||
expect(detailSource).toContain("item.customerName || '客户信息缺失'")
|
||||
expect(detailSource).toContain("history.operatorName || '操作人信息缺失'")
|
||||
expect(detailSource).toContain("row.operatorName || '操作人信息缺失'")
|
||||
expect(detailSource).not.toContain('item.customerName || item.accountId')
|
||||
expect(detailSource).not.toContain('history.operatorName || history.operatorId')
|
||||
expect(detailSource).not.toContain('row.operatorName || row.operatorId')
|
||||
})
|
||||
|
||||
it('does not retain the retired loading-list customs entry', () => {
|
||||
@@ -244,7 +244,7 @@ describe('LoadingListsView', () => {
|
||||
it('filters pure status no-ops and counts identity-distinct visible history events', () => {
|
||||
for (const marker of ['visibleHistories', 'STATUS_UPDATE', 'operationId', 'PUSH_PRELOAD']) expect(detailSource).toContain(marker)
|
||||
expect(detailSource).toContain('visibleHistories.length }} 条')
|
||||
expect(detailSource).toContain('v-for="history in visibleHistories"')
|
||||
expect(detailSource).toContain(':data="visibleHistories"')
|
||||
expect(detailSource).not.toContain('detail.histories.length }} 条')
|
||||
expect(detailSource).not.toContain('v-for="history in detail.histories"')
|
||||
expect(detailSource).toContain('seen.has(eventKey)')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ContainerSimulationCreate } from '@/modules/container-loading'
|
||||
@@ -181,7 +182,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<AdminPage>
|
||||
<div class="business-page loading-lists-page">
|
||||
<div class="business-page loading-lists-page" :class="{ 'admin-density': isPreload }">
|
||||
<ListPageLayout :ariaLabel="title">
|
||||
<template #toolbar>
|
||||
<QueryToolbar
|
||||
@@ -215,7 +216,7 @@ onMounted(() => {
|
||||
:aria-label="title"
|
||||
>
|
||||
<template #toolbar-actions>
|
||||
<ContainerSimulationCreate v-if="canCreate" success-message="模拟柜及预装清单已创建" @created="onSimulationCreated" />
|
||||
<ContainerSimulationCreate :dense="isPreload" v-if="canCreate" success-message="模拟柜及预装清单已创建" @created="onSimulationCreated" />
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<div class="row-actions">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, ref } from 'vue'
|
||||
import { Printer } from '@lucide/vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@@ -7,7 +8,7 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { preparePalletLabels, printPalletLabels, type PalletLabelManifest } from '../api/platformLoadingLists'
|
||||
|
||||
const props = defineProps<{ planId: string; warehouseId: string; disabled?: boolean }>()
|
||||
const props = defineProps<{ planId: string; warehouseId: string; disabled?: boolean; dense?: boolean }>()
|
||||
const open = ref(false)
|
||||
const loading = ref(false)
|
||||
const printing = ref(false)
|
||||
@@ -47,7 +48,7 @@ async function print() {
|
||||
|
||||
<template>
|
||||
<el-button :disabled="disabled" @click="show"><Printer :size="16" />打印托盘码</el-button>
|
||||
<AppDialog v-model="open" title="散货托盘码" width="min(760px, calc(100vw - 28px))" confirm-text="生成 PDF" :loading="loading" :confirm-loading="printing" :confirm-disabled="disabledConfirm" @confirm="print">
|
||||
<AppDialog :class="{ 'admin-density-dialog': dense }" v-model="open" title="散货托盘码" width="min(760px, calc(100vw - 28px))" confirm-text="生成 PDF" :loading="loading" :confirm-loading="printing" :confirm-disabled="disabledConfirm" @confirm="print">
|
||||
<LoadErrorState v-if="error" compact title="托盘码操作失败" :message="error.message" :show-retry="false" />
|
||||
<template v-if="manifest">
|
||||
<el-alert type="info" :closable="false" :title="`编号规则:${manifest.containerNo}-FBA地址内部编号-三位序号;一件代发托盘不在此清单。`" />
|
||||
|
||||
Reference in New Issue
Block a user