refactor: flatten dropship PDA layout

This commit is contained in:
2026-09-11 14:21:46 +08:00
parent a04a1c9cbc
commit 2be72b11f7
2 changed files with 16 additions and 12 deletions
@@ -8,7 +8,7 @@
<template v-if="task">
<view class="task-summary-card">
<view class="summary-head"><text class="inbound-code">{{ task.inboundCode || '—' }}</text><text class="status">{{ statusLabel }}</text></view>
<text class="customer">{{ task.customerName || '客户未关联' }} · {{ task.warehouseName || '仓库未关联' }}</text>
<text class="warehouse-summary">{{ task.warehouseName || '仓库未关联' }}</text>
<view class="compact-metrics">
<text><strong>{{ task.totalCartons || 0 }}</strong>总箱</text>
<text><strong>{{ task.countedCartons || 0 }}</strong>清点</text>
@@ -52,7 +52,7 @@
</view>
<view class="section-card">
<view class="section-heading"><view><text class="section-title">2. 预生成托盘码</text><text class="section-desc">测量审核后已按预计托数生成,可先打印粘贴;装完一个托盘即可封托。</text></view><button class="text-button" :disabled="loading" @tap="loadTask">刷新</button></view>
<view class="section-heading"><view><text class="section-title">2. 托盘码</text><text class="section-desc">打印贴码,装完后封托</text></view><button class="text-button" :disabled="loading" @tap="loadTask">刷新</button></view>
<view v-if="!task.pallets || !task.pallets.length" class="empty">暂无托盘</view>
<view v-for="pallet in task.pallets" :key="pallet.palletId" class="pallet-card">
<view class="pallet-head"><text class="pallet-code">{{ pallet.palletNo }}</text><text class="pallet-status" :class="pallet.status === 'SEALED' ? 'sealed' : ''">{{ pallet.status === 'SEALED' ? '已封托' : '待封托' }}</text></view>
@@ -160,21 +160,22 @@
</script>
<style scoped>
.content { padding: 12px 12px 42px; }
.content { padding: 0 0 32px; background: #fff; }
.state, .message { margin-bottom: 10px; padding: 12px; border-radius: 9px; color: #667085; font-size: 12px; line-height: 18px; text-align: center; background: #fff; }
.message.error { color: #b42318; background: #fff1f0; }.message.success { color: #067647; background: #ecfdf3; }
.task-summary-card, .section-card { margin-bottom: 8px; padding: 10px; border: 1px solid #dce6f1; border-radius: 10px; background: #fff; box-shadow: 0 1px 4px rgba(23,55,93,.04); }
.task-summary-card, .section-card { margin: 0; padding: 11px 12px; border: 0; border-bottom: 6px solid #eef2f7; border-radius: 0; background: #fff; box-shadow: none; }
.task-summary-card { display: block; }
.summary-head, .section-heading, .pallet-head, .carton-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.inbound-code { min-width: 0; color: #12233f; font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }
.status, .pallet-status { flex-shrink: 0; padding: 4px 8px; border-radius: 99px; color: #155eef; font-size: 10px; background: #eff4ff; }.pallet-status.sealed { color: #067647; background: #ecfdf3; }
.customer { display: block; overflow: hidden; margin-top: 3px; color: #667085; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.compact-metrics { display: grid; grid-template-columns: repeat(5,1fr); margin-top: 8px; padding-top: 7px; border-top: 1px solid #edf1f5; }.compact-metrics > text { display: flex; align-items: center; justify-content: center; gap: 2px; color: #667085; font-size: 9px; white-space: nowrap; }.compact-metrics strong { color: #12233f; font-size: 13px; }.compact-metrics .pallet-readiness { color: #067647; }.compact-metrics .pallet-readiness.invalid,.compact-metrics .pallet-readiness.invalid strong { color: #b42318; }.pallet-setup-error { margin-top: 8px; margin-bottom: 0; text-align: left; }
.section-title { display: block; color: #12233f; font-size: 15px; font-weight: 700; }.section-desc { display: block; margin: 2px 0 8px; color: #667085; font-size: 10px; line-height: 15px; }.section-heading > view { min-width: 0; }
.status, .pallet-status { flex-shrink: 0; padding: 4px 8px; border-radius: 99px; color: #155eef; font-size: 12px; background: #eff4ff; }.pallet-status.sealed { color: #067647; background: #ecfdf3; }
.warehouse-summary { display: block; margin-top: 3px; color: #667085; font-size: 12px; }
.compact-metrics { display: grid; grid-template-columns: repeat(5,1fr); margin-top: 8px; padding-top: 7px; border-top: 1px solid #edf1f5; }.compact-metrics > text { display: flex; align-items: center; justify-content: center; gap: 3px; color: #667085; font-size: 11px; white-space: nowrap; }.compact-metrics strong { color: #12233f; font-size: 15px; }.compact-metrics .pallet-readiness { color: #067647; }.compact-metrics .pallet-readiness.invalid,.compact-metrics .pallet-readiness.invalid strong { color: #b42318; }.pallet-setup-error { margin-top: 8px; margin-bottom: 0; text-align: left; }
.section-title { display: block; color: #12233f; font-size: 18px; font-weight: 700; }.section-desc { display: block; margin: 2px 0 8px; color: #667085; font-size: 13px; line-height: 18px; }.section-heading > view { min-width: 0; }
.primary-button, .secondary-button { box-sizing: border-box; width: 100%; height: 46px; margin-top: 10px; border-radius: 9px; font-size: 14px; font-weight: 700; line-height: 44px; }.primary-button { border: 0; color: #fff; background: #1a73e8; }.secondary-button { border: 1px solid #8ab8ef; color: #155eef; background: #f6f9ff; }.primary-button[disabled],.secondary-button[disabled] { opacity: .45; }
.count-entry { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px; padding: 5px 7px; border: 1px solid #dbe8f8; border-radius: 7px; color: #667085; font-size: 10px; background: #f6f9ff; }.compact-action { width: 78px; height: 32px; margin: 0; border: 0; border-radius: 6px; color: #fff; font-size: 11px; line-height: 32px; background: #1a73e8; }.compact-action[disabled] { opacity: .35; }.count-unavailable { padding: 12px 8px; border-radius: 7px; color: #b42318; font-size: 11px; line-height: 16px; text-align: center; background: #fff1f0; }.pallet-scan-block { margin-top: 8px; padding-top: 8px; border-top: 1px solid #e6edf5; }.field-label { display: block; margin-bottom: 5px; color: #344054; font-size: 11px; font-weight: 700; }.field-label text { margin-left: 3px; color: #98a2b3; font-size: 9px; font-weight: 400; }
.carton-card, .pallet-card { margin-top: 11px; padding: 11px; border: 1px solid #e3eaf2; border-radius: 9px; background: #f8fbff; }.sku-label { display: block; color: #667085; font-size: 10px; }.sku-code { display: block; margin-top: 3px; color: #12233f; font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }.pallet-meta { display: block; margin-top: 5px; color: #667085; font-size: 11px; line-height: 17px; }
.count-entry { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px; padding: 5px 7px; border: 0; border-radius: 0; color: #667085; font-size: 13px; background: #f6f9ff; }.compact-action { width: 86px; height: 34px; margin: 0; border: 0; border-radius: 6px; color: #fff; font-size: 13px; line-height: 34px; background: #1a73e8; }.compact-action[disabled] { opacity: .35; }.count-unavailable { padding: 12px 8px; color: #b42318; font-size: 13px; line-height: 18px; text-align: center; background: #fff1f0; }.pallet-scan-block { margin-top: 8px; padding-top: 8px; border-top: 1px solid #e6edf5; }.field-label { display: block; margin-bottom: 5px; color: #344054; font-size: 15px; font-weight: 700; }.field-label text { margin-left: 3px; color: #98a2b3; font-size: 12px; font-weight: 400; }
.carton-card, .pallet-card { margin-top: 8px; padding: 10px 0 0; border: 0; border-top: 1px solid #e3eaf2; border-radius: 0; background: transparent; }.sku-label { display: block; color: #667085; font-size: 12px; }.sku-code { display: block; margin-top: 3px; color: #12233f; font-size: 19px; font-weight: 700; overflow-wrap: anywhere; }.pallet-meta { display: block; margin-top: 5px; color: #667085; font-size: 14px; line-height: 20px; }
.quantity-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; color: #344054; font-size: 13px; font-weight: 700; }.quantity-stepper { display: grid; grid-template-columns: 44px 72px 44px; overflow: hidden; border: 1px solid #b8c6d8; border-radius: 9px; background: #fff; }.quantity-stepper button,.quantity-stepper input { box-sizing: border-box; height: 44px; margin: 0; border: 0; border-radius: 0; text-align: center; background: #fff; }.quantity-stepper button { color: #155eef; font-size: 21px; line-height: 44px; }.quantity-stepper input { width: 72px; border-right: 1px solid #dce4ed; border-left: 1px solid #dce4ed; color: #12233f; font-size: 16px; }.pallet-hint { display: block; margin-top: 10px; color: #155eef; font-size: 11px; text-align: center; }
.field { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 10px; color: #344054; font-size: 12px; }.field input { box-sizing: border-box; width: 120px; height: 42px; padding: 0 10px; border: 1px solid #cfd8e3; border-radius: 8px; background: #fff; }.field.stacked { align-items: stretch; flex-direction: column; gap: 6px; }.field textarea { box-sizing: border-box; width: 100%; height: 70px; padding: 9px; border: 1px solid #cfd8e3; border-radius: 8px; background: #fff; }
.pallet-card { background: #fff; }.pallet-code { color: #12233f; font-size: 15px; font-weight: 700; overflow-wrap: anywhere; }.text-button { min-width: 58px; height: 40px; border: 0; color: #155eef; font-size: 12px; line-height: 40px; background: transparent; }.empty { padding: 18px 0 8px; color: #98a2b3; font-size: 12px; text-align: center; }
.pallet-code { color: #12233f; font-size: 19px; font-weight: 700; overflow-wrap: anywhere; }.text-button { min-width: 58px; height: 40px; border: 0; color: #155eef; font-size: 14px; line-height: 40px; background: transparent; }.empty { padding: 18px 0 8px; color: #98a2b3; font-size: 14px; text-align: center; }
.palletization-page :deep(.scan-target-value) { font-size: 17px; }
</style>
+4 -1
View File
@@ -43,9 +43,12 @@ test('palletization UI accepts carton and pre-generated pallet scans in either o
assert.match(tasks, /\.search-card\s*\{[^}]*display:\s*flex;[^}]*box-shadow:\s*none;/)
assert.match(tasks, /\.task-list\s*\{[^}]*overflow:\s*hidden;[^}]*border-radius:\s*7px;/)
assert.match(tasks, /\.task-card\s*\{[^}]*margin:\s*0;[^}]*border-radius:\s*0;[^}]*box-shadow:\s*none;/)
for (const text of ['一件代发入库', '领取并开始入库', '扫箱清点', '读取 SKU', '确认清点', '扫托盘', '可选', '差异说明', '预生成托盘码', '打印托盘码', '封托']) assert.match(work, new RegExp(text))
for (const text of ['一件代发入库', '领取并开始入库', '扫箱清点', '读取 SKU', '确认清点', '扫托盘', '可选', '差异说明', '托盘码', '打印托盘码', '封托']) assert.match(work, new RegExp(text))
for (const text of ['sku-label', 'sku-code', 'quantity-stepper', '减少清点数量', '增加清点数量', 'adjustQuantity']) assert.match(work, new RegExp(text))
for (const text of ['compact-metrics', 'compact-action']) assert.match(work, new RegExp(text))
assert.doesNotMatch(work, /task\.customerName/)
assert.match(work, /\.task-summary-card, \.section-card \{[^}]*border:\s*0;[^}]*border-bottom:\s*6px solid[^}]*border-radius:\s*0;[^}]*box-shadow:\s*none;/)
assert.match(work, /\.carton-card, \.pallet-card \{[^}]*border:\s*0;[^}]*border-top:\s*1px solid[^}]*border-radius:\s*0;[^}]*background:\s*transparent;/)
for (const text of ['计划 {{ carton.expectedSkuQuantity', "carton.cargoName", "carton.countStatus === 'UNCOUNTED'"]) assert.doesNotMatch(work, new RegExp(text))
assert.match(work, /canResolveCarton\(\)[\s\S]*?boxCode[\s\S]*?!this\.loading[\s\S]*?!this\.submitting/)
for (const text of ['expectedPalletCount', 'generatedPalletCount', 'palletSetupReady', 'palletSetupMessage']) assert.match(work, new RegExp(text))