优化
This commit is contained in:
@@ -2,7 +2,7 @@ import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
|
||||
import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders'
|
||||
|
||||
export interface ReturnStockRow { customerId: string; overseasWarehouseId: string; skuCode: string; productNameZh?: string; totalQuantity: number; availableQuantity: number; looseAvailableQuantity?: number; cartonQuantity: number; updatedAt: string }
|
||||
export interface ReturnStockRow { customerId: string; overseasWarehouseId: string; skuCode: string; productNameZh?: string; totalQuantity: number; availableQuantity: number; relabelLockedQuantity: number; looseAvailableQuantity?: number; cartonQuantity: number; updatedAt: string }
|
||||
export interface ReturnCartonRow { customerId: string; overseasWarehouseId: string; cartonMark: string; sourceReturnNo?: string; sourceUnitType?: 'PALLET' | 'BOX' | 'PARCEL' | string; sourceBatchNo?: string; status: string; fbaCartonMark?: string; destinationWarehouseCode?: string; destinationWarehouseName?: string; relabelNo?: string; relabelStatus?: string; relabelledQuantity?: number; relabelReservedQuantity?: number; skuTypes: number; totalQuantity: number; length?: number; width?: number; height?: number; weight?: number; createdAt: string }
|
||||
export interface ReturnCartonMergeHistory { planNo?: string; sourceCartonMark: string; targetCartonMark: string; returnNo: string; skuCode: string; quantity: number; createdAt: string }
|
||||
export interface ReturnCartonDetail extends ReturnCartonRow { customerId: string; items: Array<{ skuCode: string; productNameZh?: string; quantity: number; availableQuantity?: number }>; mergeHistory?: ReturnCartonMergeHistory[] }
|
||||
|
||||
@@ -1137,7 +1137,7 @@ onMounted(() => { void load() })
|
||||
|
||||
<template v-if="statusTab !== '柜子'" #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderPalletMerge)" plain :disabled="!palletMergeSelectionEditable || actionLoading" @click="submitPalletMerge(true)">合托</el-button><el-button v-if="access.can(permission.lastMileOrderPalletMerge)" plain :disabled="!canCancelPalletMerge || actionLoading" @click="submitPalletMerge(false)">取消合托</el-button><el-button v-if="selectedReturnRows.length" type="warning" @click="openReturnPackingPlan"><PackagePlus :size="16" />创建退货合箱计划({{ selectedReturnRows.length }})</el-button><el-button v-if="access.can(permission.lastMileOrderExport) && access.can('platform:download:list')" plain :loading="exportLoading" @click="exportOrders"><Download :size="16" />导出订单</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || hasSelectedRejectedReturn() || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.inboundOrderCreate) && selectedRows.length === 1 && canGenerateInboundPlan(selectedRows[0])" type="primary" plain :disabled="hasSelectedInboundPlan() || actionLoading" @click="openInboundPlan()">生成入库计划</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" :disabled="actionLoading" @click="openContainerConversion">按柜批量生成</el-button></template>
|
||||
<template #relabelOrderNo="{ row }"><div v-for="application in row.relabelApplications" :key="application.relabelNo" class="relabel-suborder">{{ application.relabelNo }}</div><span v-if="!row.relabelApplications?.length">{{ row.relabelOrderNo }}</span></template>
|
||||
<template #relabelStatus="{ row }"><div v-for="application in row.relabelApplications" :key="application.relabelNo" class="relabel-suborder">{{ application.statusLabel }} · {{ application.quantity }} 件</div><span v-if="!row.relabelApplications?.length">{{ row.relabelStatus }}</span></template>
|
||||
<template #relabelStatus="{ row }"><div v-for="application in row.relabelApplications" :key="application.relabelNo" class="relabel-suborder">{{ application.statusLabel }}</div><span v-if="!row.relabelApplications?.length">{{ row.relabelStatus }}</span></template>
|
||||
<template #actions="{ row }"><RowActions text-actions :actions="lastMileRowActions(row as LastMileOrderListItem)" :more-label="`更多尾程订单操作 · ${(row as LastMileOrderListItem).orderNo || '当前记录'}`" @action="handleLastMileRowAction($event, row as LastMileOrderListItem)" /></template>
|
||||
<template #businessOrderNo="{ row }"><el-button v-if="businessOrderLink(row.businessType, row.businessOrderNo, access.can)" link type="primary" @click="router.push(businessOrderLink(row.businessType, row.businessOrderNo, access.can)!)">{{ row.businessOrderNo }}</el-button><span v-else>{{ row.businessOrderNo }}</span></template>
|
||||
<template #orderNo="{ row }"><OrderReferenceText :value="String(row.orderNo || '')" copyable /></template>
|
||||
|
||||
@@ -25,7 +25,7 @@ vi.mock('../api/relabelOrders', () => ({
|
||||
reviewReturnPackingPlan: vi.fn(), cancelReturnPackingPlan: vi.fn(),
|
||||
}))
|
||||
const wrappers: VueWrapper[] = []
|
||||
const stock = { customerId: 'customer-1', overseasWarehouseId: 'warehouse-1', skuCode: 'SKU-TEST', totalQuantity: 8, availableQuantity: 6, cartonQuantity: 1, updatedAt: '2026-09-30' }
|
||||
const stock = { customerId: 'customer-1', overseasWarehouseId: 'warehouse-1', skuCode: 'SKU-TEST', totalQuantity: 8, availableQuantity: 6, relabelLockedQuantity: 2, cartonQuantity: 1, updatedAt: '2026-09-30' }
|
||||
const carton = { customerId: 'customer-1', overseasWarehouseId: 'warehouse-1', cartonMark: 'RETURN-BOX-1', status: 'AVAILABLE', skuTypes: 1, totalQuantity: 8, createdAt: '2026-09-30' }
|
||||
async function mountView(mode: 'inventory' | 'cartons') {
|
||||
const wrapper = mount(ReturnInventoryManagementView, {
|
||||
@@ -56,6 +56,12 @@ afterEach(() => {
|
||||
})
|
||||
|
||||
describe('ReturnInventoryManagementView shared list', () => {
|
||||
it('退货库存展示服务端换标占用列', async () => {
|
||||
const wrapper = await mountView('inventory')
|
||||
const columns = wrapper.findComponent(DataTable).props('columns')
|
||||
expect(columns).toEqual(expect.arrayContaining([expect.objectContaining({ prop: 'relabelLockedQuantity', label: '换标占用(件)' })]))
|
||||
expect(wrapper.findComponent(DataTable).props('data')[0]).toEqual(expect.objectContaining({ relabelLockedQuantity: 2 }))
|
||||
})
|
||||
it('keeps partial quantities bound to each physical parcel and box when they share a SKU', async () => {
|
||||
vi.mocked(listReturnPackingSources).mockResolvedValue({ records: [
|
||||
{ ...carton, cartonMark: 'PARCEL-A', sourceUnitType: 'PARCEL', sourceReturnNo: 'RETURN-1', items: [{ skuCode: 'SKU-A', quantity: 5, availableQuantity: 5 }] },
|
||||
@@ -272,10 +278,11 @@ describe('ReturnInventoryManagementView shared list', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('箱列表分别显示后端实际完成量与未完成申请占用量', async () => {
|
||||
it('箱列表不展示换标单号和换标进度', async () => {
|
||||
vi.mocked(listReturnCartons).mockResolvedValue({ records: [{ ...carton, relabelStatus: 'PARTIALLY_COMPLETED', relabelledQuantity: 3, relabelReservedQuantity: 2 }], page: 1, size: 20, total: 1, pages: 1 })
|
||||
const wrapper = await mountView('cartons')
|
||||
expect(wrapper.text()).toContain('部分完成')
|
||||
expect(wrapper.text()).toContain('实际完成 3 件')
|
||||
expect(wrapper.text()).toContain('处理中占用 2 件')
|
||||
expect(wrapper.text()).not.toContain('换标单号')
|
||||
expect(wrapper.text()).not.toContain('换标进度')
|
||||
expect(wrapper.text()).not.toContain('实际完成 3 件')
|
||||
expect(wrapper.text()).not.toContain('处理中占用 2 件')
|
||||
})
|
||||
|
||||
@@ -427,6 +427,7 @@ const stockColumns: DataTableColumn[] = [
|
||||
prop: "availableQuantity",
|
||||
align: "right",
|
||||
},
|
||||
{ key: "relabelLockedQuantity", label: "换标占用(件)", prop: "relabelLockedQuantity", minWidth: 140, align: "right" },
|
||||
{ key: "updatedAt", label: "更新时间", prop: "updatedAt", minWidth: 180 },
|
||||
];
|
||||
const movementColumns: DataTableColumn[] = [
|
||||
@@ -489,8 +490,6 @@ const cartonColumns: DataTableColumn[] = [
|
||||
minWidth: 180,
|
||||
},
|
||||
{ key: "carton-6", label: "目的仓", minWidth: 180, slotName: "carton-6" },
|
||||
{ key: "relabelNo", label: "换标单号", prop: "relabelNo", minWidth: 200 },
|
||||
{ key: "carton-8", label: "换标进度", minWidth: 290, slotName: "carton-8" },
|
||||
{ key: "carton-9", label: "状态", width: 100, slotName: "carton-9" },
|
||||
{ key: "skuTypes", label: "SKU种类", prop: "skuTypes", align: "right" },
|
||||
{
|
||||
@@ -734,9 +733,6 @@ const tableColumns = computed(() =>
|
||||
<template #carton-6="{ row }">{{
|
||||
row.destinationWarehouseCode || row.destinationWarehouseName || "—"
|
||||
}}</template>
|
||||
<template #carton-8="{ row }">{{
|
||||
returnRelabelStatusLabel(row.relabelStatus)
|
||||
}}|实际完成 {{ row.relabelledQuantity ?? "—" }} 件|处理中占用 {{ row.relabelReservedQuantity ?? "—" }} 件</template>
|
||||
<template #carton-9="{ row }">{{ statusLabel(row.status) }}</template>
|
||||
<template #carton-12="{ row }">{{
|
||||
row.length ? `${row.length}×${row.width}×${row.height} cm` : "—"
|
||||
|
||||
Reference in New Issue
Block a user