优化
This commit is contained in:
@@ -215,8 +215,9 @@ test('distills order creation into the confirmed prototype sections with server
|
||||
assert.ok(source.indexOf('<h3>目的地信息</h3>') < source.indexOf('<h3>货物明细</h3>'))
|
||||
assert.match(source, /class="segmented-options"/)
|
||||
assert.match(source, /class="prototype-form-row prototype-form-row--tabs"/)
|
||||
assert.match(source, /class="cargo-primary-grid"/)
|
||||
assert.match(source, /title="更多申报信息"/)
|
||||
for (const heading of ['商品信息', '箱规、数量与重量', '报关与产品资料', '货件与备注']) {
|
||||
assert.match(source, new RegExp(`<h4>${heading}</h4>`))
|
||||
}
|
||||
assert.match(source, /参考运费/)
|
||||
assert.match(source, /仅供参考,最终以实际结算为准/)
|
||||
assert.doesNotMatch(source, /v-model="form\.(?:businessType|origin|destination|priority|tradeTerm)"/)
|
||||
@@ -268,7 +269,7 @@ test('shows field-level validation and concise guidance for required order input
|
||||
assert.match(source, /prop="consigneePartySnapshot\.address" required/)
|
||||
assert.match(source, /:prop="`items\.\$\{index\}\.cargoNameCn`" required/)
|
||||
assert.match(source, /:prop="`items\.\$\{index\}\.grossWeightKg`" required/)
|
||||
assert.match(source, /label="UPC".*required.*v-model="item\.upc"/)
|
||||
assert.match(source, /label="UPC NO\."[^>]*:required="form\.destinationType === 'FBA'"[^>]*>\s*<el-input v-model="item\.upc"/)
|
||||
assert.match(source, /placeholder="例如:蓝牙音箱"/)
|
||||
assert.match(source, /\.order-form :deep\(\.el-form-item__error\).*position: static/)
|
||||
})
|
||||
@@ -297,7 +298,12 @@ test('shows the full customer-safe order detail without platform-only controls',
|
||||
for (const heading of ['订单与运输', '收发货信息', '关键业务摘要', '履约快递信息', '货物明细']) {
|
||||
assert.match(source, new RegExp(`<h3>${heading}<\\/h3>`))
|
||||
}
|
||||
for (const field of ['贸易条款', '发货方式', '报关方式', '运输渠道', '收货要求', '目的仓类型', '海关查验', '提交时间', '完成时间', 'SKU / UPC', 'HS 编码', '申报价值', '危险品']) {
|
||||
for (const field of [
|
||||
'贸易条款', '发货方式', '报关方式', '运输渠道', '收货要求', '目的仓类型', '海关查验',
|
||||
'提交时间', '完成时间', 'SKU NO.', 'UPC NO.', '报关 HS CODE', '清关 HS CODE', '每箱数量',
|
||||
'总净重', '清关申报单价', '中英文材质', '中英文用途', '产品规格', 'Shipment ID',
|
||||
'Reference ID', '危险品',
|
||||
]) {
|
||||
assert.match(source, new RegExp(field))
|
||||
}
|
||||
assert.doesNotMatch(detailSource, /承运商|待平台指派/)
|
||||
|
||||
@@ -394,7 +394,10 @@ watch(isCreatePage, (isCreate, wasCreate) => {
|
||||
}, { immediate: true })
|
||||
|
||||
watch(detailOpen, (open) => {
|
||||
if (!open) resetInboundBillingState()
|
||||
if (!open) {
|
||||
resetInboundBillingState()
|
||||
if (detailOrder.value) releaseProductImagePreviews(detailOrder.value.items)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -942,7 +945,8 @@ function removeCargoItem(index: number) {
|
||||
ElMessage.warning('订单至少需要保留一条货物明细')
|
||||
return
|
||||
}
|
||||
form.items.splice(index, 1)
|
||||
const [removed] = form.items.splice(index, 1)
|
||||
if (removed) releaseProductImagePreviews([removed])
|
||||
resetEditorValidation()
|
||||
}
|
||||
|
||||
@@ -1083,7 +1087,7 @@ async function searchOrders(model: QueryModel) {
|
||||
<template #order="{ row }">
|
||||
<button class="order-number-link" type="button" @click="openDetail(row as FirstLegOrder)">{{ (row as FirstLegOrder).orderNo || '未提交草稿' }}</button>
|
||||
<span v-if="(row as FirstLegOrder).businessSummary.inboundCode" class="order-reference">入仓码 {{ (row as FirstLegOrder).businessSummary.inboundCode }}</span>
|
||||
<span class="order-reference">{{ (row as FirstLegOrder).referenceNo || '无客户参考号' }}</span>
|
||||
<span class="order-reference">{{ (row as FirstLegOrder).referenceNo || '无 Reference ID' }}</span>
|
||||
</template>
|
||||
<template #route="{ row }"><strong>{{ (row as FirstLegOrder).destination || '目的地待更新' }}</strong><span class="order-reference">{{ (row as FirstLegOrder).transportMode ? getFirstLegTransportModeLabel((row as FirstLegOrder).transportMode) : (row as FirstLegOrder).channelName || '渠道待更新' }}</span></template>
|
||||
<template #cargo="{ row }">{{ getOrderCargoSummary(row as FirstLegOrder) }}</template>
|
||||
@@ -1101,7 +1105,7 @@ async function searchOrders(model: QueryModel) {
|
||||
<article v-for="order in filteredOrders" :key="order.id" class="mobile-order-card">
|
||||
<header><button type="button" @click="openDetail(order)">{{ order.orderNo || '未提交草稿' }}</button><el-tag :type="getFirstLegStatusTone(order.status)" effect="light">{{ getFirstLegStatusLabel(order.status) }}</el-tag></header>
|
||||
<span v-if="order.businessSummary.inboundCode" class="order-reference">入仓码 {{ order.businessSummary.inboundCode }}</span>
|
||||
<span class="order-reference">{{ order.referenceNo || '无客户参考号' }}</span>
|
||||
<span class="order-reference">{{ order.referenceNo || '无 Reference ID' }}</span>
|
||||
<dl><div><dt>目的地</dt><dd>{{ order.destination || '待更新' }}</dd></div><div><dt>收货仓</dt><dd>{{ order.receivingWarehouseName || '待更新' }}</dd></div><div><dt>货物摘要</dt><dd>{{ getOrderCargoSummary(order) }}</dd></div><div><dt>运输渠道</dt><dd>{{ order.transportMode ? getFirstLegTransportModeLabel(order.transportMode) : order.channelName || '待更新' }}</dd></div></dl>
|
||||
<footer><span>更新于 {{ formatDateTime(order.updatedAt) }}</span><div><el-button link type="primary" @click="openDetail(order)"><Eye :size="15" />详情</el-button><el-button v-if="canEditOrder && canClientEditFirstLegOrder(order.status)" link type="primary" :loading="openingEditor" @click="openEdit(order)"><Pencil :size="15" />编辑</el-button></div></footer>
|
||||
</article>
|
||||
@@ -1243,13 +1247,6 @@ async function searchOrders(model: QueryModel) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="form.transportMode === 'FCL'" class="cargo-field-section">
|
||||
<h4>整柜信息</h4>
|
||||
<div class="cargo-form-grid">
|
||||
<el-form-item label="箱型" :prop="`items.${index}.containerType`" required :rules="requiredSelectRules('请选择箱型')"><el-select v-model="item.containerType"><el-option v-for="type in ['20GP', '40GP', '40HQ']" :key="type" :label="type" :value="type" /></el-select></el-form-item>
|
||||
<el-form-item label="柜量" :prop="`items.${index}.containerCount`" required :rules="positiveNumberRules('柜量必须为大于 0 的整数', true)"><el-input-number v-model="item.containerCount" :min="1" controls-position="right" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
<aside class="price-estimate" aria-live="polite">
|
||||
<div class="price-estimate__heading"><div><strong>参考运费</strong><span>仅供参考,最终以实际结算为准</span></div><el-button v-if="priceEstimateError" link type="primary" @click="loadPriceEstimate">重新估价</el-button></div>
|
||||
@@ -1279,7 +1276,6 @@ async function searchOrders(model: QueryModel) {
|
||||
<h3>订单与运输</h3>
|
||||
<dl class="order-detail-grid">
|
||||
<div v-if="detailOrder.businessSummary.inboundCode"><dt>入仓码</dt><dd>{{ detailOrder.businessSummary.inboundCode }}</dd></div>
|
||||
<div><dt>客户参考号</dt><dd>{{ displayValue(detailOrder.referenceNo) }}</dd></div>
|
||||
<div><dt>创建时间</dt><dd>{{ formatDateTime(detailOrder.createdAt) }}</dd></div>
|
||||
<div><dt>运输方式</dt><dd>{{ getFirstLegTransportModeLabel(detailOrder.transportMode) }}</dd></div>
|
||||
<div><dt>贸易条款</dt><dd>{{ displayValue(detailOrder.tradeTerm) }}</dd></div>
|
||||
@@ -1291,7 +1287,6 @@ async function searchOrders(model: QueryModel) {
|
||||
<div><dt>目的仓类型</dt><dd>{{ destinationTypeLabels[detailOrder.destinationType] }}</dd></div>
|
||||
<div><dt>目的国家 / 仓库</dt><dd>{{ detailOrder.destinationCountryCode || '-' }} · {{ detailOrder.destinationWarehouseName || '-' }}</dd></div>
|
||||
<div v-if="detailOrder.destinationType === 'FBA'"><dt>Amazon 仓库代码</dt><dd>{{ displayValue(detailOrder.amazonWarehouseCode) }}</dd></div>
|
||||
<div v-if="detailOrder.destinationType === 'FBA'"><dt>Shipment ID</dt><dd>{{ displayValue(detailOrder.shipmentId) }}</dd></div>
|
||||
<div><dt>期望出运</dt><dd>{{ displayValue(detailOrder.expectedDepartureDate) }}</dd></div>
|
||||
<div><dt>海关查验</dt><dd>{{ detailOrder.customsInspection ? '需要' : '不需要' }}</dd></div>
|
||||
<div><dt>提交时间</dt><dd>{{ detailOrder.submittedAt ? formatDateTime(detailOrder.submittedAt) : '-' }}</dd></div>
|
||||
@@ -1317,7 +1312,30 @@ async function searchOrders(model: QueryModel) {
|
||||
<div v-if="detailOrder.expressCompanyName || detailOrder.trackingNumber" class="express-information"><PackageCheck :size="20" /><div><span>快递公司</span><strong>{{ detailOrder.expressCompanyName || '待平台补充' }}</strong></div><div><span>快递单号</span><strong>{{ detailOrder.trackingNumber || '待平台补充' }}</strong></div></div>
|
||||
<div v-else class="express-empty"><PackageCheck :size="20" /><div><strong>平台尚未维护快递信息</strong><span>快递公司和快递单号由平台后台维护,客户端仅只读展示。</span></div></div>
|
||||
</section>
|
||||
<section class="detail-section"><h3>货物明细</h3><div v-if="detailSummary" class="cargo-summary"><div><Box :size="18" /><span>明细</span><strong>{{ detailOrder.items.length }} 项</strong></div><div><span>件数</span><strong>{{ detailSummary.pieces }}</strong></div><div><span>毛重</span><strong>{{ detailSummary.grossWeightKg.toLocaleString() }} kg</strong></div><div><span>体积</span><strong>{{ detailSummary.volumeCbm }} m³</strong></div></div><div v-if="detailOrder.items.length" class="cargo-detail-list"><article v-for="(item, index) in detailOrder.items" :key="item.id"><header><span>货物 {{ index + 1 }}</span><strong>{{ item.cargoNameCn || '未命名货物' }}</strong><small>{{ item.cargoNameEn || '' }}</small></header><div v-if="item.productImageFileId" class="cargo-detail-image"><img v-if="item.productImagePreviewUrl" :src="item.productImagePreviewUrl" :alt="`${item.cargoNameCn || `货物 ${index + 1}`}产品图片`" /><span v-else-if="item.productImageUploading">图片加载中...</span><span v-else>{{ item.productImageError || '产品图片暂不可用' }}</span></div><dl><div><dt>SKU / UPC</dt><dd>{{ item.sku || '-' }} / {{ item.upc || '-' }}</dd></div><div><dt>HS 编码</dt><dd>{{ item.hsCode || '-' }}</dd></div><div><dt>包装 / 箱数</dt><dd>{{ packageTypeLabels[item.packageType] || item.packageType || '-' }} · {{ item.packageCount }} 箱</dd></div><div><dt>数量</dt><dd>{{ item.pieces }} 件</dd></div><div><dt>毛重</dt><dd>{{ item.grossWeightKg }} kg</dd></div><div><dt>体积</dt><dd>{{ item.volumeCbm }} m³</dd></div><div><dt>申报价值</dt><dd>{{ item.declaredValue ? `${item.currency} ${item.declaredValue.toLocaleString()}` : '-' }}</dd></div><div><dt>危险品</dt><dd>{{ item.dangerousGoods ? '是' : '否' }}</dd></div></dl><p v-if="item.remark">{{ item.remark }}</p></article></div><el-empty v-else description="暂无货物明细" :image-size="56" /></section>
|
||||
<section class="detail-section">
|
||||
<h3>货物明细</h3>
|
||||
<div v-if="detailSummary" class="cargo-summary"><div><Box :size="18" /><span>明细</span><strong>{{ detailOrder.items.length }} 项</strong></div><div><span>件数</span><strong>{{ detailSummary.pieces }}</strong></div><div><span>毛重</span><strong>{{ detailSummary.grossWeightKg.toLocaleString() }} kg</strong></div><div><span>体积</span><strong>{{ detailSummary.volumeCbm }} m³</strong></div></div>
|
||||
<div v-if="detailOrder.items.length" class="cargo-detail-list">
|
||||
<article v-for="(item, index) in detailOrder.items" :key="item.id">
|
||||
<header><span>货物 {{ index + 1 }}</span><strong>{{ item.cargoNameCn || '未命名货物' }}</strong><small>{{ item.cargoNameEn || '' }}</small></header>
|
||||
<div v-if="item.productImageFileId" class="cargo-detail-image"><img v-if="item.productImagePreviewUrl" :src="item.productImagePreviewUrl" :alt="`${item.cargoNameCn || `货物 ${index + 1}`}产品图片`" /><span v-else-if="item.productImageUploading">图片加载中...</span><span v-else>{{ item.productImageError || '产品图片暂不可用' }}</span></div>
|
||||
<dl>
|
||||
<div><dt>SKU NO.</dt><dd>{{ item.sku || '-' }}</dd></div><div><dt>UPC NO.</dt><dd>{{ item.upc || '-' }}</dd></div>
|
||||
<div><dt>报关 HS CODE</dt><dd>{{ item.hsCode || '-' }}</dd></div><div><dt>清关 HS CODE</dt><dd>{{ item.customsHsCode || '-' }}</dd></div>
|
||||
<div><dt>箱规(长×宽×高)</dt><dd>{{ item.lengthCm || '-' }} × {{ item.widthCm || '-' }} × {{ item.heightCm || '-' }} cm</dd></div>
|
||||
<div><dt>每箱数量</dt><dd>{{ item.unitsPerPackage }} 件</dd></div><div><dt>箱数</dt><dd>{{ item.packageCount }} 箱</dd></div><div><dt>总数量</dt><dd>{{ item.pieces }} 件</dd></div>
|
||||
<div><dt>总毛重</dt><dd>{{ item.grossWeightKg }} kg</dd></div><div><dt>总净重</dt><dd>{{ item.netWeightKg ? `${item.netWeightKg} kg` : '-' }}</dd></div><div><dt>总体积</dt><dd>{{ item.volumeCbm }} m³</dd></div>
|
||||
<div><dt>清关申报单价</dt><dd>{{ item.unitDeclaredValue ? `USD ${item.unitDeclaredValue.toLocaleString()}` : '-' }}</dd></div><div><dt>清关申报金额</dt><dd>{{ item.declaredValue ? `USD ${item.declaredValue.toLocaleString()}` : '-' }}</dd></div>
|
||||
<div><dt>中英文材质</dt><dd>{{ item.material || '-' }}</dd></div><div><dt>中英文用途</dt><dd>{{ item.usage || '-' }}</dd></div><div><dt>型号</dt><dd>{{ item.model || '-' }}</dd></div><div><dt>品牌</dt><dd>{{ item.brand || '-' }}</dd></div>
|
||||
<div><dt>产品规格(长×宽×高)</dt><dd>{{ item.productLengthCm || '-' }} × {{ item.productWidthCm || '-' }} × {{ item.productHeightCm || '-' }} cm</dd></div>
|
||||
<div><dt>Shipment ID</dt><dd>{{ item.shipmentId || '-' }}</dd></div><div><dt>Reference ID</dt><dd>{{ item.referenceId || '-' }}</dd></div>
|
||||
<div><dt>包装类型</dt><dd>{{ packageTypeLabels[item.packageType] || item.packageType || '-' }}</dd></div><div><dt>危险品</dt><dd>{{ item.dangerousGoods ? '是' : '否' }}</dd></div>
|
||||
</dl>
|
||||
<p v-if="item.remark">{{ item.remark }}</p>
|
||||
</article>
|
||||
</div>
|
||||
<el-empty v-else description="暂无货物明细" :image-size="56" />
|
||||
</section>
|
||||
<OrderProgressPanel :order="detailOrder" />
|
||||
<InboundBillingPanel
|
||||
:data="inboundBilling"
|
||||
@@ -1514,6 +1532,8 @@ async function searchOrders(model: QueryModel) {
|
||||
}
|
||||
@media (min-width: 721px) and (max-width: 1050px) {
|
||||
.first-leg-query-toolbar :deep(.query-toolbar__filters) { grid-template-columns: repeat(2, minmax(140px, 1fr)); }
|
||||
.cargo-form-grid, .cargo-form-grid--basic { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.product-image-field { grid-row: auto; }
|
||||
}
|
||||
@media (max-width: 720px) {
|
||||
.first-leg-query-toolbar { flex-wrap: wrap; }
|
||||
|
||||
Reference in New Issue
Block a user