front/src/views/order/platformStoreOrder/index.vue
zzh 76d8b473b6 feat: 查价下单加固、待排货 UI 与 EnableStatus 对齐
查价参考价提示与可选尺寸;下单尺寸必填及查价带入;待排货状态展示;货物属性/启用状态工具化及相关页面更新。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 19:00:56 +08:00

735 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { Modal } from '@arco-design/web-vue'
import HandsontablePro from '@/components/HandsontablePro/index.vue'
import PaginationPro from '@/components/PaginationPro/index.vue'
import { useTableContainerHeight } from '@/composables/useTableContainerHeight'
import { useWarehouseAdminCustomer } from '@/composables/useWarehouseAdminCustomer'
import { getSalesProductList } from '@/api/channel/salesProduct'
import {
batchMatchPlatformStoreOrderInventory,
deletePlatformStoreOrder,
fetchPlatformStoreOrderLabel,
getPlatformStoreOrderList,
getPlatformStoreOrderSummary,
matchPlatformStoreOrderInventory,
readyToShipPlatformStoreOrder,
syncPlatformStoreOrderStatus,
togglePlatformStoreOrderSuspend,
} from '@/api/order/platformStore'
import { getWarehouseList } from '@/api/system/warehouse'
import { $baseMessage } from '@/utils'
import { hasPermission } from '@/utils/rbac-permission'
import {
buildWarehouseNameMap,
formatDateTime,
formatMoney,
normalizeListRow,
pickField,
resolveWarehouseLabel,
} from '@/utils/warehouseListMapper'
import { renderWarehouseActionBtn, wrapWarehouseActions } from '@/utils/warehouseActionRenderer'
import PullOrdersModal from './PullOrdersModal.vue'
import StoreOrderDetailDrawer from './StoreOrderDetailDrawer.vue'
import CreateLogisticsModal, { type CreateLogisticsMode } from './CreateLogisticsModal.vue'
defineOptions({ name: 'PlatformStoreOrder' })
const { t } = useI18n()
const route = useRoute()
const { tableContainerRef, tableHeight } = useTableContainerHeight()
const {
isAdmin,
customerId: adminCustomerId,
customerOptions,
withCustomerId,
ensureMutationCustomerId,
} = useWarehouseAdminCustomer()
/** Tab active-key;全部用 'all',请求时再转成不传 fulfillStatus */
const STATUS_TAB_ALL = 'all'
const ALLOWED_FULFILL_STATUS = new Set(['pending', 'toShip', 'shipped', 'canceled', 'completed'])
function resolveFulfillStatusFromQuery(): string {
const raw = route.query.fulfillStatus
const value = Array.isArray(raw) ? raw[0] : raw
if (typeof value === 'string' && ALLOWED_FULFILL_STATUS.has(value)) {
return value
}
return STATUS_TAB_ALL
}
const fulfillStatus = ref<string>(resolveFulfillStatusFromQuery())
const keyword = ref('')
const summary = ref<Record<string, number>>({})
const warehouseOptions = ref<Array<{ label: string; value: number }>>([])
const warehouseNameMap = computed(() => buildWarehouseNameMap(warehouseOptions.value))
const productOptions = ref<Array<{ label: string; value: string }>>([])
const listLoading = ref(false)
const tableRows = ref<any[]>([])
const selectedRows = ref<any[]>([])
const currentPage = ref(1)
const pageSize = ref(30)
const totalCount = ref(0)
const pullVisible = ref(false)
const actionLoading = ref(false)
const matchWarehouseId = ref<number>()
const matchProductCode = ref<string>()
const detailDrawerRef = ref<InstanceType<typeof StoreOrderDetailDrawer>>()
const createModalVisible = ref(false)
const createModalMode = ref<CreateLogisticsMode>('logistics')
const createModalIds = ref<number[]>([])
const statusTabs = [
{ value: STATUS_TAB_ALL, labelKey: 'order.platformStoreOrder.status.all', countKey: null },
{ value: 'pending', labelKey: 'order.platformStoreOrder.status.pending', countKey: 'pending' as const },
{ value: 'toShip', labelKey: 'order.platformStoreOrder.status.toShip', countKey: 'toShip' as const },
{ value: 'shipped', labelKey: 'order.platformStoreOrder.status.shipped', countKey: 'shipped' as const },
]
const hotColumns = computed(() => {
const cols = [
{ key: 'platformOrderNo', label: t('order.platformStoreOrder.table.orderNo'), width: 160 },
{ key: 'platformName', label: t('order.platformStoreOrder.table.platform'), width: 90 },
{ key: 'storeNickname', label: t('order.platformStoreOrder.table.store'), width: 120 },
{ key: 'orderCountry', label: t('order.platformStoreOrder.table.country'), width: 80 },
{ key: 'recipientName', label: t('order.platformStoreOrder.table.recipient'), width: 110 },
{ key: 'fulfillStatus', label: t('order.platformStoreOrder.table.status'), width: 90 },
{ key: 'itemCount', label: t('order.platformStoreOrder.table.itemCount'), width: 70 },
{ key: 'totalAmountDisplay', label: t('order.platformStoreOrder.table.amount'), width: 110 },
{ key: 'linkedServiceNo', label: t('order.platformStoreOrder.table.linkedServiceNo'), width: 150 },
{ key: 'shippingLabelNo', label: t('order.platformStoreOrder.table.shippingLabel'), width: 140 },
{ key: 'warehouseName', label: t('order.platformStoreOrder.table.warehouse'), width: 120 },
{ key: 'platformOrderTime', label: t('order.platformStoreOrder.table.orderTime'), width: 160 },
{ key: 'lastSyncTime', label: t('order.platformStoreOrder.table.lastSync'), width: 160 },
]
if (isAdmin.value) {
cols.unshift(
{ key: 'customerName', label: t('order.myOrders.table.customerName'), width: 120 },
{ key: 'customerCode', label: t('order.myOrders.table.customerCode'), width: 110 },
)
}
return cols
})
function mapRow(raw: Record<string, unknown>) {
const row = normalizeListRow(raw)
const status = String(pickField(row, 'fulfillStatus', 'FulfillStatus') ?? '')
const platformCode = String(pickField(row, 'platformCode', 'PlatformCode') ?? '')
const whId = pickField<number>(row, 'warehouseId', 'WarehouseId')
const currency = pickField<string>(row, 'currency', 'Currency')
const amount = pickField(row, 'totalAmount', 'TotalAmount')
const suspended = Boolean(pickField(row, 'isSuspended', 'IsSuspended'))
let statusLabel = t(`order.platformStoreOrder.status.${status}`, status)
if (suspended) statusLabel = `${statusLabel}(${t('order.platformStoreOrder.status.suspended')})`
return {
id: pickField<number>(row, 'id', 'Id'),
customerId: pickField<number>(row, 'customerId', 'CustomerId'),
customerName: pickField(row, 'customerName', 'CustomerName') ?? '',
customerCode: pickField(row, 'customerCode', 'CustomerCode') ?? '',
platformOrderNo: pickField(row, 'platformOrderNo', 'PlatformOrderNo') ?? '-',
platformName: pickField(row, 'platformName', 'PlatformName') ?? platformCode ?? '-',
storeNickname: pickField(row, 'storeNickname', 'StoreNickname') ?? '-',
orderCountry: pickField(row, 'orderCountry', 'OrderCountry') ?? '-',
recipientName: pickField(row, 'recipientName', 'RecipientName') || '-',
fulfillStatus: statusLabel,
itemCount: pickField<number>(row, 'itemCount', 'ItemCount') ?? '-',
totalAmountDisplay: formatMoney(amount, currency),
linkedServiceNo: pickField(row, 'linkedServiceNo', 'LinkedServiceNo') || '-',
shippingLabelNo: pickField(row, 'shippingLabelNo', 'ShippingLabelNo') ?? '-',
warehouseName: resolveWarehouseLabel(whId, warehouseNameMap.value),
platformOrderTime: formatDateTime(pickField(row, 'platformOrderTime', 'PlatformOrderTime')),
lastSyncTime: formatDateTime(pickField(row, 'lastSyncTime', 'LastSyncTime')),
_raw: row,
_status: status,
_suspended: suspended,
_platformCode: platformCode.toLowerCase(),
}
}
function getSelectedIds(): number[] {
return selectedRows.value
.map((row) => Number(row.id ?? pickField(row._raw || row, 'id', 'Id')))
.filter((id) => Number.isFinite(id) && id > 0)
}
function mutationCustomerId(): number | undefined {
return ensureMutationCustomerId()
}
async function loadProducts() {
try {
const { items } = await getSalesProductList({ page: 1, pageSize: 200, isActive: 2 })
productOptions.value = (items || [])
.map((p: any) => {
const code = p.productCode || p.ProductCode || ''
const name = p.productName || p.ProductName || code
return { label: `${name} (${code})`, value: code }
})
.filter((p: { value: string }) => !!p.value)
if (productOptions.value.length && !matchProductCode.value) {
matchProductCode.value = productOptions.value[0].value
}
} catch {
productOptions.value = []
}
}
async function loadSummary() {
try {
const data = await getPlatformStoreOrderSummary(withCustomerId({}))
summary.value = {
pending: data?.pending ?? data?.Pending ?? 0,
toShip: data?.toShip ?? data?.ToShip ?? 0,
shipped: data?.shipped ?? data?.Shipped ?? 0,
suspended: data?.suspended ?? data?.Suspended ?? 0,
}
} catch {
summary.value = {}
}
}
function resolveFulfillStatusFilter(): string | undefined {
const status = fulfillStatus.value
if (!status || status === STATUS_TAB_ALL) return undefined
return status
}
async function loadList() {
listLoading.value = true
selectedRows.value = []
try {
const { items, total } = await getPlatformStoreOrderList(
withCustomerId({
page: currentPage.value,
pageSize: pageSize.value,
fulfillStatus: resolveFulfillStatusFilter(),
platformOrderNo: keyword.value || undefined,
}),
)
tableRows.value = (items || []).map((item: Record<string, unknown>) => mapRow(item))
totalCount.value = Number(total || 0)
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.loadFailed'), 'error')
} finally {
listLoading.value = false
}
}
function handleStatusTabChange(key: string | number) {
fulfillStatus.value = String(key)
currentPage.value = 1
loadList()
}
function handlePageChange(page: number) {
currentPage.value = page
loadList()
}
function handlePageSizeChange(size: number) {
pageSize.value = size
currentPage.value = 1
loadList()
}
function handleSearch() {
currentPage.value = 1
loadList()
}
function handleCustomerChange() {
currentPage.value = 1
loadSummary()
loadList()
}
function handleSelectionChange(rows: any[]) {
selectedRows.value = rows || []
}
async function showDetail(row: any) {
const id = Number(row._raw?.id || row.id)
if (!id) return
detailDrawerRef.value?.open({
id,
customerId: withCustomerId({}).customerId,
})
}
function buildMatchPayload(id: number) {
const customerId = mutationCustomerId()
if (isAdmin.value && customerId == null) return null
return {
id,
warehouseId: matchWarehouseId.value,
productCode: matchProductCode.value || undefined,
customerId,
}
}
async function handleMatch(row: any) {
if (!hasPermission('Order.PlatformStoreOrder.MatchInventory')) return
if (!matchWarehouseId.value) {
$baseMessage(t('order.platformStoreOrder.message.warehouseRequired'), 'warning')
return
}
const payload = buildMatchPayload(row._raw?.id || row.id)
if (!payload) return
try {
const result = await matchPlatformStoreOrderInventory(payload)
$baseMessage(result?.message || t('order.platformStoreOrder.message.matchSuccess'), 'success')
await loadSummary()
await loadList()
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.matchFailed'), 'error')
}
}
async function handleBatchMatch() {
if (!hasPermission('Order.PlatformStoreOrder.MatchInventory')) return
if (!matchWarehouseId.value) {
$baseMessage(t('order.platformStoreOrder.message.warehouseRequired'), 'warning')
return
}
const customerId = mutationCustomerId()
if (isAdmin.value && customerId == null) return
const pendingIds = tableRows.value
.filter((row) => row._status === 'pending' && !pickField(row._raw, 'linkedOrderId', 'LinkedOrderId'))
.map((row) => Number(row.id))
if (!pendingIds.length) {
$baseMessage(t('order.platformStoreOrder.message.batchEmpty'), 'warning')
return
}
Modal.confirm({
title: t('order.platformStoreOrder.actions.batchMatch'),
content: t('order.platformStoreOrder.message.batchConfirm', { count: pendingIds.length }),
onOk: async () => {
try {
const result = await batchMatchPlatformStoreOrderInventory({
ids: pendingIds,
warehouseId: matchWarehouseId.value,
productCode: matchProductCode.value || undefined,
customerId,
})
$baseMessage(
t('order.platformStoreOrder.message.batchResult', {
success: result?.successCount ?? 0,
fail: result?.failCount ?? 0,
}),
(result?.failCount ?? 0) > 0 ? 'warning' : 'success',
)
await loadSummary()
await loadList()
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.matchFailed'), 'error')
}
},
})
}
function resolveCreatableSelectedIds(): number[] | null {
const selected = selectedRows.value
if (!selected.length) {
$baseMessage(t('order.platformStoreOrder.createLogistics.selectRequired'), 'warning')
return null
}
if (selected.length > 50) {
$baseMessage(t('order.platformStoreOrder.createLogistics.maxLimit'), 'warning')
return null
}
const invalid = selected.filter((row) => {
if (row._suspended) return true
if (row._status !== 'pending') return true
if (pickField(row._raw || row, 'linkedOrderId', 'LinkedOrderId')) return true
return false
})
if (invalid.length) {
$baseMessage(
t('order.platformStoreOrder.createLogistics.invalidSelection', { count: invalid.length }),
'warning',
)
return null
}
return selected.map((row) => Number(row.id)).filter((id) => id > 0)
}
function openCreateModal(mode: CreateLogisticsMode) {
const perm =
mode === 'fulfill'
? 'Order.PlatformStoreOrder.CreateFulfill'
: 'Order.PlatformStoreOrder.CreateLogistics'
if (!hasPermission(perm)) return
const customerId = mutationCustomerId()
if (isAdmin.value && customerId == null) return
const ids = resolveCreatableSelectedIds()
if (!ids) return
createModalMode.value = mode
createModalIds.value = ids
createModalVisible.value = true
}
function openPullModal() {
if (!hasPermission('Order.PlatformStoreOrder.Pull')) return
if (isAdmin.value && mutationCustomerId() == null) return
pullVisible.value = true
}
function handleSyncStatus() {
if (!hasPermission('Order.PlatformStoreOrder.Sync')) return
const ids = getSelectedIds()
if (!ids.length) {
$baseMessage(t('order.platformStoreOrder.message.selectOrders'), 'warning')
return
}
const customerId = withCustomerId({}).customerId
Modal.confirm({
title: t('order.platformStoreOrder.actions.syncStatus'),
content: t('order.platformStoreOrder.message.syncConfirm', { count: ids.length }),
onOk: async () => {
actionLoading.value = true
try {
const result = await syncPlatformStoreOrderStatus(ids, customerId)
$baseMessage(
result?.message
|| t('order.platformStoreOrder.message.syncResult', {
success: result?.successCount ?? 0,
fail: result?.failCount ?? 0,
}),
(result?.failCount ?? 0) > 0 ? 'warning' : 'success',
)
await loadSummary()
await loadList()
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.actionFailed'), 'error')
} finally {
actionLoading.value = false
}
},
})
}
function handleReadyToShip(ids?: number[]) {
if (!hasPermission('Order.PlatformStoreOrder.Rts')) return
const targetIds = ids?.length ? ids : getSelectedIds()
if (!targetIds.length) {
$baseMessage(t('order.platformStoreOrder.message.selectOrders'), 'warning')
return
}
const customerId = withCustomerId({}).customerId
Modal.confirm({
title: t('order.platformStoreOrder.actions.readyToShip'),
content: t('order.platformStoreOrder.message.rtsConfirm', { count: targetIds.length }),
onOk: async () => {
actionLoading.value = true
try {
const result = await readyToShipPlatformStoreOrder(targetIds, customerId)
$baseMessage(
result?.message
|| t('order.platformStoreOrder.message.rtsResult', {
success: result?.successCount ?? 0,
fail: result?.failCount ?? 0,
}),
(result?.failCount ?? 0) > 0 ? 'warning' : 'success',
)
await loadSummary()
await loadList()
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.actionFailed'), 'error')
} finally {
actionLoading.value = false
}
},
})
}
function handleFetchLabel(row: any) {
if (!hasPermission('Order.PlatformStoreOrder.Label')) return
const id = Number(row.id ?? pickField(row._raw || row, 'id', 'Id'))
if (!id) return
const customerId = withCustomerId({}).customerId
Modal.confirm({
title: t('order.platformStoreOrder.actions.fetchLabel'),
content: t('order.platformStoreOrder.message.labelConfirm'),
onOk: async () => {
actionLoading.value = true
try {
const result = await fetchPlatformStoreOrderLabel(id, customerId)
if (result?.success === false) {
$baseMessage(result?.message || t('order.platformStoreOrder.message.labelFailed'), 'error')
return
}
$baseMessage(result?.message || t('order.platformStoreOrder.message.labelSuccess'), 'success')
const url = result?.shippingLabelUrl || result?.ShippingLabelUrl
if (url) window.open(String(url), '_blank')
await loadList()
} catch (e: any) {
$baseMessage(e?.message || t('order.platformStoreOrder.message.labelFailed'), 'error')
} finally {
actionLoading.value = false
}
},
})
}
async function handleSuspend(row: any) {
if (!hasPermission('Order.PlatformStoreOrder.ToggleSuspend')) return
const customerId = mutationCustomerId()
if (isAdmin.value && customerId == null) return
const raw = row._raw || row
await togglePlatformStoreOrderSuspend({
id: Number(pickField(raw, 'id', 'Id')),
isSuspended: !Boolean(pickField(raw, 'isSuspended', 'IsSuspended')),
customerId,
})
$baseMessage(t('order.platformStoreOrder.message.suspendSuccess'), 'success')
await loadSummary()
await loadList()
}
function handleDelete(row: any) {
if (!hasPermission('Order.PlatformStoreOrder.Delete')) return
const customerId = mutationCustomerId()
if (isAdmin.value && customerId == null) return
Modal.confirm({
title: t('order.platformStoreOrder.actions.delete'),
content: row.platformOrderNo,
onOk: async () => {
await deletePlatformStoreOrder([row.id], customerId)
$baseMessage(t('order.platformStoreOrder.message.deleteSuccess'), 'success')
await loadSummary()
await loadList()
},
})
}
function canRts(row: any) {
if (row._suspended) return false
if (row._platformCode === 'temu') return false
return row._status === 'pending' || row._status === 'toShip'
}
function actionRenderer(row: any) {
const parts = [
renderWarehouseActionBtn('detail', t('warehouse.common.detail'), 'view'),
]
const raw = row._raw || row
if (
hasPermission('Order.PlatformStoreOrder.MatchInventory')
&& row._status === 'pending'
&& !pickField(raw, 'linkedOrderId', 'LinkedOrderId')
) {
parts.push(renderWarehouseActionBtn('match', t('order.platformStoreOrder.actions.match'), 'match'))
}
if (hasPermission('Order.PlatformStoreOrder.Rts') && canRts(row)) {
parts.push(renderWarehouseActionBtn('rts', t('order.platformStoreOrder.actions.readyToShip'), 'ship'))
}
if (hasPermission('Order.PlatformStoreOrder.Label') && !row._suspended) {
parts.push(renderWarehouseActionBtn('label', t('order.platformStoreOrder.actions.fetchLabel'), 'label'))
}
if (hasPermission('Order.PlatformStoreOrder.ToggleSuspend')) {
parts.push(
row._suspended
? renderWarehouseActionBtn('suspend', t('order.platformStoreOrder.actions.resume'), 'resume')
: renderWarehouseActionBtn('suspend', t('order.platformStoreOrder.actions.suspend'), 'suspend'),
)
}
if (hasPermission('Order.PlatformStoreOrder.Delete')) {
parts.push(renderWarehouseActionBtn('delete', t('warehouse.common.delete')))
}
return wrapWarehouseActions(parts)
}
function handleActionClick(row: any, _i: number, action?: string) {
if (action === 'detail') showDetail(row)
if (action === 'match') handleMatch(row)
if (action === 'rts') {
if (row._platformCode === 'temu') {
$baseMessage(t('order.platformStoreOrder.message.temuNoRts'), 'warning')
return
}
handleReadyToShip([Number(row.id)])
}
if (action === 'label') handleFetchLabel(row)
if (action === 'suspend') handleSuspend(row)
if (action === 'delete') handleDelete(row)
}
onMounted(async () => {
const { items } = await getWarehouseList({ page: 1, pageSize: 200 }).catch(() => ({ items: [] }))
warehouseOptions.value = (items || []).map((w: any) => ({
label: w.warehouseName || `#${w.id}`,
value: Number(w.id),
}))
if (warehouseOptions.value.length) matchWarehouseId.value = warehouseOptions.value[0].value
await loadProducts()
await loadSummary()
await loadList()
})
watch(
() => route.query.fulfillStatus,
() => {
const next = resolveFulfillStatusFromQuery()
if (next === fulfillStatus.value) return
fulfillStatus.value = next
currentPage.value = 1
void loadList()
},
)
</script>
<template>
<div class="platform-store-order-container warehouse-list-page">
<div class="warehouse-list-page-card">
<a-tabs
v-model:active-key="fulfillStatus"
class="status-tabs"
hide-content
@change="handleStatusTabChange"
>
<a-tab-pane v-for="tab in statusTabs" :key="tab.value">
<template #title>
{{ t(tab.labelKey) }}
<span v-if="tab.countKey" class="tab-count">({{ summary[tab.countKey] ?? 0 }})</span>
</template>
</a-tab-pane>
</a-tabs>
<div class="table-toolbar">
<div class="toolbar-left">
<a-space wrap :size="8">
<a-select
v-if="isAdmin"
v-model="adminCustomerId"
allow-clear
:placeholder="t('warehouse.common.selectCustomer')"
:options="customerOptions"
style="width: 200px"
@change="handleCustomerChange"
/>
<a-select
v-model="matchWarehouseId"
:placeholder="t('warehouse.common.warehouse')"
:options="warehouseOptions"
style="width: 180px"
/>
<a-select
v-model="matchProductCode"
allow-clear
:placeholder="t('order.platformStoreOrder.form.product')"
:options="productOptions"
style="width: 220px"
/>
<a-input
v-model="keyword"
allow-clear
:placeholder="t('order.platformStoreOrder.search.orderNo')"
style="width: 180px"
@press-enter="handleSearch"
/>
<a-button type="primary" @click="handleSearch">{{ t('warehouse.common.search') }}</a-button>
<a-button
v-if="hasPermission('Order.PlatformStoreOrder.Pull')"
:loading="actionLoading"
@click="openPullModal"
>
{{ t('order.platformStoreOrder.actions.pullOrders') }}
</a-button>
<a-button
v-if="hasPermission('Order.PlatformStoreOrder.Sync')"
:loading="actionLoading"
@click="handleSyncStatus"
>
{{ t('order.platformStoreOrder.actions.syncStatus') }}
</a-button>
<a-button
v-if="hasPermission('Order.PlatformStoreOrder.Rts')"
:loading="actionLoading"
@click="handleReadyToShip()"
>
{{ t('order.platformStoreOrder.actions.readyToShip') }}
</a-button>
<a-button v-if="hasPermission('Order.PlatformStoreOrder.MatchInventory')" @click="handleBatchMatch">
{{ t('order.platformStoreOrder.actions.batchMatch') }}
</a-button>
<a-button
v-if="hasPermission('Order.PlatformStoreOrder.CreateLogistics')"
type="primary"
@click="openCreateModal('logistics')"
>
{{ t('order.platformStoreOrder.actions.createLogistics') }}
</a-button>
<a-button
v-if="hasPermission('Order.PlatformStoreOrder.CreateFulfill')"
type="primary"
status="success"
@click="openCreateModal('fulfill')"
>
{{ t('order.platformStoreOrder.actions.createFulfill') }}
</a-button>
</a-space>
</div>
<div class="toolbar-right">
<PaginationPro
:total-count="totalCount"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
/>
</div>
</div>
<div ref="tableContainerRef" class="list-wrap">
<HandsontablePro
:columns="hotColumns"
:data="tableRows"
:height="tableHeight"
:loading="listLoading"
:stretch-columns="true"
show-action-column
:action-column-width="200"
:action-renderer="actionRenderer"
@action-click="handleActionClick"
@selection-change="handleSelectionChange"
/>
</div>
</div>
<StoreOrderDetailDrawer
ref="detailDrawerRef"
:warehouse-name-map="warehouseNameMap"
/>
<PullOrdersModal
v-model:visible="pullVisible"
:customer-id="withCustomerId({}).customerId"
@success="() => { loadSummary(); loadList() }"
/>
<CreateLogisticsModal
v-model:visible="createModalVisible"
:mode="createModalMode"
:store-order-ids="createModalIds"
:product-options="productOptions"
:warehouse-options="warehouseOptions"
:default-product-code="matchProductCode"
:default-warehouse-id="matchWarehouseId"
:customer-id="withCustomerId({}).customerId"
@success="() => { loadSummary(); loadList() }"
/>
</div>
</template>
<style scoped lang="less">
@import '@/styles/warehouse-list-page.less';
</style>