diff --git a/src/modules/dashboard/overview.test.mjs b/src/modules/dashboard/overview.test.mjs index c0df45d..da51657 100644 --- a/src/modules/dashboard/overview.test.mjs +++ b/src/modules/dashboard/overview.test.mjs @@ -142,3 +142,15 @@ test('matches the updated six-action icon and motion treatment', () => { assert.match(dashboardView, /prefers-reduced-motion: reduce/) assert.match(dashboardView, /\.client-dashboard a:focus-visible/) }) + +test('opens all six dashboard businesses through their dedicated create pages', () => { + for (const route of [ + '/orders/first-leg/create', + '/overseas-warehouse/return-relabel/create', + '/cross-border/domestic-trucking/create', + '/cross-border/pallet-shipping/create', + '/cross-border/procurement/create', + '/overseas-warehouse/labeling/create', + ]) assert.match(dashboardView, new RegExp(`route: '${route.replaceAll('/', '\\/')}'`)) + assert.match(dashboardView, /title: '退货换标'[\s\S]*?permission: 'merchant:overseas-warehouse:return-order:create'/) +}) diff --git a/src/modules/first-leg/types/inboundBilling.ts b/src/modules/first-leg/types/inboundBilling.ts index 101a2a5..51d3db9 100644 --- a/src/modules/first-leg/types/inboundBilling.ts +++ b/src/modules/first-leg/types/inboundBilling.ts @@ -68,9 +68,9 @@ export interface MerchantInboundFeeSnapshot { chargeRuleId: string ruleCode: string chargeRuleVersion: number - carrierRateId: string + carrierRateId: string | null rateCode: string - carrierRateVersion: number + carrierRateVersion: number | null customerId: string customerName: string originWarehouseId: string diff --git a/src/modules/overseas-warehouse/permissions.test.mjs b/src/modules/overseas-warehouse/permissions.test.mjs index cd405e3..b5c9791 100644 --- a/src/modules/overseas-warehouse/permissions.test.mjs +++ b/src/modules/overseas-warehouse/permissions.test.mjs @@ -20,9 +20,11 @@ test('protects every overseas warehouse page with its independent list permissio test('opens labeling and return relabeling on dedicated protected create pages', () => { assert.match(routes, /path: 'overseas-warehouse\/labeling\/create'[\s\S]*?props: \{ service: 'labeling', createPage: true \}[\s\S]*?permission: 'merchant:overseas-warehouse:relabel:create'/) - assert.match(routes, /path: 'overseas-warehouse\/return-relabel\/create'[\s\S]*?props: \{ service: 'relabel', createPage: true \}[\s\S]*?permission: 'merchant:overseas-warehouse:return-order:create'/) + assert.match(routes, /path: 'overseas-warehouse\/return-relabel\/create'[\s\S]*?ReturnOrdersView\.vue'[\s\S]*?props: \{ createPage: true \}[\s\S]*?title: '新建退货预报'[\s\S]*?permission: 'merchant:overseas-warehouse:return-order:create'/) assert.match(services, /props\.createPage \? 'create' : 'list'/) assert.match(services, /function returnToList\(\)/) + assert.match(returns, /props\.createPage/) + assert.match(returns, /class="return-create-surface"/) }) test('opens warehouse service and return receipt details as dedicated protected workspace pages', () => { diff --git a/src/modules/overseas-warehouse/routes.ts b/src/modules/overseas-warehouse/routes.ts index 93ee9f0..f9a225c 100644 --- a/src/modules/overseas-warehouse/routes.ts +++ b/src/modules/overseas-warehouse/routes.ts @@ -24,8 +24,8 @@ export const overseasWarehouseModule = { }, { path: 'overseas-warehouse/return-relabel/create', name: 'overseas-return-relabel-create', - component: () => import('./views/WarehouseServiceView.vue'), props: { service: 'relabel', createPage: true }, release: 'active', - meta: { title: '新建退货换标单', workspaceTitle: '退货换标 · 新建', description: '填写并提交退货换标订单', permission: 'merchant:overseas-warehouse:return-order:create' }, + component: () => import('./views/ReturnOrdersView.vue'), props: { createPage: true }, release: 'active', + meta: { title: '新建退货预报', workspaceTitle: '退货预报 · 新建', description: '填写并提交海外仓退货预报', permission: 'merchant:overseas-warehouse:return-order:create', keepAlive: false }, }, { path: 'overseas-warehouse/return-relabel/:returnNo/detail', name: 'overseas-return-relabel-detail', diff --git a/src/modules/overseas-warehouse/views/ReturnOrdersView.test.mjs b/src/modules/overseas-warehouse/views/ReturnOrdersView.test.mjs index 22d2073..77975ae 100644 --- a/src/modules/overseas-warehouse/views/ReturnOrdersView.test.mjs +++ b/src/modules/overseas-warehouse/views/ReturnOrdersView.test.mjs @@ -27,9 +27,13 @@ test('新建退货预报选择海外仓后带出联系人和电话', () => { assert.match(view, /warehouseContactPhone: form\.warehouseContactPhone\.trim\(\)/) }) -test('新建退货预报使用加宽的双列表单弹窗', () => { +test('新建退货预报使用独立路由页面,编辑仍保留加宽弹框', () => { + assert.match(view, /defineProps<\{ createPage\?: boolean; detailPage\?: boolean/) + assert.match(view, /name: 'overseas-return-relabel-create'/) + assert.match(view, /v-if="props\.createPage"/) + assert.match(view, /class="return-create-surface"/) + assert.match(view, /

新建退货预报<\/h2>/) assert.match(view, /:title="editingReturnNo \? '编辑退货预报' : '新建退货预报'" width="1120px"/) - assert.match(view, //) assert.match(view, /return-create-form \{ display:grid; grid-template-columns:repeat\(2,minmax\(0,1fr\)\)/) }) diff --git a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue index 01de759..e8737cd 100644 --- a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue +++ b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue @@ -10,7 +10,7 @@ import { useAuthStore } from '@/modules/auth/public' import { getMerchantWarehouses, type MerchantWarehouse } from '@/modules/first-leg/public' import { createReturnOrder, downloadReturnPhoto, getReturnOrder, listReturnOrders, updateReturnOrder, type ReturnOrderDetail, type ReturnOrderSummary, type ReturnReceipt } from '../api/returnOrders' -const props = withDefaults(defineProps<{ detailPage?: boolean; returnNo?: string }>(), { detailPage: false, returnNo: '' }) +const props = withDefaults(defineProps<{ createPage?: boolean; detailPage?: boolean; returnNo?: string }>(), { createPage: false, detailPage: false, returnNo: '' }) const router = useRouter() const route = useRoute() const detailReturnNo = computed(() => props.returnNo || String(route.params.returnNo || '')) @@ -110,10 +110,7 @@ async function loadOperationWarehouses() { } finally { operationWarehousesLoading.value = false } } function openCreate() { - editingReturnNo.value = '' - resetForm() - showCreate.value = true - if (!operationWarehouses.value.length && !operationWarehousesLoading.value) void loadOperationWarehouses() + void router.push({ name: 'overseas-return-relabel-create' }) } async function openEdit(returnNo: string) { const detail = await getReturnOrder(returnNo) @@ -176,6 +173,7 @@ function previewPhoto(fileId: string | number) { } function openDetail(returnNo: string) { void router.push({ name: 'overseas-return-relabel-detail', params: { returnNo } }) } function returnToList() { void router.push({ name: 'overseas-return-relabel' }) } +function cancelCreate() { resetForm(); void router.push({ name: 'overseas-return-relabel' }) } function canApplyRelabel(order: { status?: unknown; needRelabel?: unknown; relabelNo?: unknown }) { return order.status === 'COMPLETED' && order.needRelabel === true && !order.relabelNo } function openRelabel(order: Pick) { void router.push({ name: 'overseas-labeling-create', query: { returnNo: order.returnNo, warehouseId: String(order.overseasWarehouseId) } }) @@ -218,19 +216,48 @@ function formatDateTime(value?: string | null) { return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).format(date) } onMounted(() => { - if (props.detailPage) void Promise.all([loadDetail(), loadOperationWarehouses()]) + if (props.createPage) { resetForm(); void loadOperationWarehouses() } + else if (props.detailPage) void Promise.all([loadDetail(), loadOperationWarehouses()]) else void Promise.all([load(), loadOperationWarehouses()]) }) watch(() => [query.page, query.size] as const, ([nextPage, nextSize], [previousPage, previousSize]) => { if (nextSize !== previousSize && nextPage !== 1) { query.page = 1; return } - if (!props.detailPage) void load() + if (!props.createPage && !props.detailPage) void load() }) onBeforeUnmount(clearPhotoUrls)