feat(client): optimize first-leg order actions

This commit is contained in:
2026-09-14 17:18:56 +08:00
parent cd057845bf
commit c2611a1bfd
5 changed files with 69 additions and 16 deletions
@@ -8,6 +8,7 @@ const editorShellSource = readFileSync(new URL('../components/FirstLegOrderEdito
const progressSource = readFileSync(new URL('../components/OrderProgressPanel.vue', import.meta.url), 'utf8')
const customsDialogSource = readFileSync(new URL('../components/CustomsDocumentsDialog.vue', import.meta.url), 'utf8')
const customsApiSource = readFileSync(new URL('../api/customs.ts', import.meta.url), 'utf8')
const orderStoreSource = readFileSync(new URL('../store/firstLegOrders.ts', import.meta.url), 'utf8')
test('routes the confirmed first-leg path to the implemented order view', () => {
assert.match(routerSource, /path: 'orders\/first-leg'[\s\S]*?component: \(\) => import\('\.\/views\/FirstLegOrdersView\.vue'\)[\s\S]*?release: 'active'/)
@@ -88,7 +89,7 @@ test('uses the shared query toolbar and data table without metric cards', () =>
assert.match(source, /import QueryToolbar, \{ type QueryField, type QueryModel \}/)
assert.match(source, /import DataTable, \{ type DataTableColumn \}/)
assert.match(source, /const filters = ref<QueryModel>/)
assert.match(source, /<QueryToolbar v-model="filters" class="first-leg-query-toolbar" :fields="queryFields" ariaLabel="订单查询" @search="searchOrders">/)
assert.match(source, /<QueryToolbar v-model="filters" class="first-leg-query-toolbar" :fields="queryFields" ariaLabel="订单查询" @search="searchOrders" \/>/)
assert.match(source, /async function searchOrders\(model: QueryModel\)/)
assert.match(source, /await store\.load\(\{/)
assert.match(source, /<DataTable v-model:page="tablePage" v-model:page-size="tablePageSize" :data="pagedOrders" :columns="visibleOrderColumns"/)
@@ -96,7 +97,7 @@ test('uses the shared query toolbar and data table without metric cards', () =>
assert.doesNotMatch(source, /order-metrics|订单概览/)
})
test('adds prototype download actions to the order query panel', () => {
test('adds download actions to the order-list toolbar', () => {
assert.match(source, /下载唛头/)
assert.match(source, /导出订单信息/)
assert.match(source, /function downloadShippingMarks\(\)/)
@@ -237,12 +238,12 @@ test('keeps the seven-stage progress and business summary usable on mobile', ()
})
test('keeps the first viewport compact and moves create into the table toolbar', () => {
const queryToolbarSource = source.slice(source.indexOf('<QueryToolbar'), source.indexOf('</QueryToolbar>') + '</QueryToolbar>'.length)
const tableToolbarSource = source.slice(source.indexOf('class="order-table-toolbar"'), source.indexOf('class="order-eligibility is-pending"'))
assert.match(source, /class="order-table-toolbar"/)
assert.match(source, /<strong>订单列表<\/strong><span>共 \{\{ filteredOrders\.length \}\} 条<\/span>/)
assert.match(source, /class="order-table-toolbar"[\s\S]*order:first-leg:create[\s\S]*创建订单[\s\S]*class="order-eligibility is-pending"/)
assert.match(queryToolbarSource, /<template #actions>[\s\S]*下载唛头[\s\S]*导出订单信息/)
assert.doesNotMatch(queryToolbarSource, /order:first-leg:create|创建订单/)
assert.match(tableToolbarSource, /下载唛头[\s\S]*导出订单信息[\s\S]*批量提交草稿[\s\S]*创建订单/)
assert.doesNotMatch(source.slice(source.indexOf('<QueryToolbar'), source.indexOf('<div class="client-card order-table-card">')), /下载唛头|导出订单信息|创建订单/)
assert.match(source, /client-main:has\(> \.first-leg-page:not\(\.is-create-route\)\) > \.client-page-heading > div\) \{ position: absolute; width: 1px; height: 1px;/)
})
@@ -532,11 +533,18 @@ test('opens billing-weight confirmation independently from order details', () =>
assert.match(source, /unavailable-message="未推送计费重"/)
})
test('shows the standalone billing-weight entry at every order node', () => {
test('shows billing-weight confirmation only when the backend marks it pending', () => {
const templateSource = source.slice(source.indexOf('<template>'), source.lastIndexOf('</template>'))
const entries = templateSource.match(/<el-button link type="primary" @click="openFeeConfirmation\([^)]*\)">确认计费重<\/el-button>/g) ?? []
const entries = templateSource.match(/<el-button v-if="canConfirmInboundFee && [^"]*customerFeeConfirmationRequired" link type="primary" @click="openFeeConfirmation\([^)]*\)">确认计费重<\/el-button>/g) ?? []
assert.equal(entries.length, 2)
assert.doesNotMatch(templateSource, /v-if="[^"]*status === 'WAIT_SPLIT'[^"]*"[^>]*>确认计费重/)
assert.match(orderStoreSource, /customerFeeConfirmationRequired: summary\?\.customerFeeConfirmationRequired \?\? false/)
})
test('submits only selected draft orders in one batch action', () => {
assert.match(source, /selectedDraftOrders = computed\(\(\) => selectedOrders\.value\.filter\(\(order\) => order\.status === 'DRAFT'\)\)/)
assert.match(source, /Promise\.allSettled\(drafts\.map\(\(order\) => submitMerchantFirstLegOrder/)
assert.match(source, /createIdempotencyKey\(`first-leg-batch-submit-\$\{order\.id\}`\)/)
assert.match(source, /v-if="canSubmitOrder"[\s\S]*批量提交草稿/)
})
test('discards stale inbound billing responses when billing views close or the user changes orders', () => {