优化
This commit is contained in:
@@ -177,6 +177,7 @@ export interface DispatchPdaItemDto {
|
||||
destinationWarehouseCode?: string | null
|
||||
destinationWarehouseName?: string | null
|
||||
fbaWarehouseCode?: string | null
|
||||
warehouseRouteLabel?: string | null
|
||||
scheduledPackages: number
|
||||
pickedPackages: number
|
||||
positions: DispatchPdaPositionDto[]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { convertLastMileOrderToInboundPlan, getLastMileOrder, listLastMileOrders, setLastMileOrderDetained, setLastMileOrderPalletMergeRequired, transferLastMileOrders } from './lastMileOrders'
|
||||
import { convertLastMileOrderToInboundPlan, downloadLastMileOrders, getLastMileOrder, listLastMileOrders, setLastMileOrderDetained, setLastMileOrderPalletMergeBatch, setLastMileOrderPalletMergeRequired, transferLastMileOrders } from './lastMileOrders'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn(), put: vi.fn(), post: vi.fn() } }))
|
||||
|
||||
@@ -47,6 +47,38 @@ describe('last-mile order overseas API', () => {
|
||||
expect(overseasHttp.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/destination', expect.objectContaining({ orderIds: ['190000000000000099'] }))
|
||||
})
|
||||
|
||||
it('returns the exported CSV blob without reading data twice', async () => {
|
||||
const blob = new Blob(['orders'], { type: 'text/csv' })
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue(blob)
|
||||
|
||||
await expect(downloadLastMileOrders({ orderNo: 'LM-1' })).resolves.toBe(blob)
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders/export', {
|
||||
params: { orderNo: 'LM-1' }, responseType: 'blob',
|
||||
})
|
||||
})
|
||||
|
||||
it('exports all authorized orders without pagination or empty filters', async () => {
|
||||
const blob = new Blob(['orders'], { type: 'text/csv' })
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue(blob)
|
||||
|
||||
await downloadLastMileOrders({ page: 1, size: 10, orderNo: '', createdFrom: undefined })
|
||||
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders/export', {
|
||||
params: {}, responseType: 'blob',
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects a JSON business error instead of saving it as CSV', async () => {
|
||||
const blob = new Blob([JSON.stringify({
|
||||
code: 'S0500', message: '系统内部错误', data: null, requestId: 'req-1', traceId: 'trace-1',
|
||||
})], { type: 'application/json' })
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue(blob)
|
||||
|
||||
await expect(downloadLastMileOrders({})).rejects.toMatchObject({
|
||||
code: 'S0500', message: '系统内部错误', requestId: 'req-1', traceId: 'trace-1',
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the order hold endpoint with the required operation remark', async () => {
|
||||
vi.mocked(overseasHttp.put).mockResolvedValue({ code: '200', message: 'success', data: null })
|
||||
await setLastMileOrderDetained('190000000000000099', { detained: true, remark: '等待质检确认' })
|
||||
@@ -63,6 +95,14 @@ describe('last-mile order overseas API', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('marks selected orders as one visible pallet-merge group', async () => {
|
||||
vi.mocked(overseasHttp.put).mockResolvedValue({ code: '200', message: 'success', data: null })
|
||||
await setLastMileOrderPalletMergeBatch(['11', '12'], true)
|
||||
expect(overseasHttp.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/pallet-merge-required/batch', {
|
||||
orderIds: ['11', '12'], palletMergeRequired: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the inbound-plan conversion endpoint without customerId', async () => {
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', message: 'success', data: {} })
|
||||
await convertLastMileOrderToInboundPlan({ orderId: '190000000000000099' })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import { ApiResponseError, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
|
||||
export interface OverseasPageResult<T> {
|
||||
records: T[]
|
||||
@@ -74,7 +74,7 @@ export interface LastMileOrderSummaryDto {
|
||||
palletMergeFlag?: string | null
|
||||
/** Optional grouping facts returned by newer last-leg services. */
|
||||
palletMergeBatchId?: string | null
|
||||
palletMergeOrderNos?: string[] | null
|
||||
palletMergeInboundNos?: string[] | null
|
||||
currentStatus?: string | null
|
||||
privateRemark?: string | null
|
||||
customerRemark?: string | null
|
||||
@@ -188,8 +188,26 @@ export async function getLastMileOrder(orderId: string) {
|
||||
}
|
||||
|
||||
export async function downloadLastMileOrders(query: Partial<LastMileOrderQuery>) {
|
||||
const response = await overseasHttp.get<Blob>('/platform/v1/last-leg/orders/export', { params: query, responseType: 'blob' })
|
||||
return response.data
|
||||
const { page: _page, size: _size, ...filters } = query
|
||||
const params = Object.fromEntries(
|
||||
Object.entries(filters).filter(([, value]) => value !== undefined && value !== null && value !== ''),
|
||||
)
|
||||
const blob = await overseasHttp.get<Blob, Blob>('/platform/v1/last-leg/orders/export', { params, responseType: 'blob' })
|
||||
if (!blob.type.toLowerCase().includes('json')) return blob
|
||||
let error: Partial<ApiEnvelope<unknown>>
|
||||
try {
|
||||
error = JSON.parse(await blob.text()) as Partial<ApiEnvelope<unknown>>
|
||||
} catch {
|
||||
throw new ApiResponseError('导出接口返回了非 CSV 内容', 'INVALID_EXPORT_RESPONSE')
|
||||
}
|
||||
throw new ApiResponseError(
|
||||
error.message || '尾程订单导出失败',
|
||||
error.code || 'INVALID_EXPORT_RESPONSE',
|
||||
undefined,
|
||||
error.data,
|
||||
error.requestId,
|
||||
error.traceId,
|
||||
)
|
||||
}
|
||||
|
||||
export async function createLastMileOrderFee(orderId: string, payload: CreateLastMileFeePayload) {
|
||||
@@ -226,3 +244,10 @@ export async function setLastMileOrderPalletMergeRequired(orderId: string, paylo
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function setLastMileOrderPalletMergeBatch(orderIds: string[], palletMergeRequired: boolean) {
|
||||
const response = await overseasHttp.put<ApiEnvelope<void>, ApiEnvelope<void>>(
|
||||
'/platform/v1/last-leg/orders/pallet-merge-required/batch', { orderIds, palletMergeRequired },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@ describe('last-mile order presentation adapter', () => {
|
||||
expect(row.orderType).toBe(expected)
|
||||
})
|
||||
|
||||
it('shows the actual related order numbers returned after pallet merge', () => {
|
||||
it('shows related inbound numbers instead of the shared tail-leg order number', () => {
|
||||
const row = toLastMileOrderListItem({
|
||||
id: '11', customerId: '100', orderNo: 'LMO-1', palletMergeFlag: 'MERGED',
|
||||
palletMergeBatchId: 'PMG-1', palletMergeOrderNos: ['LMO-2', 'LMO-3'],
|
||||
palletMergeBatchId: 'PMG-1', palletMergeInboundNos: ['NYEXX2608280001', 'NYEXX2608280002'],
|
||||
})
|
||||
|
||||
expect(row.palletMergeRelation).toBe('LMO-2、LMO-3')
|
||||
expect(row.palletMergeRelation).toBe('NYEXX2608280001、NYEXX2608280002')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -99,8 +99,8 @@ export function toLastMileOrderListItem(dto: LastMileOrderSummaryDto): LastMileO
|
||||
relabelStatus: lastMileStatusLabel(dto.relabelStatus),
|
||||
consolidated: palletMergeLabel(dto.palletMergeFlag),
|
||||
palletMergeFlag: String(dto.palletMergeFlag ?? '').trim(),
|
||||
palletMergeRelation: Array.isArray(dto.palletMergeOrderNos) && dto.palletMergeOrderNos.length
|
||||
? dto.palletMergeOrderNos.map((value) => text(value)).join('、')
|
||||
palletMergeRelation: Array.isArray(dto.palletMergeInboundNos) && dto.palletMergeInboundNos.length
|
||||
? dto.palletMergeInboundNos.map((value) => text(value)).join('、')
|
||||
: dto.palletMergeBatchId ? `批次 ${text(dto.palletMergeBatchId)}` : '—',
|
||||
status: lastMileStatusLabel(dto.currentStatus),
|
||||
internalRemark: text(dto.privateRemark),
|
||||
|
||||
@@ -187,7 +187,7 @@ onMounted(load)
|
||||
<div v-if="pdaTask" v-loading="pdaLoading" class="pda-body">
|
||||
<div class="pda-meta">任务号:{{ pdaTask.taskNo }} 状态:<strong>{{ dispatchStatus(pdaTask.status) }}</strong> 仓库:{{ text(pdaTask.warehouseId) }}</div>
|
||||
<el-table :data="pdaTask.items || []" size="small" border @row-click="selectPdaItem">
|
||||
<el-table-column label="托盘" prop="palletNo" min-width="140" /><el-table-column label="目的仓" prop="fbaWarehouseCode" min-width="110" /><el-table-column label="计划箱数" prop="scheduledPackages" width="100" /><el-table-column label="已拣箱数" prop="pickedPackages" width="100" />
|
||||
<el-table-column label="托盘" prop="palletNo" min-width="140" /><el-table-column label="转仓提示" min-width="150"><template #default="{ row }"><el-tag v-if="row.warehouseRouteLabel" type="warning" effect="plain">{{ row.warehouseRouteLabel }}</el-tag><span v-else>{{ text(row.fbaWarehouseCode || row.destinationWarehouseCode) }}</span></template></el-table-column><el-table-column label="计划箱数" prop="scheduledPackages" width="100" /><el-table-column label="已拣箱数" prop="pickedPackages" width="100" />
|
||||
<el-table-column label="库位(可用)" min-width="220"><template #default="{ row }"><el-button v-for="position in row.positions || []" :key="position.id" link type="primary" @click.stop="selectPdaRow(row); pickForm.positionId = Number(position.id)">{{ position.id }}({{ position.availablePackages }})</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
<div class="pick-form"><span class="pick-label">拣货明细:{{ pickForm.itemId || '未选择' }}</span><el-input-number v-model="pickForm.positionId" :min="1" controls-position="right" placeholder="库位ID" /><el-input-number v-model="pickForm.packages" :min="1" controls-position="right" placeholder="箱数" @change="(value) => { pickForm.productQuantity = Number(value || 1) }" /><el-input v-model="pickForm.idempotencyKey" placeholder="拣货幂等键" /><el-button type="success" :loading="pdaMutating" @click="submitPick">拣货并扣减库存</el-button></div>
|
||||
|
||||
@@ -12,12 +12,12 @@ import ListPageLayout from '@/shared/components/ListPageLayout.vue'
|
||||
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
||||
import OperationErrorToast from '@/shared/components/OperationErrorToast.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import { convertLastMileOrderToInboundPlan, listLastMileOrders, setLastMileOrderDetained, transferLastMileOrders, downloadLastMileOrders } from '../api/lastMileOrders'
|
||||
import { convertLastMileOrderToInboundPlan, listLastMileOrders, setLastMileOrderDetained, setLastMileOrderPalletMergeBatch, transferLastMileOrders, downloadLastMileOrders } from '../api/lastMileOrders'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { overseasWarehousePermissions as permission } from '../permissions'
|
||||
import { toLastMileOrderListItem } from '../lastMilePresentation'
|
||||
import type { LastMileOrderListItem } from '../types'
|
||||
import { listReceivingOverseasWarehouses, type ReceivingOverseasWarehouseDto } from '../api/pallets'
|
||||
import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses'
|
||||
import { saveCsv } from '@/modules/overseas-master-data/downloadCsv'
|
||||
|
||||
const rows = ref<LastMileOrderListItem[]>([])
|
||||
@@ -29,16 +29,17 @@ const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
const selectedRows = ref<LastMileOrderListItem[]>([])
|
||||
const cancellableMergeCount = computed(() => selectedRows.value.filter((row) => row.palletMergeFlag === 'REQUIRED').length)
|
||||
const actionLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
async function exportOrders() { exportLoading.value = true; try { const { createdAt: range, ...rest } = filters.value; saveCsv(await downloadLastMileOrders({ ...rest, page: undefined, size: undefined, createdFrom: Array.isArray(range) && range[0] ? `${String(range[0]).slice(0, 10)}T00:00:00` : undefined, createdTo: Array.isArray(range) && range[1] ? `${String(range[1]).slice(0, 10)}T23:59:59` : undefined }) as Blob, '尾程订单.csv') } catch { ElMessage.error('尾程订单导出失败,请重试') } finally { exportLoading.value = false } }
|
||||
async function exportOrders() { exportLoading.value = true; try { const { createdAt: range, ...rest } = filters.value; saveCsv(await downloadLastMileOrders({ ...rest, createdFrom: Array.isArray(range) && range[0] ? `${String(range[0]).slice(0, 10)}T00:00:00` : undefined, createdTo: Array.isArray(range) && range[1] ? `${String(range[1]).slice(0, 10)}T23:59:59` : undefined }) as Blob, '尾程订单.csv') } catch (cause) { ElMessage.error(getApiErrorDetails(cause, '尾程订单导出失败,请重试').message) } finally { exportLoading.value = false } }
|
||||
const actionError = ref<ApiErrorDetails | null>(null)
|
||||
const transferOpen = ref(false)
|
||||
const detainedOpen = ref(false)
|
||||
const detainedTarget = ref<LastMileOrderListItem | null>(null)
|
||||
const detainedRemark = ref('')
|
||||
const transferForm = reactive({ warehouseId: '', warehouseCode: '', warehouseName: '', remark: '' })
|
||||
const warehouses = ref<ReceivingOverseasWarehouseDto[]>([])
|
||||
const warehouses = ref<PlatformWarehouseSummaryResource[]>([])
|
||||
const statusTab = ref<'全部' | '待分配'>('全部')
|
||||
const filters = ref<QueryModel>({ orderNo: '', orderType: '', warehouse: '', inboundCode: '', sourceOrderNo: '', containerNo: '', status: '', transferWarehouseCode: '', abnormal: '', detained: '', createdAt: [] })
|
||||
const fields = computed<QueryField[]>(() => [
|
||||
@@ -69,7 +70,8 @@ const columns: DataTableColumn[] = [
|
||||
{ key: 'actions', label: '操作', width: 270, fixed: 'left', slotName: 'actions' },
|
||||
{ key: 'selection', type: 'selection', width: 48, fixed: 'left' },
|
||||
{ key: 'orderNo', prop: 'orderNo', label: '尾程单号', minWidth: 170 },
|
||||
{ key: 'palletMergeRelation', prop: 'palletMergeRelation', label: '合托关联订单', minWidth: 220, hideable: false },
|
||||
{ key: 'consolidated', prop: 'consolidated', label: '合托标记', width: 100, hideable: false },
|
||||
{ key: 'palletMergeRelation', prop: 'palletMergeRelation', label: '合托关联入仓单', minWidth: 220, hideable: false },
|
||||
{ key: 'warning', prop: 'warning', label: '预警', width: 90 },
|
||||
{ key: 'orderType', prop: 'orderType', label: '订单类型', minWidth: 110 },
|
||||
{ key: 'rejectedAt', prop: 'rejectedAt', label: '拒收时间', minWidth: 150 },
|
||||
@@ -166,6 +168,32 @@ async function submitDetained() {
|
||||
} catch (error) { actionError.value = getApiErrorDetails(error, target.detained ? '解除暂扣失败,请重试' : '暂扣失败,请重试') }
|
||||
finally { actionLoading.value = false }
|
||||
}
|
||||
async function batchPalletMerge() {
|
||||
const targets = selectedRows.value.filter((row) => row.palletMergeFlag !== 'MERGED')
|
||||
if (!targets.length) { ElMessage.warning('请选择至少 1 条未完成合托的尾程订单'); return }
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定为选中的 ${targets.length} 条尾程订单标记合托吗?PDA 扫描对应箱唛时将显示合托提示。`, '批量合托标记', { type: 'warning', confirmButtonText: '确认标记', cancelButtonText: '返回' })
|
||||
} catch { return }
|
||||
actionLoading.value = true; actionError.value = null
|
||||
try {
|
||||
await setLastMileOrderPalletMergeBatch(targets.map((row) => row.id), true)
|
||||
selectedRows.value = []; ElMessage.success(`已标记 ${targets.length} 条订单合托`); await load()
|
||||
} catch (error) { actionError.value = getApiErrorDetails(error, '批量合托标记失败,请重试') }
|
||||
finally { actionLoading.value = false }
|
||||
}
|
||||
async function cancelBatchPalletMerge() {
|
||||
const targets = selectedRows.value.filter((row) => row.palletMergeFlag === 'REQUIRED')
|
||||
if (!targets.length) { ElMessage.warning('请选择至少 1 条待合托订单'); return }
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定取消选中的 ${targets.length} 条订单合托标记吗?`, '取消合托标记', { type: 'warning', confirmButtonText: '确认取消', cancelButtonText: '返回' })
|
||||
} catch { return }
|
||||
actionLoading.value = true; actionError.value = null
|
||||
try {
|
||||
await setLastMileOrderPalletMergeBatch(targets.map((row) => row.id), false)
|
||||
selectedRows.value = []; ElMessage.success(`已取消 ${targets.length} 条订单合托标记`); await load()
|
||||
} catch (error) { actionError.value = getApiErrorDetails(error, '取消合托标记失败,请重试') }
|
||||
finally { actionLoading.value = false }
|
||||
}
|
||||
async function submitTransfer() {
|
||||
if (!transferForm.warehouseId.trim() || !transferForm.warehouseCode.trim() || !transferForm.warehouseName.trim()) {
|
||||
ElMessage.warning('请填写目的仓 ID、代码和名称')
|
||||
@@ -194,7 +222,13 @@ function openDetail(source: object) {
|
||||
}
|
||||
|
||||
onMounted(() => { void load(); void loadWarehouses() })
|
||||
async function loadWarehouses() { try { warehouses.value = (await listReceivingOverseasWarehouses()).records } catch { warehouses.value = [] } }
|
||||
async function loadWarehouses() {
|
||||
try {
|
||||
warehouses.value = await listAllPlatformWarehouses({ warehouseType: 'FBA', status: 'ACTIVE' })
|
||||
} catch {
|
||||
warehouses.value = []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -214,14 +248,14 @@ async function loadWarehouses() { try { warehouses.value = (await listReceivingO
|
||||
</LoadErrorState>
|
||||
</template>
|
||||
<section v-if="!loadError" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="overseas-last-mile-orders" row-key="id" empty-text="暂无尾程订单" :row-class-name="({ row }: { row: LastMileOrderListItem }) => row.detained ? 'is-detained-row' : ''" @selection-change="onSelectionChange" @update:page="load()" @update:page-size="page = 1; load()">
|
||||
<template #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderExport)" plain :loading="exportLoading" @click="exportOrders"><Download :size="16" />导出订单</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" plain :disabled="selectedRows.length !== 1 || actionLoading" @click="convertInboundPlan">生成入库计划</el-button></template>
|
||||
<template #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderExport)" plain :loading="exportLoading" @click="exportOrders"><Download :size="16" />导出订单</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" type="primary" plain :disabled="!selectedRows.length || actionLoading" @click="batchPalletMerge">合托标记</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" type="warning" plain :disabled="!cancellableMergeCount || actionLoading" @click="cancelBatchPalletMerge">取消合托</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" plain :disabled="selectedRows.length !== 1 || actionLoading" @click="convertInboundPlan">生成入库计划</el-button></template>
|
||||
<template #actions="{ row }"><el-button size="small" plain type="primary" @click="openDetail(row)"><Eye :size="15" />查看</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" size="small" plain :type="(row as LastMileOrderListItem).detained ? 'success' : 'danger'" :disabled="actionLoading" @click="openDetained(row as LastMileOrderListItem)">{{ (row as LastMileOrderListItem).detained ? '解除暂扣' : '暂扣' }}</el-button></template>
|
||||
<template #pagination-left>共 {{ total }} 条尾程订单 · 已选 {{ selectedRows.length }} 条</template>
|
||||
</DataTable></section>
|
||||
</ListPageLayout></AdminPage>
|
||||
<AppDialog v-model="transferOpen" title="转仓" confirm-text="确认转仓" :confirm-loading="actionLoading" @confirm="submitTransfer">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="目的仓" required><el-select v-model="transferForm.warehouseId" filterable clearable placeholder="请选择目的仓" style="width:100%" @change="(id: string) => { const w = warehouses.find((item) => item.id === id); transferForm.warehouseCode = w?.warehouseCode || ''; transferForm.warehouseName = w?.warehouseName || '' }"><el-option v-for="warehouse in warehouses" :key="warehouse.id" :label="`${warehouse.warehouseName}(${warehouse.warehouseCode})`" :value="warehouse.id" /></el-select></el-form-item>
|
||||
<el-form-item label="FBA 目的仓" required><el-select v-model="transferForm.warehouseId" filterable clearable placeholder="请选择头程 FBA 目的仓" style="width:100%" @change="(id: string) => { const w = warehouses.find((item) => String(item.id) === id); transferForm.warehouseCode = w?.warehouseCode || ''; transferForm.warehouseName = w?.warehouseName || '' }"><el-option v-for="warehouse in warehouses" :key="warehouse.id" :label="`${warehouse.warehouseName}(${warehouse.warehouseCode})`" :value="String(warehouse.id)" /></el-select></el-form-item>
|
||||
<el-form-item label="备注"><el-input v-model="transferForm.remark" type="textarea" maxlength="500" /></el-form-item>
|
||||
</el-form>
|
||||
</AppDialog>
|
||||
|
||||
@@ -305,8 +305,17 @@ describe('overseas warehouse first-batch prototype contract', () => {
|
||||
expect(detail).not.toContain('ElMessage.success')
|
||||
})
|
||||
|
||||
it('shows the transfer route label on PDA pallet picking rows', () => {
|
||||
const detail = source('DispatchDetailView.vue')
|
||||
expect(detail).toContain('label="转仓提示"')
|
||||
expect(detail).toContain('row.warehouseRouteLabel')
|
||||
expect(detail).toContain('type="warning"')
|
||||
})
|
||||
|
||||
it('preserves last-mile status tabs and read-only outbound association columns without links', () => {
|
||||
const value = source('LastMileOrdersView.vue')
|
||||
expect(value).toContain("listAllPlatformWarehouses({ warehouseType: 'FBA', status: 'ACTIVE' })")
|
||||
expect(value).toContain('请选择头程 FBA 目的仓')
|
||||
expect(value).toContain('aria-label="尾程订单状态"')
|
||||
expect(value).toContain('<el-radio-button value="全部">全部</el-radio-button>')
|
||||
expect(value).toContain('<el-radio-button value="待分配">待分配</el-radio-button>')
|
||||
@@ -327,7 +336,7 @@ describe('overseas warehouse first-batch prototype contract', () => {
|
||||
|
||||
it('keeps every prototype list column in its frozen order', () => {
|
||||
expect(columnKeys('LastMileOrdersView.vue')).toEqual([
|
||||
'actions', 'selection', 'orderNo', 'palletMergeRelation', 'warning', 'orderType', 'rejectedAt', 'inboundCode', 'owner', 'warehouse',
|
||||
'actions', 'selection', 'orderNo', 'consolidated', 'palletMergeRelation', 'warning', 'orderType', 'rejectedAt', 'inboundCode', 'owner', 'warehouse',
|
||||
'transferWarehouse', 'fbaWarehouse', 'containerNo', 'abnormal', 'held', 'pallets',
|
||||
'cartons', 'volume', 'quantity', 'volumeWeight', 'portEta', 'portAta', 'warehouseEta', 'inboundOrderNo',
|
||||
'outboundOrderNo', 'dispatchOrderNo', 'relabelOrderNo', 'relabelStatus', 'status',
|
||||
|
||||
Reference in New Issue
Block a user