头程下单<\/h1>/)
assert.match(createHubSource, /
[\s\S]*order-mode-switch[\s\S]*选择下单方式/)
assert.doesNotMatch(createHubSource, /填写货物信息,创建新的头程运输订单/)
assert.match(source, /\.is-create-route \.prototype-order-form \{[^}]*align-items: start/)
assert.doesNotMatch(source, /\.is-create-route \.order-basic-section, \.is-create-route \.destination-section \{ height: 100%; \}/)
assert.doesNotMatch(source, /\.is-create-route \.order-basic-section > \.order-section-heading, \.is-create-route \.destination-section > \.order-section-heading \{[^}]*(?:height|min-height):/)
assert.match(source, /\.is-create-route \.order-basic-section > \.order-section-heading h3, \.is-create-route \.destination-section > \.order-section-heading h3 \{[^}]*font-size: 17px[^}]*line-height: 24px/)
assert.match(source, /\.is-create-route \.order-step-badge \{[^}]*width: 30px[^}]*height: 30px/)
assert.match(source, /\.is-create-route \.order-section-context \{[^}]*margin-left: auto/)
assert.match(source, /\.is-create-route \.warehouse-options :deep\(\.el-radio\.is-checked\) \{[^}]*linear-gradient/)
})
test('shows an optional LX inbound order number for one-click dropship orders', () => {
assert.match(source, /v-if="form\.fulfillmentType === 'ONE_CLICK_DROPSHIP'" label="LX入库单号" prop="lxCode"/)
assert.match(source, /v-model="form\.lxCode"[^>]*placeholder=""/)
assert.doesNotMatch(source, /label="LX入库单号"[^>]*required/)
})
test('loads only active server channels for the selected domestic warehouse', () => {
assert.match(source, /getMerchantPricingChannels\(warehouseId\)/)
assert.match(source, /const channelOptions = ref\(\[\]\)/)
assert.match(source, /channelOptions\.value = \[\]/)
assert.match(source, /form\.channelCode = ''/)
assert.match(source, /sequence !== channelRequestSequence \|\| form\.receivingWarehouseId !== warehouseId/)
assert.match(source, /channel\.pricingTaxModes\.includes\(form\.pricingTaxMode\)/)
assert.match(source, /availablePricingTaxModes/)
assert.match(source, /:loading="channelLoading"/)
assert.match(source, /:disabled="!form\.receivingWarehouseId \|\| channelLoading"/)
assert.match(source, /label="报价包税方式" prop="pricingTaxMode" required class="pricing-tax-mode-field"/)
assert.match(source, /\.compact-transport-grid > :deep\(\.pricing-tax-mode-field\) \{ display: none; \}/)
assert.doesNotMatch(source, /\.compact-transport-grid > :deep\(\.el-form-item:nth-child\(2\)\)/)
assert.match(source, /当前收货仓暂无可用渠道/)
assert.match(source, /渠道加载失败/)
assert.match(source, /@click="retryPricingChannels"/)
assert.doesNotMatch(source, /SEA-US-GENERAL|SEA-US-SENSITIVE|SEA-US-EXPRESS|美线 FBA 直送/)
assert.doesNotMatch(source, /channelOptions\.some\(\(channel\) => channel\.code/)
})
test('estimates by warehouse, destination, tax mode, weight and volume without blocking saves', () => {
assert.match(source, /estimateMerchantFirstLegPrice\(request\)/)
assert.match(source, /originWarehouseId: form\.receivingWarehouseId/)
assert.match(source, /destinationCode: form\.destinationType === 'FBA' \? form\.amazonWarehouseCode : undefined/)
assert.match(source, /destinationWarehouseId: form\.destinationType === 'OVERSEAS'/)
assert.match(source, /pricingTaxMode: form\.pricingTaxMode/)
assert.match(source, /actualWeightKg: summary\.grossWeightKg/)
assert.match(source, /actualVolumeCbm: summary\.volumeCbm/)
assert.match(source, /setTimeout\(\(\) => void loadPriceEstimate\(\), 300\)/)
assert.match(source, /sequence === estimateRequestSequence/)
assert.match(source, /您仍可正常保存订单草稿/)
assert.match(source, /v-for="mode in availablePricingTaxModes"/)
assert.match(source, /pricingTaxModeLabel\(mode\)/)
assert.match(source, /priceEstimate\.chargeableQuantity/)
assert.match(source, /priceEstimateBreakdown\.actualLabel/)
assert.match(source, /priceEstimateBreakdown\.convertedLabel/)
assert.match(source, /priceEstimateBreakdown\.basisLabel/)
assert.match(source, /两者取大/)
assert.match(source, /priceEstimate\.unitPrice/)
assert.match(source, /priceEstimate\.estimatedAmount/)
assert.match(source, /priceEstimateDisclaimer/)
assert.doesNotMatch(source, /3,310|2,990|2,500|静态预估展示/)
assert.doesNotMatch(source, /当前价格表不提供不包税报价|历史草稿的不包税设置/)
const saveSource = source.slice(source.indexOf('async function saveDraft()'), source.indexOf('async function submitOrder()'))
assert.doesNotMatch(saveSource, /loadPriceEstimate|priceEstimateError|estimateMerchantFirstLegPrice/)
})
test('keeps the reference estimate readable on narrow screens', () => {
assert.match(source, /\.price-estimate__result \{ grid-template-columns: 1fr; \}/)
assert.match(source, /\.price-estimate__result > small \{ grid-column: auto; \}/)
})
test('shows field-level validation and concise guidance for required order inputs', () => {
assert.match(source, /ref="orderFormRef"[^>]*:model="form" :rules="orderFormRules"/)
assert.match(source, /prop="shipperPartySnapshot\.contactName" required/)
assert.match(source, /prop="consigneePartySnapshot\.address" required/)
assert.match(source, /:prop="`items\.\$\{index\}\.cargoNameCn`" required/)
assert.match(source, /form\.destinationType === 'FBA' \|\| form\.fulfillmentType === 'ONE_CLICK_DROPSHIP' \? '必填' : '选填'/)
assert.match(source, /SKU NO\. 和 UPC NO\. 均为选填项/)
assert.match(source, /一件代发必须填写 SKU/)
assert.match(source, /:prop="`items\.\$\{index\}\.grossWeightKg`" required/)
assert.match(source, /\*<\/span>总毛重/)
assert.match(source, /\*<\/span>总体积/)
assert.match(source, /:prop="`items\.\$\{index\}\.upc`">\s*]*placeholder="UPC NO\.(选填)"/)
assert.doesNotMatch(source, /:prop="`items\.\$\{index\}\.upc`"[^>]*(?:required|:rules)/)
assert.match(source, /UPC NO\. 选填/)
assert.doesNotMatch(source, /UPC必填/)
assert.match(source, /v-model="item\.cargoNameCn"[^>]*placeholder="中文品名"/)
assert.match(source, /\.order-form :deep\(\.el-form-item__error\).*position: static/)
})
test('collects snapshots only for pickup and private destinations', () => {
assert.doesNotMatch(source, /firstLegPartySource|v-model="form\.(?:shipper|consignee)PartyId"/)
assert.match(source, /form\.pickupMethod === 'PICKUP'/)
assert.match(source, /form\.destinationType === 'PRIVATE'/)
assert.match(source, /form\.shipperPartySnapshot\.contactName/)
assert.match(source, /form\.consigneePartySnapshot\.address/)
assert.match(source, /syncPrivateDestinationName/)
assert.match(source, /changePickupMethod/)
})
test('shows fulfillment courier information as read-only client detail', () => {
assert.match(source, /履约快递信息/)
assert.match(source, /detailOrder\.expressCompanyName/)
assert.match(source, /detailOrder\.trackingNumber/)
assert.match(source, /快递公司由平台维护/)
assert.doesNotMatch(source, /v-model="form\.expressCompanyName"/)
})
test('orders pickup choices and offers an optional tracking number only for express pickup', () => {
const group = source.match(//)[0]
assert.deepEqual([...group.matchAll(/value="([A-Z_]+)"/g)].map(match => match[1]), ['SELF_TRUCK', 'PICKUP', 'SELF_EXPRESS'])
assert.match(group, /value="SELF_EXPRESS">快递自提/)
const field = source.match(/]*label="快递单号"[\s\S]*?<\/el-form-item>/)[0]
assert.match(field, /v-model="form\.trackingNumber" maxlength="128"/)
assert.doesNotMatch(field, /\brequired\b|:rules=/)
assert.match(source, /trackingNumber: order\.pickupMethod === 'SELF_EXPRESS' \? order\.trackingNumber : ''/)
assert.match(source, /if \(form\.pickupMethod !== 'SELF_EXPRESS'\) form\.trackingNumber = ''/)
})
test('shows the full customer-safe order detail without platform-only controls', () => {
const detailSource = source.slice(source.indexOf('', source.indexOf('${heading}<\\/h3>`))
}
for (const field of [
'贸易条款', '发货方式', '报关方式', '运输渠道', '收货要求', '目的仓类型', '海关查验',
'提交时间', '完成时间', 'SKU NO.', 'UPC NO.', '报关 HS CODE', '清关 HS CODE', '每箱数量',
'总净重', '清关申报单价', '中英文材质', '中英文用途', '产品规格', '货件编号',
'跟踪编号', '危险品',
]) {
assert.match(source, new RegExp(field))
}
assert.doesNotMatch(detailSource, /承运商|待平台指派/)
assert.match(source, /detailOrder\.customerRemark/)
assert.doesNotMatch(detailSource, /内部备注|审核通过|添加备注/)
})
test('opens order detail as a protected workspace page and paginates cargoes as a read-only table', () => {
assert.match(routerSource, /path: 'orders\/first-leg\/:orderId\/detail'[\s\S]*?name: 'first-leg-order-detail'[\s\S]*?props: \{ detailPage: true \}[\s\S]*?permission: 'order:first-leg:list'/)
assert.match(source, /router\.push\(\{ name: 'first-leg-order-detail', params: \{ orderId: order\.id \} \}\)/)
assert.match(source, //)
assert.doesNotMatch(source, /]*class="cargo-detail-table"/)
assert.match(source, /v-model:current-page="detailCargoPage"/)
assert.match(source, /v-model:page-size="detailCargoPageSize"/)
assert.match(source, /:total="detailOrder\.items\.length"/)
assert.doesNotMatch(source, /class="cargo-detail-list"/)
assert.match(source, /\.first-leg-detail-page \{[^}]*padding: 10px 14px 20px;[^}]*border: 1px solid var\(--client-border\);[^}]*border-radius: var\(--client-radius\);[^}]*background: #fff;/)
assert.match(source, /\.order-detail-grid div \{[^}]*min-height: 34px;[^}]*padding: 3px 8px;/)
})
test('keeps shared button hierarchy compact and consistent', () => {
assert.match(querySource, /class="query-toolbar__search" type="primary"/)
assert.match(querySource, /class="query-toolbar__reset"/)
assert.match(tableSource, /v-for="action in splitTableActions\(rowActions\(row\)\)\.visible"[\s\S]*?link type="primary"/)
assert.match(clientUiSource, /--client-control-height: 32px/)
assert.match(clientUiSource, /\.client-ui \.el-button \{[\s\S]*?min-width: 68px;[\s\S]*?font-weight: 600;/)
assert.match(clientUiSource, /\.client-ui \.el-button\.is-link, \.client-ui \.el-button\.is-text \{[\s\S]*?min-width: 0;[\s\S]*?background: transparent;/)
assert.match(clientUiSource, /\.client-ui \.el-button svg \{[\s\S]*?width: 16px; height: 16px;/)
})
test('loads merchant inbound billing as an isolated read-only detail section', () => {
assert.match(source, /import InboundBillingPanel/)
assert.match(source, /import \{ getMerchantInboundBilling \}/)
assert.match(source, /void loadInboundBilling\(detailedOrder\)/)
assert.match(source, / {
const templateSource = source.slice(source.indexOf(''), source.lastIndexOf(''))
assert.doesNotMatch(templateSource, /租户|tenantId|所属企业|企业筛选/)
})
test('opens billing-weight confirmation independently from order details', () => {
const handler = source.slice(source.indexOf('function openFeeConfirmation'), source.indexOf('async function retryDetail'))
assert.match(handler, /feeConfirmationOpen\.value = true/)
assert.match(handler, /loadInboundBilling\(order, '未推送费用'\)/)
assert.doesNotMatch(handler, /openDetail\(/)
assert.match(source, /v-if="feeConfirmationOpen"[\s\S]*dialog-only[\s\S]*auto-open/)
assert.match(source, /unavailable-message="未推送费用"/)
})
test('only offers published-fee confirmation for pending orders with confirmation permission', () => {
const actions = source.slice(source.indexOf('function getOrderRowActions'), source.indexOf('function getOrderRowActions') + 1800)
assert.match(actions, /actions\.push\(\{ key: 'fee', label: '确认计费重', run: \(\) => openFeeConfirmation\(order\) \}\)/)
assert.match(actions, /if \(canConfirmInboundFee\.value && order\.businessSummary\.customerFeeConfirmationRequired\) \{\s*actions\.push\(\{ key: 'fee'/)
assert.doesNotMatch(actions, /label: '确认费用'|key: 'weight'/)
assert.doesNotMatch(source, /ChargeableWeightDialog|weightConfirmationOrderId/)
assert.match(source, /:row-actions="getOrderRowActions"/)
assert.match(orderStoreSource, /customerFeeConfirmationRequired: summary\?\.customerFeeConfirmationRequired \?\? false/)
})
test('hides confirmation for confirmed, unpushed and unauthorized orders and refreshes after confirmation', () => {
const start = source.indexOf('function getOrderRowActions')
const end = source.indexOf('\nasync function copyOrder', start)
const body = source.slice(start, end)
.replace('function getOrderRowActions(row: object): TableAction[]', 'function getOrderRowActions(row)')
.replace('const order = row as FirstLegOrder', 'const order = row')
.replace('const actions: TableAction[]', 'const actions')
const actionsFor = new Function('canConfirmInboundFee', 'canCreateOrder', 'canEditOrder',
'canOfferCancellation', 'eligibleCustomsDetail', 'openFeeConfirmation',
`${body}; return getOrderRowActions`)
for (const [permitted, pending] of [[true, true], [true, false], [false, true], [false, false]]) {
const opened = []
const order = { id: 'order-1', businessSummary: { customerFeeConfirmationRequired: pending } }
const getActions = actionsFor({ value: permitted }, { value: false }, { value: false },
() => false, () => false, row => opened.push(row.id))
const confirm = getActions(order).filter(action => action.key === 'fee')
assert.equal(confirm.length, permitted && pending ? 1 : 0)
if (confirm.length) {
confirm[0].run()
assert.deepEqual(opened, ['order-1'])
}
}
assert.match(source, /function handleInboundFeeConfirmed\(\) \{\s*if \(!isCreatePage\.value && !isDetailPage\.value\) void loadOrderPage\(\)/)
})
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\(ids\.map\(id => store\.submitSaved/)
assert.doesNotMatch(source, /submitMerchantFirstLegOrder/)
assert.match(source, /v-if="canSubmitOrder"[\s\S]*批量提交草稿/)
})
test('discards stale inbound billing responses when billing views close or the user changes orders', () => {
assert.match(source, /let inboundBillingRequestSequence = 0/)
assert.match(source, /const sequence = \+\+inboundBillingRequestSequence/)
assert.match(source, /sequence === inboundBillingRequestSequence[\s\S]*inboundBillingOrderId\.value === orderId[\s\S]*isDetailPage\.value \|\| feeConfirmationOpen\.value/)
assert.doesNotMatch(source, /watch\(detailOpen/)
assert.match(source, /watch\(feeConfirmationOpen,[\s\S]*resetInboundBillingState\(\)/)
})
test('protects unsaved drafts and exposes recoverable load failures', () => {
assert.match(source, /useUnsavedWorkRegistration\(/)
assert.match(source, /routeKey: unsavedRouteKey/)
assert.doesNotMatch(source, /onBeforeRouteLeave|beforeunload/)
assert.match(source, /confirmDiscardChanges/)
assert.match(source, /:before-close="requestCloseEditor"/)
assert.match(source, /store\.loadError/)
assert.match(source, /订单数据加载失败/)
assert.match(source, /订单详情加载失败/)
assert.match(source, /部分订单配套数据加载失败/)
assert.doesNotMatch(source, /往来单位加载失败/)
assert.match(source, /企业资料加载失败/)
assert.match(source, /@click="loadPageData"/)
assert.match(source, /@click="retryDetail"/)
})
test('copies reactive order drafts into plain request data', () => {
assert.match(source, /function cloneDraft\(draft: FirstLegOrderDraft\)/)
assert.match(source, /items: draft\.items\.map\(\(item\) => \(\{ \.\.\.item \}\)\)/)
assert.match(source, /store\.saveDraft\(cloneDraft\(form\)/)
assert.match(source, /editingId\.value = savedOrder\.id/)
assert.match(source, /store\.submitSaved\(savedOrder\.id/)
assert.doesNotMatch(source, /structuredClone\((?:form|order\.)/)
})
test('opens the server-owned inbound-code association from the order detail', () => {
assert.match(source, /import InboundCodeAssociationDialog/)
assert.match(source, /function openInboundCodeAssociation\(inboundCode: string\)/)
assert.doesNotMatch(source, /#inboundCode[\s\S]*?openInboundCodeAssociation\(\(row as FirstLegOrder\)\.businessSummary\.inboundCode\)/)
assert.match(source, /入仓码<\/dt>