This commit is contained in:
2026-08-31 10:31:53 +08:00
parent b4d5fb1170
commit 1548d444c6
7 changed files with 144 additions and 99 deletions
@@ -63,4 +63,20 @@ describe('co-load group API', () => {
expect.objectContaining({ orderId: '2093000000000000008', inboundId: '2093000000000000009', inboundCode: 'NYEXX2608310002', fullPackageCount: 10 }),
])
})
it('normalizes missing and blank member inbound codes without exposing technical ids as fallbacks', async () => {
const incompleteGroup = {
...group,
members: [
{ ...group.members[0], inboundCode: undefined },
{ ...group.members[1], inboundCode: null },
{ ...group.members[1], inboundId: 2093000000000000012n, inboundCode: ' ' },
{ ...group.members[1], inboundId: 2093000000000000013n, inboundCode: ' NYEXX2608310003 ' },
],
}
vi.spyOn(http, 'post').mockResolvedValue({ code: '200', message: 'ok', data: incompleteGroup })
const result = await createPlatformCoLoadGroup(['2093000000000000005', '2093000000000000008'])
expect(result.members.map((member) => member.inboundCode)).toEqual(['', '', '', 'NYEXX2608310003'])
expect(result.members.map((member) => member.inboundCode)).not.toContain('2093000000000000012')
})
})
+28 -15
View File
@@ -6,7 +6,6 @@ export interface CoLoadGroupMember {
tenantId: string
orderId: string
inboundId: string
inboundCode: string
fullPackageCount: number
}
@@ -24,21 +23,31 @@ export interface CoLoadGroup {
updatedAt: string
}
export interface OrderCoLoadGroupInfo {
orderId: string
group: CoLoadGroup
export interface CoLoadBusinessMember {
inboundCode: string
}
export interface CoLoadBusinessSummary {
status: CoLoadGroupStatus
memberCount: number
members: CoLoadBusinessMember[]
}
type RawId = string | number
type RawCoLoadGroupMember = Omit<CoLoadGroupMember, 'tenantId' | 'orderId' | 'inboundId'> & {
tenantId: RawId
orderId: RawId
inboundId: RawId
}
type RawCoLoadGroup = Omit<CoLoadGroup, 'groupId' | 'warehouseId' | 'lockedPlanId' | 'members'> & {
groupId: RawId
warehouseId: RawId
lockedPlanId: RawId | null
members: Array<Omit<CoLoadGroupMember, 'tenantId' | 'orderId' | 'inboundId'> & { tenantId: RawId; orderId: RawId; inboundId: RawId }>
members: RawCoLoadGroupMember[]
}
type RawOrderCoLoadGroupInfo = Omit<OrderCoLoadGroupInfo, 'orderId' | 'group'> & {
orderId: RawId
group: RawCoLoadGroup
type RawCoLoadBusinessSummary = Omit<CoLoadBusinessSummary, 'memberCount' | 'members'> & {
memberCount: number | string
members: Array<{ inboundCode?: string | null }>
}
const basePath = '/platform/v1/first-leg/coload-groups'
@@ -81,13 +90,17 @@ export async function cancelPlatformCoLoadGroup(groupId: string, expectedVersion
return normalizeGroup(unwrapApiResponse(response))
}
export async function batchQueryPlatformCoLoadGroups(orderIds: string[]) {
const response = await http.post<ApiEnvelope<RawOrderCoLoadGroupInfo[]>, ApiEnvelope<RawOrderCoLoadGroupInfo[]>>(
`${basePath}/batch-query`,
{ orderIds },
export async function getPlatformCoLoadGroupByInboundCode(inboundCode: string) {
const response = await http.get<ApiEnvelope<RawCoLoadBusinessSummary>, ApiEnvelope<RawCoLoadBusinessSummary>>(
`${basePath}/by-inbound-code/${encodeURIComponent(inboundCode)}`,
)
return unwrapApiResponse(response).map((item) => ({
orderId: String(item.orderId),
group: normalizeGroup(item.group),
const raw = unwrapApiResponse(response)
const members = (raw.members || []).map((member) => ({
inboundCode: typeof member.inboundCode === 'string' ? member.inboundCode.trim() : '',
}))
return {
status: raw.status,
memberCount: Number(raw.memberCount),
members,
} satisfies CoLoadBusinessSummary
}
@@ -75,6 +75,12 @@ export interface UnifiedOrderRelationSummary {
childCount: number
}
export interface UnifiedOrderCoLoadGroupSummary {
status: string
memberCount: number
memberInboundCodes: string[]
}
export interface UnifiedOrderResource {
orderId: number | string
tenantId: number | string
@@ -103,6 +109,7 @@ export interface UnifiedOrderResource {
loading: UnifiedOrderLoadingSummary | null
delivery: UnifiedOrderDeliverySummary | null
transport: UnifiedOrderTransportSummary | null
coLoadGroup: UnifiedOrderCoLoadGroupSummary | null
createdAt: string | null
updatedAt: string | null
expectedArrivalAt: string | null
@@ -368,6 +375,13 @@ function normalizeRow(raw: UnifiedOrderResource): UnifiedOrderResource {
evidenceCount: nullableInteger(raw.loading.evidenceCount),
} : null,
transport: raw.transport ? { ...raw.transport } : null,
coLoadGroup: raw.coLoadGroup ? {
status: String(raw.coLoadGroup.status || ''),
memberCount: integer(raw.coLoadGroup.memberCount, 0),
memberInboundCodes: (raw.coLoadGroup.memberInboundCodes || [])
.map((value) => typeof value === 'string' ? value.trim() : '')
.filter(Boolean),
} : null,
}
}
+3 -2
View File
@@ -5,13 +5,14 @@ export {
type UnifiedOrderResource,
} from './api/unifiedOrders'
export {
batchQueryPlatformCoLoadGroups,
cancelPlatformCoLoadGroup,
createPlatformCoLoadGroup,
getPlatformCoLoadGroupByInboundCode,
type CoLoadBusinessMember,
type CoLoadBusinessSummary,
type CoLoadGroup,
type CoLoadGroupMember,
type CoLoadGroupStatus,
type OrderCoLoadGroupInfo,
} from './api/coLoadGroups'
export {
@@ -102,7 +102,7 @@ describe('UnifiedOrdersView co-load group behavior', () => {
expect(wrapper.text()).toContain('同柜组 · 2 票 · 未锁定')
expect(wrapper.text()).not.toContain('CLG-9001')
await wrapper.get('[aria-label="查看同柜组 · 2 票 · 未锁定成员"]').trigger('click')
expect(wrapper.text()).toContain('3 个入仓码')
expect(wrapper.text()).toContain('3 个成员')
expect(wrapper.text()).toContain('13 箱')
expect(wrapper.text()).toContain('IN-1')
expect(wrapper.text()).toContain('IN-1-B')
@@ -116,4 +116,23 @@ describe('UnifiedOrdersView co-load group behavior', () => {
expect(cancelPlatformCoLoadGroup).toHaveBeenCalledWith('9001', 0, '计划调整')
expect(ElMessageBox.prompt).toHaveBeenCalledWith(expect.stringContaining('不支持单独移除成员'), '取消同柜不可拆组', expect.any(Object))
})
it.each([
['undefined', undefined],
['null', null],
['blank', ' '],
])('keeps the member dialog readable when a normalized inbound code is %s', async (_case, inboundCode) => {
const incompleteGroup = {
...group,
members: [{ ...group.members[0], inboundCode: inboundCode as unknown as string }, group.members[1]],
}
vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue(rows.map((row) => ({ orderId: row.orderId, group: incompleteGroup })))
const wrapper = mountView()
await flushPromises()
await wrapper.get('[aria-label="查看同柜组 · 2 票 · 未锁定成员"]').trigger('click')
expect(wrapper.text()).toContain('同柜组成员入仓码尚未返回,请刷新后重试')
expect(wrapper.text()).not.toContain('CLG-9001')
expect(wrapper.text()).not.toContain('ORD-1')
expect(wrapper.text()).not.toContain('5001')
})
})
@@ -188,12 +188,21 @@ describe('UnifiedOrdersView contract', () => {
expect(source).toContain('v-for="member in coLoadDetailMembers"')
expect(source).toContain('<th>入仓码</th><th>箱数</th>')
expect(source).toContain('{{ member.inboundCode }}')
expect(source).toContain('同柜组成员入仓码尚未返回,请刷新后重试')
expect(source).toContain('coLoadDetailHasMissingInboundCodes')
expect(source).not.toContain('visibleInboundCode')
expect(source).not.toContain('visibleOrderNo')
expect(source).not.toContain('<th>订单编码</th>')
expect(source).not.toContain('客户 ID')
})
it('names the cross-domain relationship entry as fulfillment details', () => {
expect(source).toContain('>履约详情</el-button>')
expect(source).toContain('aria-label="查看该入仓码的订单、装柜、尾程与库存关系"')
expect(source).toContain('title="查看该入仓码的订单、装柜、尾程与库存关系"')
expect(source).not.toContain('>关联数据</el-button>')
})
it('keeps editable query values separate from the applied list request', () => {
expect(source).toContain('const appliedFilters = ref<FilterModel>(emptyFilters())')
expect(source).toContain('const activeFilters = appliedFilters.value')
@@ -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, Link2, ListChecks, MoreHorizontal, PackageOpen, Ruler, SlidersHorizontal, StickyNote, Unlink, WalletCards } from '@lucide/vue'
import { ArrowLeft, Box, ChevronDown, ChevronUp, CircleCheck, Eye, GitBranch, History, ListChecks, MoreHorizontal, PackageOpen, Ruler, SlidersHorizontal, StickyNote, WalletCards } from '@lucide/vue'
import { useRoute, useRouter } from 'vue-router'
import {
getPlatformUnifiedOrder,
@@ -12,15 +12,11 @@ import {
listPlatformUnifiedOrders,
unifiedOrderStatusOptions,
type UnifiedOrderDetailResource,
type UnifiedOrderCoLoadGroupSummary,
type UnifiedOrderMainStatus,
type UnifiedOrderResource,
} from '@/modules/unified-orders/api/unifiedOrders'
import {
batchQueryPlatformCoLoadGroups,
cancelPlatformCoLoadGroup,
createPlatformCoLoadGroup,
type CoLoadGroup,
} from '@/modules/unified-orders/api/coLoadGroups'
import { createPlatformCoLoadGroup, getPlatformCoLoadGroupByInboundCode, type CoLoadBusinessSummary, type CoLoadGroup } from '@/modules/unified-orders/api/coLoadGroups'
import OrderFulfillmentTreePanel from '@/modules/unified-orders/components/OrderFulfillmentTreePanel.vue'
import InboundFeeDetailManager from '@/modules/unified-orders/components/InboundFeeDetailManager.vue'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
@@ -36,7 +32,6 @@ import DetailPageLayout from '@/shared/components/DetailPageLayout.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import LineClampText from '@/shared/components/LineClampText.vue'
import InboundCodeRelationshipDialog from '@/shared/components/InboundCodeRelationshipDialog.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
import StatusBadge from '@/shared/components/StatusBadge.vue'
import {
@@ -129,9 +124,12 @@ const approvalSaving = ref(false)
const batchApprovalSaving = ref(false)
const selectedApprovalOrders = ref<UnifiedOrderResource[]>([])
const selectedOrders = ref<UnifiedOrderResource[]>([])
const coLoadGroupsByOrderId = ref(new Map<string, CoLoadGroup>())
const coLoadCreateOpen = ref(false)
const coLoadDetailGroup = ref<CoLoadGroup | null>(null)
const coLoadDetailOpen = ref(false)
const coLoadDetailInboundCode = ref('')
const coLoadDetailSummary = ref<CoLoadBusinessSummary | null>(null)
const coLoadDetailLoading = ref(false)
const coLoadDetailError = ref<ApiErrorDetails | null>(null)
const coLoadSaving = ref(false)
const coLoadError = ref<ApiErrorDetails | null>(null)
const approvalOrder = ref<UnifiedOrderResource | null>(null)
@@ -141,8 +139,6 @@ const noteContent = ref('')
const noteOrder = ref<UnifiedOrderResource | null>(null)
const relationOpen = ref(false)
const relationOrder = ref<UnifiedOrderResource | null>(null)
const inboundRelationshipDialogOpen = ref(false)
const inboundRelationshipDialogCode = ref('')
const measurementDetail = ref<InboundMeasurementDetail | null>(null)
const measurementLoading = ref(false)
const measurementError = ref<ApiErrorDetails | null>(null)
@@ -709,7 +705,6 @@ async function loadWarehouses() {
async function loadOrders() {
selectedApprovalOrders.value = []
selectedOrders.value = []
coLoadGroupsByOrderId.value = new Map()
loading.value = true
loadError.value = null
coLoadError.value = null
@@ -739,14 +734,6 @@ async function loadOrders() {
})
records.value = result.records
total.value = result.total
if (can('platform:firstleg:smart-loading:assign') && result.records.length) {
try {
const groups = await batchQueryPlatformCoLoadGroups(result.records.map((row) => String(row.orderId)))
coLoadGroupsByOrderId.value = new Map(groups.map((item) => [item.orderId, item.group]))
} catch (error) {
coLoadError.value = getApiErrorDetails(error, '同柜不可拆组信息加载失败')
}
}
} catch (error) {
records.value = []
total.value = 0
@@ -789,40 +776,55 @@ function handleOrderSelectionChange(rows: UnifiedOrderResource[]) {
selectedApprovalOrders.value = rows.filter(canApprove)
}
function openInboundRelationship(row: UnifiedOrderResource) {
const code = row.inboundCode?.trim()
if (!code) return
inboundRelationshipDialogCode.value = code
inboundRelationshipDialogOpen.value = true
}
function coLoadGroup(row: UnifiedOrderResource) {
return coLoadGroupsByOrderId.value.get(String(row.orderId)) || null
}
function coLoadGroupOrderCount(group: CoLoadGroup) {
return new Set(group.members.map((member) => member.orderId)).size
return row.coLoadGroup || null
}
function coLoadGroupMemberLabel(group: CoLoadGroup) {
const orderCount = coLoadGroupOrderCount(group)
const orderCount = new Set(group.members.map((member) => member.orderId)).size
return group.members.length === orderCount
? `${orderCount} 票`
: `${orderCount} 票 · ${group.members.length} 个入仓片段`
}
function coLoadGroupStatusLabel(group: CoLoadGroup) {
function coLoadGroupStatusLabel(group: { status: string }) {
return group.status === 'ACTIVE' ? '未锁定' : group.status === 'LOCKED' ? '已锁定' : group.status === 'CONSUMED' ? '已消费' : '已取消'
}
function coLoadGroupSummary(group: CoLoadGroup) {
return `同柜组 · ${coLoadGroupOrderCount(group)} 票 · ${coLoadGroupStatusLabel(group)}`
function coLoadGroupSummary(group: UnifiedOrderCoLoadGroupSummary | CoLoadBusinessSummary) {
return `同柜组 · ${group.memberCount} 票 · ${coLoadGroupStatusLabel(group)}`
}
const coLoadDetailMembers = computed(() => coLoadDetailGroup.value?.members.filter((member) => member.inboundCode.trim()) || [])
function hasCoLoadMemberInboundCode(member: CoLoadBusinessSummary['members'][number]) {
return typeof member.inboundCode === 'string' && Boolean(member.inboundCode.trim())
}
function openCoLoadDetail(group: CoLoadGroup) {
coLoadDetailGroup.value = group
const coLoadDetailMembers = computed(() => coLoadDetailSummary.value?.members.filter(hasCoLoadMemberInboundCode) || [])
const coLoadDetailHasMissingInboundCodes = computed(() => Boolean(coLoadDetailSummary.value)
&& (coLoadDetailMembers.value.length !== coLoadDetailSummary.value!.memberCount
|| coLoadDetailSummary.value!.members.some((member) => !hasCoLoadMemberInboundCode(member))))
async function loadCoLoadDetail() {
const inboundCode = coLoadDetailInboundCode.value
if (!inboundCode || coLoadDetailLoading.value) return
coLoadDetailLoading.value = true
coLoadDetailError.value = null
coLoadDetailSummary.value = null
try {
coLoadDetailSummary.value = await getPlatformCoLoadGroupByInboundCode(inboundCode)
} catch (error) {
coLoadDetailError.value = getApiErrorDetails(error, '同柜组成员加载失败,请刷新后重试')
} finally {
coLoadDetailLoading.value = false
}
}
function openCoLoadDetail(row: UnifiedOrderResource) {
coLoadDetailInboundCode.value = row.inboundCode?.trim() || ''
coLoadDetailOpen.value = true
coLoadDetailSummary.value = null
coLoadDetailError.value = coLoadDetailInboundCode.value ? null : getApiErrorDetails(new Error('同柜组成员入仓码尚未返回'), '同柜组成员入仓码尚未返回,请刷新后重试')
if (coLoadDetailInboundCode.value) void loadCoLoadDetail()
}
function openCoLoadCreate() {
@@ -847,31 +849,6 @@ async function createCoLoadGroup() {
}
}
async function cancelCoLoadGroup(row: UnifiedOrderResource) {
const group = coLoadGroup(row)
if (!group || group.status !== 'ACTIVE' || coLoadSaving.value) return
let reason = ''
try {
const result = await ElMessageBox.prompt(
`将整组取消(${coLoadGroupMemberLabel(group)})。不支持单独移除成员;如需调整,请取消后重新建组。`,
'取消同柜不可拆组',
{ confirmButtonText: '确认整组取消', cancelButtonText: '返回', inputPlaceholder: '取消原因(选填)', inputType: 'textarea' },
)
reason = result.value
} catch { return }
coLoadSaving.value = true
coLoadError.value = null
try {
await cancelPlatformCoLoadGroup(group.groupId, group.version, reason)
ElMessage.success('同柜不可拆组已整组取消')
await loadOrders()
} catch (error) {
coLoadError.value = getApiErrorDetails(error, '取消同柜不可拆组失败')
} finally {
coLoadSaving.value = false
}
}
async function batchApproveOrders() {
const selected = [...selectedApprovalOrders.value]
if (!selected.length || batchApprovalSaving.value) return
@@ -925,19 +902,17 @@ function clearMeasurementOrder() {
measurementOrder.value = null
}
type UnifiedOrderRowAction = 'note' | 'approve' | 'measurement' | 'cancelCoLoad'
type UnifiedOrderRowAction = 'note' | 'approve' | 'measurement'
const unifiedOrderRowActionIcons: Record<UnifiedOrderRowAction, Component> = {
note: StickyNote,
approve: CircleCheck,
measurement: Ruler,
cancelCoLoad: Unlink,
}
function unifiedOrderSecondaryActions(row: UnifiedOrderResource): UnifiedOrderRowAction[] {
return [
...(can('platform:order:note') ? ['note' as const] : []),
...(canApprove(row) ? ['approve' as const] : []),
...(row.mainStatus === 'WAIT_MEASURE' && row.inboundId && can('platform:firstleg:inbound:measure:view') ? ['measurement' as const] : []),
...(can('platform:firstleg:smart-loading:assign') && coLoadGroup(row)?.status === 'ACTIVE' ? ['cancelCoLoad' as const] : []),
]
}
function directUnifiedOrderActions(row: UnifiedOrderResource) {
@@ -952,17 +927,15 @@ function moreUnifiedOrderActionsLabel(row: UnifiedOrderResource) {
function unifiedOrderActionLabel(action: UnifiedOrderRowAction) {
if (action === 'note') return '添加备注'
if (action === 'approve') return '审核通过'
if (action === 'cancelCoLoad') return '取消同柜组'
return '测量作业'
}
function unifiedOrderActionType(action: UnifiedOrderRowAction) {
return action === 'approve' ? 'success' : action === 'cancelCoLoad' ? 'danger' : 'primary'
return action === 'approve' ? 'success' : 'primary'
}
function runMoreAction(command: string | number | object, row: UnifiedOrderResource) {
if (command === 'note') openNoteDialog(row)
if (command === 'approve') openApproval(row)
if (command === 'measurement') openMeasurement(row)
if (command === 'cancelCoLoad') void cancelCoLoadGroup(row)
}
function closeDetail() {
@@ -1361,8 +1334,7 @@ onBeforeUnmount(() => {
<template #inboundCode="{ row }">
<div class="inbound-relation-cell order-code-cell">
<strong class="inbound-code-value" :title="(row as UnifiedOrderResource).inboundCode || '待生成入仓码'">{{ (row as UnifiedOrderResource).inboundCode || '待生成入仓码' }}</strong>
<button v-if="coLoadGroup(row as UnifiedOrderResource)" type="button" class="coload-tag-trigger" :aria-label="`查看${coLoadGroupSummary(coLoadGroup(row as UnifiedOrderResource)!)}成员`" @click.stop="openCoLoadDetail(coLoadGroup(row as UnifiedOrderResource)!)"><el-tag size="small" :type="coLoadGroup(row as UnifiedOrderResource)?.status === 'ACTIVE' ? 'warning' : 'info'">{{ coLoadGroupSummary(coLoadGroup(row as UnifiedOrderResource)!) }}</el-tag></button>
<el-button v-if="(row as UnifiedOrderResource).inboundCode" class="order-relation-link" link type="primary" aria-label="查看入仓码关联数据" @click="openInboundRelationship(row as UnifiedOrderResource)"><Link2 :size="14" />关联数据</el-button>
<button v-if="coLoadGroup(row as UnifiedOrderResource)" type="button" class="coload-tag-trigger" :aria-label="`查看${coLoadGroupSummary(coLoadGroup(row as UnifiedOrderResource)!)}成员`" @click.stop="openCoLoadDetail(row as UnifiedOrderResource)"><el-tag size="small" :type="coLoadGroup(row as UnifiedOrderResource)?.status === 'ACTIVE' ? 'warning' : 'info'">{{ coLoadGroupSummary(coLoadGroup(row as UnifiedOrderResource)!) }}</el-tag></button>
<el-button
v-if="(row as UnifiedOrderResource).relation"
class="order-relation-link"
@@ -1395,16 +1367,18 @@ onBeforeUnmount(() => {
<div class="coload-selection"><span v-for="row in selectedOrders" :key="String(row.orderId)">{{ row.inboundCode || '待生成入仓码' }}</span></div>
<div v-if="coLoadError" class="coload-error" role="alert"><span>{{ coLoadError.message }}</span><ApiErrorMeta :details="coLoadError" /></div>
</AppDialog>
<AppDialog :model-value="Boolean(coLoadDetailGroup)" title="同柜组成员" :show-confirm="false" cancel-text="关闭" width="min(720px, 94vw)" @update:model-value="coLoadDetailGroup = null">
<template v-if="coLoadDetailGroup">
<div class="coload-detail-summary"><el-tag size="small" :type="coLoadDetailGroup.status === 'ACTIVE' ? 'warning' : 'info'">{{ coLoadGroupSummary(coLoadDetailGroup) }}</el-tag><span>{{ coLoadDetailMembers.length }} 个入仓码 · 共 {{ coLoadDetailGroup.fullPackageCount }} 箱</span></div>
<div v-if="coLoadDetailMembers.length" class="coload-detail-scroll">
<AppDialog v-model="coLoadDetailOpen" title="同柜组成员" :show-confirm="false" cancel-text="关闭" width="min(720px, 94vw)" :loading="coLoadDetailLoading">
<LoadErrorState v-if="coLoadDetailError" title="同柜组成员加载失败" :message="coLoadDetailError.message" :loading="coLoadDetailLoading" @retry="loadCoLoadDetail"><template #details><ApiErrorMeta :details="coLoadDetailError" /></template></LoadErrorState>
<template v-else-if="coLoadDetailSummary">
<div class="coload-detail-summary"><el-tag size="small" :type="coLoadDetailSummary.status === 'ACTIVE' ? 'warning' : 'info'">{{ coLoadGroupSummary(coLoadDetailSummary) }}</el-tag><span>{{ coLoadDetailSummary.memberCount }} 个成员</span></div>
<el-alert v-if="coLoadDetailHasMissingInboundCodes" type="error" :closable="false" show-icon title="同柜组成员入仓码尚未返回,请刷新后重试" />
<div v-else-if="coLoadDetailMembers.length" class="coload-detail-scroll">
<table class="coload-detail-table">
<thead><tr><th>入仓码</th><th>箱数</th></tr></thead>
<tbody><tr v-for="member in coLoadDetailMembers" :key="member.inboundId"><td><strong :title="member.inboundCode">{{ member.inboundCode }}</strong></td><td>{{ member.fullPackageCount }} 箱</td></tr></tbody>
<thead><tr><th>入仓码</th></tr></thead>
<tbody><tr v-for="member in coLoadDetailMembers" :key="member.inboundCode"><td><strong :title="member.inboundCode">{{ member.inboundCode }}</strong></td></tr></tbody>
</table>
</div>
<el-empty v-else description="暂无有效入仓码" :image-size="56" />
<el-empty v-else description="暂无同柜组成员" :image-size="56" />
</template>
</AppDialog>
</template>
@@ -1417,7 +1391,6 @@ onBeforeUnmount(() => {
:inbound-code="relationOrder.inboundCode"
/>
</AppDrawer>
<InboundCodeRelationshipDialog v-if="inboundRelationshipDialogOpen" v-model="inboundRelationshipDialogOpen" :inbound-code="inboundRelationshipDialogCode" :can-read-base="access.can('platform:order:list')" :can-read-loading="access.can('platform:firstleg:smart-loading:list')" :can-read-overseas="access.can('platform:overseas-warehouse:inventory:list')" />
<AppDialog v-model="noteOpen" title="添加内部备注" confirm-text="保存备注" :confirm-loading="noteSaving" @confirm="saveNote">
<el-input v-model="noteContent" type="textarea" :rows="5" maxlength="2000" show-word-limit placeholder="请输入仅平台内部可见的备注" aria-label="内部备注内容" />