优化
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch, type Component } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ArrowLeft, Box, ChevronDown, ChevronUp, CircleCheck, Eye, GitBranch, History, ListChecks, MoreHorizontal, PackageOpen, Ruler, SlidersHorizontal, StickyNote, WalletCards } from '@lucide/vue'
|
||||
import { ArrowLeft, Box, ChevronDown, ChevronUp, CircleCheck, Eye, GitBranch, History, Link2, ListChecks, MoreHorizontal, PackageOpen, Ruler, SlidersHorizontal, StickyNote, WalletCards } from '@lucide/vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
getPlatformUnifiedOrder,
|
||||
@@ -23,6 +23,7 @@ import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
|
||||
import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { getLoadingAssociationSummary, getOverseasInboundCodeRelationship, type LoadingAssociationSummary, type OverseasInboundCodeRelationship } from '@/shared/api/inboundCodeRelations'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import AppDialog from '@/shared/components/AppDialog.vue'
|
||||
@@ -153,10 +154,16 @@ const cargoImagePreviewUrls = new Set<string>()
|
||||
const measurementDialogOpen = ref(false)
|
||||
const smartLoadingOpen = ref(false)
|
||||
const measurementOrder = ref<UnifiedOrderResource | null>(null)
|
||||
const loadingAssociation = ref<LoadingAssociationSummary | null>(null)
|
||||
const overseasRelationship = ref<OverseasInboundCodeRelationship | null>(null)
|
||||
const loadingAssociationError = ref<ApiErrorDetails | null>(null)
|
||||
const overseasRelationshipError = ref<ApiErrorDetails | null>(null)
|
||||
const subsequentFulfillmentLoading = ref(false)
|
||||
let detailLoadingKey = ''
|
||||
let detailRequestSerial = 0
|
||||
let measurementRequestSerial = 0
|
||||
let measurementPreviewRequestSerial = 0
|
||||
let subsequentFulfillmentRequestSerial = 0
|
||||
const showAdvancedFilters = ref(false)
|
||||
const filters = ref<FilterModel>(emptyFilters())
|
||||
const appliedFilters = ref<FilterModel>(emptyFilters())
|
||||
@@ -588,6 +595,36 @@ async function loadMeasurementDetails() {
|
||||
function selectDetailTab(key: string) {
|
||||
activeDetailTab.value = key
|
||||
if (key === 'measurement') void loadMeasurementDetails()
|
||||
if (key === 'fulfillment') void loadSubsequentFulfillment()
|
||||
}
|
||||
|
||||
const hasLoadingAssociation = computed(() => Boolean(loadingAssociation.value
|
||||
&& (loadingAssociation.value.loadingPlanNo || loadingAssociation.value.containerNo || loadingAssociation.value.cabinetNo
|
||||
|| loadingAssociation.value.loadingStatus || loadingAssociation.value.pdaTaskStatus)))
|
||||
const hasOverseasRelationship = computed(() => Boolean(overseasRelationship.value?.found
|
||||
&& (overseasRelationship.value.overseasWarehouse || overseasRelationship.value.overseasReceivingStatus
|
||||
|| overseasRelationship.value.taillegOrders.length || overseasRelationship.value.inboundPlans.length
|
||||
|| overseasRelationship.value.palletCodes.length || overseasRelationship.value.inventory.length)))
|
||||
const hasSubsequentFulfillment = computed(() => hasLoadingAssociation.value || hasOverseasRelationship.value)
|
||||
|
||||
async function loadSubsequentFulfillment() {
|
||||
const inboundCode = detail.value?.summary.inboundCode?.trim() || ''
|
||||
const serial = ++subsequentFulfillmentRequestSerial
|
||||
loadingAssociation.value = null
|
||||
overseasRelationship.value = null
|
||||
loadingAssociationError.value = null
|
||||
overseasRelationshipError.value = null
|
||||
if (!inboundCode) return
|
||||
subsequentFulfillmentLoading.value = true
|
||||
const tasks: Promise<void>[] = []
|
||||
if (can('platform:firstleg:smart-loading:list')) tasks.push(getLoadingAssociationSummary(inboundCode)
|
||||
.then((value) => { if (serial === subsequentFulfillmentRequestSerial) loadingAssociation.value = value })
|
||||
.catch((error) => { if (serial === subsequentFulfillmentRequestSerial) loadingAssociationError.value = getApiErrorDetails(error, '装柜与PDA履约数据加载失败') }))
|
||||
if (can('platform:overseas-warehouse:inventory:list')) tasks.push(getOverseasInboundCodeRelationship(inboundCode)
|
||||
.then((value) => { if (serial === subsequentFulfillmentRequestSerial) overseasRelationship.value = value })
|
||||
.catch((error) => { if (serial === subsequentFulfillmentRequestSerial) overseasRelationshipError.value = getApiErrorDetails(error, '尾程与库存履约数据加载失败') }))
|
||||
await Promise.all(tasks)
|
||||
if (serial === subsequentFulfillmentRequestSerial) subsequentFulfillmentLoading.value = false
|
||||
}
|
||||
|
||||
function toggleMeasurementSection(section: keyof typeof measurementCollapsed) {
|
||||
@@ -989,6 +1026,7 @@ watch(detailRouteKey, (value) => {
|
||||
void loadDetail()
|
||||
} else {
|
||||
detailRequestSerial += 1
|
||||
subsequentFulfillmentRequestSerial += 1
|
||||
detail.value = null
|
||||
detailError.value = null
|
||||
detailLoading.value = false
|
||||
@@ -1170,6 +1208,26 @@ onBeforeUnmount(() => {
|
||||
<template v-else-if="activeDetailTab === 'fulfillment'">
|
||||
<div class="panel-title"><div><h2>拆分履约</h2><p>根单、已完成分片与当前余量</p></div><ListChecks :size="19" /></div>
|
||||
<OrderFulfillmentTreePanel :tenant-id="String(detail.summary.tenantId)" :order-id="String(detail.summary.orderId)" :inbound-code="detail.summary.inboundCode" />
|
||||
<section v-loading="subsequentFulfillmentLoading" class="subsequent-fulfillment" aria-label="后续履约数据">
|
||||
<h3>后续履约数据</h3>
|
||||
<LoadErrorState v-if="loadingAssociationError" title="装柜与PDA履约数据加载失败" :message="loadingAssociationError.message" @retry="loadSubsequentFulfillment"><template #details><ApiErrorMeta :details="loadingAssociationError" /></template></LoadErrorState>
|
||||
<LoadErrorState v-if="overseasRelationshipError" title="尾程与库存履约数据加载失败" :message="overseasRelationshipError.message" @retry="loadSubsequentFulfillment"><template #details><ApiErrorMeta :details="overseasRelationshipError" /></template></LoadErrorState>
|
||||
<dl v-if="hasLoadingAssociation" class="fulfillment-facts">
|
||||
<div><dt>装柜计划</dt><dd>{{ loadingAssociation?.loadingPlanNo || '—' }}</dd></div>
|
||||
<div><dt>柜号</dt><dd>{{ loadingAssociation?.containerNo || loadingAssociation?.cabinetNo || '—' }}</dd></div>
|
||||
<div><dt>装柜状态</dt><dd>{{ loadingAssociation?.loadingStatus || '—' }}</dd></div>
|
||||
<div><dt>PDA状态</dt><dd>{{ loadingAssociation?.pdaTaskStatus || '—' }}</dd></div>
|
||||
</dl>
|
||||
<dl v-if="hasOverseasRelationship" class="fulfillment-facts">
|
||||
<div><dt>海外仓</dt><dd>{{ overseasRelationship?.overseasWarehouse?.warehouseName || '尚未分配海外仓' }}</dd></div>
|
||||
<div><dt>海外收货状态</dt><dd>{{ overseasRelationship?.overseasReceivingStatus || '—' }}</dd></div>
|
||||
<div class="wide"><dt>尾程订单</dt><dd>{{ overseasRelationship?.taillegOrders.map((item) => item.orderNo).join('、') || '—' }}</dd></div>
|
||||
<div class="wide"><dt>入库计划</dt><dd>{{ overseasRelationship?.inboundPlans.map((item) => item.planNo).join('、') || '—' }}</dd></div>
|
||||
<div class="wide"><dt>托盘码</dt><dd>{{ overseasRelationship?.palletCodes.join('、') || '—' }}</dd></div>
|
||||
<div><dt>库存SKU</dt><dd>{{ overseasRelationship?.inventory.length || 0 }} 个</dd></div>
|
||||
</dl>
|
||||
<p v-if="!subsequentFulfillmentLoading && !loadingAssociationError && !overseasRelationshipError && !hasSubsequentFulfillment" class="fulfillment-empty">暂无后续履约数据</p>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<template v-else-if="activeDetailTab === 'workflow'">
|
||||
@@ -1464,6 +1522,14 @@ onBeforeUnmount(() => {
|
||||
.coload-detail-table td strong,.coload-detail-table td span { display: block; overflow-wrap: anywhere; }
|
||||
.coload-detail-table td span { color: var(--cc-muted); }
|
||||
.coload-detail-table :deep(.el-button) { min-height: 24px; padding: 2px 0; }
|
||||
.subsequent-fulfillment { min-height: 72px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--cc-border); }
|
||||
.subsequent-fulfillment h3 { margin: 0 0 10px; font-size: 15px; }
|
||||
.fulfillment-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0 0 10px; border: 1px solid var(--cc-border); border-radius: 6px; overflow: hidden; }
|
||||
.fulfillment-facts > div { min-width: 0; padding: 9px 10px; border-right: 1px solid var(--cc-border); background: #fff; }
|
||||
.fulfillment-facts > div.wide { grid-column: span 2; }
|
||||
.fulfillment-facts dt { color: var(--cc-muted); font-size: 12px; }
|
||||
.fulfillment-facts dd { min-width: 0; margin: 4px 0 0; overflow-wrap: anywhere; font-size: 13px; }
|
||||
.fulfillment-empty { margin: 0; padding: 12px; border: 1px dashed var(--cc-border); border-radius: 6px; color: var(--cc-muted); text-align: center; }
|
||||
.table-card :deep(.el-table) { --el-table-border-color: #e5e7eb; --el-table-header-bg-color: #f9fafb; --el-table-row-hover-bg-color: #f3f7fb; --el-table-tr-bg-color: #fff; color: #374151; font-size: 12px; }
|
||||
.table-card :deep(.el-table th.el-table__cell) { height: 42px; padding: 0; background: #f9fafb; color: #374151; font-size: 12px; font-weight: 600; }
|
||||
.table-card :deep(.el-table td.el-table__cell) { min-height: 42px; padding: 9px 0; }
|
||||
|
||||
Reference in New Issue
Block a user