From 8029c235e4ff2a263270bf567a9ce78cb723d32f Mon Sep 17 00:00:00 2001 From: liuyihe <2513762445@qq.com> Date: Sun, 6 Sep 2026 15:53:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/overseas-warehouse/api/inboundOrders.ts | 2 ++ src/modules/overseas-warehouse/api/lastMileOrders.ts | 2 ++ src/modules/overseas-warehouse/api/outbounds.ts | 4 ++-- src/modules/overseas-warehouse/lastMilePresentation.ts | 1 + .../overseas-warehouse/pages/InboundOrdersView.vue | 8 +++++--- .../overseas-warehouse/pages/LastMileOrdersView.vue | 4 +++- src/modules/overseas-warehouse/pages/OutboundsView.vue | 8 ++++---- src/modules/overseas-warehouse/types.ts | 2 ++ 8 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/modules/overseas-warehouse/api/inboundOrders.ts b/src/modules/overseas-warehouse/api/inboundOrders.ts index dfe433d1..210c0cd1 100644 --- a/src/modules/overseas-warehouse/api/inboundOrders.ts +++ b/src/modules/overseas-warehouse/api/inboundOrders.ts @@ -7,6 +7,7 @@ export interface InboundOrderQuery { size: number planNo?: string inboundCode?: string + lxCode?: string status?: string warehouse?: string fbaWarehouseCode?: string @@ -23,6 +24,7 @@ export interface InboundOrderSummaryDto { customerId: string orderId: string inboundCode?: string | null + lxCode?: string | null orderType?: string | null warehouseId?: string | null warehouseCode?: string | null diff --git a/src/modules/overseas-warehouse/api/lastMileOrders.ts b/src/modules/overseas-warehouse/api/lastMileOrders.ts index 222d9c6b..adb1c3eb 100644 --- a/src/modules/overseas-warehouse/api/lastMileOrders.ts +++ b/src/modules/overseas-warehouse/api/lastMileOrders.ts @@ -27,6 +27,7 @@ export interface LastMileOrderQuery { orderNo?: string orderType?: string inboundCode?: string + lxCode?: string containerNo?: string currentStatus?: string status?: string @@ -47,6 +48,7 @@ export interface LastMileOrderSummaryDto { orderType?: string | null orderTypeName?: string | null inboundCode?: string | null + lxCode?: string | null sourceOrderNo?: string | null sourceInboundId?: string | null customerName?: string | null diff --git a/src/modules/overseas-warehouse/api/outbounds.ts b/src/modules/overseas-warehouse/api/outbounds.ts index b9d4cf09..311a65db 100644 --- a/src/modules/overseas-warehouse/api/outbounds.ts +++ b/src/modules/overseas-warehouse/api/outbounds.ts @@ -3,9 +3,9 @@ import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http' import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders' import type { DeliveryOrderRow } from './deliveryOrders' -export interface OutboundRow { id: string; outboundNo: string; dispatchNo?: string | null; overseasWarehouseId?: string | null; status?: string | null; palletCount?: number | null; packageCount?: number | null; createdAt?: string | null } +export interface OutboundRow { id: string; outboundNo: string; dispatchNo?: string | null; overseasWarehouseId?: string | null; lxCodes?: string | null; status?: string | null; palletCount?: number | null; packageCount?: number | null; createdAt?: string | null } export interface OutboundDetail { outbound: OutboundRow; delivery?: DeliveryOrderRow | null } -export interface OutboundQuery { page: number; size: number; documentNo?: string; warehouseId?: string; status?: string } +export interface OutboundQuery { page: number; size: number; documentNo?: string; lxCode?: string; warehouseId?: string; status?: string } export async function listOutbounds(query: OutboundQuery) { const response = await overseasHttp.get>, ApiEnvelope>>('/platform/v1/last-leg/outbound-orders', { params: query }) return normalizeOverseasPage(unwrapApiResponse(response)) diff --git a/src/modules/overseas-warehouse/lastMilePresentation.ts b/src/modules/overseas-warehouse/lastMilePresentation.ts index c7bd35a4..54680baf 100644 --- a/src/modules/overseas-warehouse/lastMilePresentation.ts +++ b/src/modules/overseas-warehouse/lastMilePresentation.ts @@ -104,6 +104,7 @@ export function toLastMileOrderListItem(dto: LastMileOrderSummaryDto): LastMileO orderType: text(dto.orderTypeName || lastMileOrderTypeLabel(dto.orderType)), rejectedAt: '—', inboundCode: text(dto.inboundCode), + lxCode: text(dto.lxCode), owner: text(dto.customerName), warehouse: text(dto.overseasWarehouseName), transferWarehouse: text(dto.transferWarehouseName), diff --git a/src/modules/overseas-warehouse/pages/InboundOrdersView.vue b/src/modules/overseas-warehouse/pages/InboundOrdersView.vue index 992eb24b..ae97a33f 100644 --- a/src/modules/overseas-warehouse/pages/InboundOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/InboundOrdersView.vue @@ -31,10 +31,11 @@ const mutationError = ref(null) const page = ref(1) const pageSize = ref(10) const total = ref(0) -const filters = ref({ orderNo: '', inboundCode: '', status: '', warehouse: '', fbaWarehouse: '', appointmentStatus: '', dispatchStatus: '', inboundDate: [] }) +const filters = ref({ orderNo: '', inboundCode: '', lxCode: '', status: '', warehouse: '', fbaWarehouse: '', appointmentStatus: '', dispatchStatus: '', inboundDate: [] }) const fields = computed(() => [ { key: 'orderNo', type: 'input', label: '入库单号', width: 165, placeholder: '入库单号' }, { key: 'inboundCode', type: 'input', label: '入仓码', width: 145, placeholder: '入仓码' }, + { key: 'lxCode', type: 'input', label: 'LX代码', width: 160, placeholder: '领星入库单代码' }, { key: 'status', type: 'select', label: '状态', width: 130, placeholder: '全部状态', options: [{ label: '待入库', value: 'PENDING_ASSIGNMENT' }, { label: '拣货中', value: 'PICKING' }, { label: '全部入库', value: 'COMPLETED' }, { label: '部分入库', value: 'PARTIAL_INBOUND' }] }, { key: 'warehouse', type: 'input', label: '海外仓', width: 155, placeholder: '全部海外仓' }, { key: 'fbaWarehouse', type: 'input', label: 'FBA仓库', width: 145, placeholder: '全部FBA仓库' }, @@ -67,6 +68,7 @@ const columns: DataTableColumn[] = [ { key: 'selection', type: 'selection', width: 48, fixed: 'left', selectable: selectableRow }, { key: 'orderNo', prop: 'orderNo', label: '入库单号', minWidth: 170 }, { key: 'inboundCode', prop: 'inboundCode', label: '入仓码', minWidth: 140 }, + { key: 'lxCode', prop: 'lxCode', label: 'LX代码', minWidth: 150 }, { key: 'type', prop: 'type', label: '类型', width: 100 }, { key: 'warehouse', prop: 'warehouse', label: '海外仓', minWidth: 170 }, { key: 'fbaWarehouse', prop: 'fbaWarehouse', label: 'FBA仓库', minWidth: 130 }, @@ -91,7 +93,7 @@ function toListItem(dto: InboundOrderSummaryDto): InboundOrderListItem { return { lineId: String(dto.lineId), planId: String(dto.planId), customerId: String(dto.customerId), orderId: String(dto.orderId), warehouseId: text(dto.warehouseId) === '—' ? '' : String(dto.warehouseId), destinationWarehouseCode: text(dto.warehouseCode), - orderNo: text(dto.planNo), inboundCode: text(dto.inboundCode), type: typeLabel(dto.orderType), warehouse: text(dto.warehouseName || dto.warehouseCode), + orderNo: text(dto.planNo), inboundCode: text(dto.inboundCode), lxCode: text(dto.lxCode), type: typeLabel(dto.orderType), warehouse: text(dto.warehouseName || dto.warehouseCode), fbaWarehouse: text(dto.fbaWarehouseCode), owner: text(dto.customerName), cartons: number(dto.packageCount), pickedCartons: number(dto.pickedPackageCount), volume: number(dto.volumeCbm), pallets: number(dto.palletCount), status: planStatusLabel(dto.status), appointmentNo: text(dto.appointmentNo), appointmentStatus: appointmentStatusLabel(dto.appointmentStatus), appointmentAt: formatOverseasDateTime(dto.appointmentAt), expectedLoadingAt: formatOverseasDateTime(dto.expectedLoadingAt), dispatchStatus: dto.dispatchStatus === 'SCHEDULED' ? '已排车' : '未排车', @@ -161,7 +163,7 @@ async function load(model: QueryModel = filters.value) { selectedRows.value = [] loading.value = true; loadError.value = null try { - const result = await listInboundOrders({ page: page.value, size: pageSize.value, planNo: String(filters.value.orderNo || '').trim() || undefined, inboundCode: String(filters.value.inboundCode || '').trim() || undefined, status: String(filters.value.status || '').trim() || undefined, warehouse: String(filters.value.warehouse || '').trim() || undefined, fbaWarehouseCode: String(filters.value.fbaWarehouse || '').trim() || undefined, appointmentStatus: String(filters.value.appointmentStatus || '').trim() || undefined, dispatchStatus: String(filters.value.dispatchStatus || '').trim() || undefined, ...dateRange() }) + const result = await listInboundOrders({ page: page.value, size: pageSize.value, planNo: String(filters.value.orderNo || '').trim() || undefined, inboundCode: String(filters.value.inboundCode || '').trim() || undefined, lxCode: String(filters.value.lxCode || '').trim() || undefined, status: String(filters.value.status || '').trim() || undefined, warehouse: String(filters.value.warehouse || '').trim() || undefined, fbaWarehouseCode: String(filters.value.fbaWarehouse || '').trim() || undefined, appointmentStatus: String(filters.value.appointmentStatus || '').trim() || undefined, dispatchStatus: String(filters.value.dispatchStatus || '').trim() || undefined, ...dateRange() }) rows.value = result.records.map(toListItem); total.value = result.total } catch (error) { rows.value = []; total.value = 0; loadError.value = getApiErrorDetails(error, '入库单加载失败,请重试') } finally { loading.value = false } diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue index f0d2bec3..ed223910 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue @@ -52,10 +52,11 @@ const containerLoadError = ref(null) const selectedContainerBookingId = ref('') let containerOptionRequest = 0 const statusTab = ref<'全部' | '待分配' | '柜子'>('全部') -const filters = ref({ orderNo: '', orderType: '', warehouse: '', inboundCode: '', sourceOrderNo: '', containerNo: '', status: '', transferWarehouseCode: '', abnormal: '', detained: '', createdAt: [] }) +const filters = ref({ orderNo: '', orderType: '', warehouse: '', inboundCode: '', lxCode: '', sourceOrderNo: '', containerNo: '', status: '', transferWarehouseCode: '', abnormal: '', detained: '', createdAt: [] }) const allFields: QueryField[] = [ { key: 'orderNo', type: 'input', label: '尾程单号', width: 190, placeholder: '请输入尾程单号' }, { key: 'inboundCode', type: 'input', label: '入仓码', width: 180, placeholder: '请输入入仓码' }, + { key: 'lxCode', type: 'input', label: 'LX代码', width: 180, placeholder: '请输入领星入库单代码' }, { key: 'orderType', type: 'select', label: '订单类型', width: 170, placeholder: '全部类型', options: [ { label: '头程订单', value: 'FIRST_LEG' }, { label: '换标下单', value: 'RELABEL_APPLICATION' }, { label: '仓储转运', value: 'WAREHOUSE_TRANSFER' }, { label: '本土散板', value: 'LOCAL_LOOSEBOARD' }, @@ -121,6 +122,7 @@ const columns: DataTableColumn[] = [ { key: 'orderType', prop: 'orderType', label: '订单类型', minWidth: 110 }, { key: 'rejectedAt', prop: 'rejectedAt', label: '拒收时间', minWidth: 150 }, { key: 'inboundCode', prop: 'inboundCode', label: '入仓码', minWidth: 140 }, + { key: 'lxCode', prop: 'lxCode', label: 'LX代码', minWidth: 150 }, { key: 'owner', prop: 'owner', label: '货主', minWidth: 150 }, { key: 'warehouse', prop: 'warehouse', label: '海外仓', minWidth: 170 }, { key: 'transferWarehouse', prop: 'transferWarehouse', label: '转仓', minWidth: 140 }, diff --git a/src/modules/overseas-warehouse/pages/OutboundsView.vue b/src/modules/overseas-warehouse/pages/OutboundsView.vue index 720a6ae5..11f25ca3 100644 --- a/src/modules/overseas-warehouse/pages/OutboundsView.vue +++ b/src/modules/overseas-warehouse/pages/OutboundsView.vue @@ -21,17 +21,17 @@ import { overseasWarehousePermissions as permission } from '../permissions' const router = useRouter(); const access = useAccessPreviewStore() const rows = ref([]); const page = ref(1); const pageSize = ref(20); const total = ref(0); const loading = ref(false); const error = ref(null); const mutationError = ref(null) -const filters = ref({ documentNo: '', warehouseId: '', status: '' }); const createOpen = ref(false); const saving = ref(false); const recipient = ref(''); const remark = ref(''); const quantity = ref(); const selectedCustomerId = ref(''); const selectedPositionId = ref(''); const positionOptions = ref>([]); const inventoryLoading = ref(false) +const filters = ref({ documentNo: '', lxCode: '', warehouseId: '', status: '' }); const createOpen = ref(false); const saving = ref(false); const recipient = ref(''); const remark = ref(''); const quantity = ref(); const selectedCustomerId = ref(''); const selectedPositionId = ref(''); const positionOptions = ref>([]); const inventoryLoading = ref(false) const customerOptions = computed(() => { const customers = new Map() positionOptions.value.forEach(({ balance }) => customers.set(balance.customerId, balance.customerName?.trim() || '客户名称待补充')) return [...customers].map(([value, label]) => ({ value, label })) }) const availablePositionOptions = computed(() => positionOptions.value.filter(({ balance }) => balance.customerId === selectedCustomerId.value)) -const columns: DataTableColumn[] = [{ key: 'actions', label: '操作', width: 190, fixed: 'left', slotName: 'actions' }, { key: 'outboundNo', prop: 'outboundNo', label: '出库单号', minWidth: 180 }, { key: 'dispatchNo', prop: 'dispatchNo', label: '关联排车单', minWidth: 160 }, { key: 'status', prop: 'status', label: '状态', width: 130, slotName: 'status' }, { key: 'palletCount', prop: 'palletCount', label: '托盘数', width: 100 }, { key: 'packageCount', prop: 'packageCount', label: '箱数', width: 100 }, { key: 'createdAt', prop: 'createdAt', label: '创建时间', minWidth: 180 }] -const fields: QueryField[] = [{ key: 'documentNo', type: 'input', label: '出库单号', placeholder: '请输入出库单号', width: 220 }, { key: 'warehouseId', type: 'input', label: '目的仓', placeholder: '请输入目的仓', width: 220 }, { key: 'status', type: 'select', label: '状态', placeholder: '全部状态', width: 160, options: [{ label: '全部', value: '' }, { label: '待出库', value: 'WAIT_OUTBOUND' }, { label: '已出库', value: 'OUTBOUNDED' }] }] +const columns: DataTableColumn[] = [{ key: 'actions', label: '操作', width: 190, fixed: 'left', slotName: 'actions' }, { key: 'outboundNo', prop: 'outboundNo', label: '出库单号', minWidth: 180 }, { key: 'lxCodes', prop: 'lxCodes', label: 'LX代码', minWidth: 180 }, { key: 'dispatchNo', prop: 'dispatchNo', label: '关联排车单', minWidth: 160 }, { key: 'status', prop: 'status', label: '状态', width: 130, slotName: 'status' }, { key: 'palletCount', prop: 'palletCount', label: '托盘数', width: 100 }, { key: 'packageCount', prop: 'packageCount', label: '箱数', width: 100 }, { key: 'createdAt', prop: 'createdAt', label: '创建时间', minWidth: 180 }] +const fields: QueryField[] = [{ key: 'documentNo', type: 'input', label: '出库单号', placeholder: '请输入出库单号', width: 220 }, { key: 'lxCode', type: 'input', label: 'LX代码', placeholder: '请输入领星入库单代码', width: 220 }, { key: 'warehouseId', type: 'input', label: '目的仓', placeholder: '请输入目的仓', width: 220 }, { key: 'status', type: 'select', label: '状态', placeholder: '全部状态', width: 160, options: [{ label: '全部', value: '' }, { label: '待出库', value: 'WAIT_OUTBOUND' }, { label: '已出库', value: 'OUTBOUNDED' }] }] -async function load(model: QueryModel = filters.value) { Object.assign(filters.value, model); loading.value = true; error.value = null; try { const result = await listOutbounds({ page: page.value, size: pageSize.value, documentNo: String(filters.value.documentNo || '').trim() || undefined, warehouseId: String(filters.value.warehouseId || '').trim() || undefined, status: String(filters.value.status || '').trim() || undefined }); rows.value = result.records.map((row) => ({ ...row, createdAt: formatOverseasDateTime(row.createdAt) })); total.value = result.total } catch (cause) { error.value = getApiErrorDetails(cause, '出库单列表加载失败') } finally { loading.value = false } } +async function load(model: QueryModel = filters.value) { Object.assign(filters.value, model); loading.value = true; error.value = null; try { const result = await listOutbounds({ page: page.value, size: pageSize.value, documentNo: String(filters.value.documentNo || '').trim() || undefined, lxCode: String(filters.value.lxCode || '').trim() || undefined, warehouseId: String(filters.value.warehouseId || '').trim() || undefined, status: String(filters.value.status || '').trim() || undefined }); rows.value = result.records.map((row) => ({ ...row, createdAt: formatOverseasDateTime(row.createdAt) })); total.value = result.total } catch (cause) { error.value = getApiErrorDetails(cause, '出库单列表加载失败') } finally { loading.value = false } } async function openCreate() { createOpen.value = true; selectedCustomerId.value = ''; selectedPositionId.value = ''; quantity.value = undefined; inventoryLoading.value = true; try { const balances = await listInventoryBalances({ page: 1, size: 200, inventoryStatus: 'AVAILABLE' }); const groups = await Promise.all(balances.records.map(async balance => (await listInventoryPositions(balance.id, { inventoryStatus: 'AVAILABLE' })).map(position => ({ balance, position })))); positionOptions.value = groups.flat().filter(item => item.position.availablePackages > 0) } catch (cause) { ElMessage.error(getApiErrorDetails(cause, '可用库存加载失败').message) } finally { inventoryLoading.value = false } } function selectCustomer() { selectedPositionId.value = ''; quantity.value = undefined } async function submit() { const selected = availablePositionOptions.value.find(item => item.position.id === selectedPositionId.value); if (!selectedCustomerId.value || !recipient.value.trim() || !selected || !quantity.value || quantity.value < 1) { ElMessage.warning('请选择客户,填写收件信息并选择托盘和出库数量'); return }; if (quantity.value > selected.position.availablePackages) { ElMessage.warning('出库数量不能超过可用库存'); return }; saving.value = true; try { await createOneClickDropshipOutbound(selectedCustomerId.value, { recipient: recipient.value.trim(), items: [{ inventoryPositionId: selected.position.id, packages: quantity.value, sku: selected.balance.skuCode || undefined }], remark: remark.value.trim() || undefined, idempotencyKey: `web-dropship-${Date.now()}` }); ElMessage.success('出库单已创建并推送PDA拣货任务'); createOpen.value = false; await load() } catch (cause) { ElMessage.error(getApiErrorDetails(cause, '一件代发出库失败').message) } finally { saving.value = false } } diff --git a/src/modules/overseas-warehouse/types.ts b/src/modules/overseas-warehouse/types.ts index 41090933..1b3c72f8 100644 --- a/src/modules/overseas-warehouse/types.ts +++ b/src/modules/overseas-warehouse/types.ts @@ -12,6 +12,7 @@ export interface LastMileOrderListItem { orderType: string rejectedAt: string inboundCode: string + lxCode: string owner: string warehouse: string transferWarehouse: string @@ -54,6 +55,7 @@ export interface InboundOrderListItem { destinationWarehouseCode: string orderNo: string inboundCode: string + lxCode: string type: string warehouse: string fbaWarehouse: string