Merge branch 'release/test' of http://8.163.30.128:10082/html/admin-web into release/test

This commit is contained in:
2026-09-04 14:31:11 +08:00
9 changed files with 117 additions and 59 deletions
@@ -231,20 +231,15 @@ describe('WeightOcrPanel confirmation behavior', () => {
expect(wrapper.text()).not.toContain('raw-0')
})
it('renders server-bound pallet sequence, target location, and pending putaway status ahead of OCR facts', async () => {
it('renders the server-bound location and status once in the compact card facts', async () => {
const wrapper = mountPanel()
await flushPromises()
const card = wrapper.get('.weight-card')
expect(card.text()).toContain('第 1 托')
expect(card.text()).toContain('目标库位')
expect(card.text()).toContain('A01')
expect(card.text()).toContain('整票预留库位')
expect(card.text()).toContain('库位A01 · 待上架')
expect(card.text()).toContain('待上架')
const putawayGuide = card.get('.weight-card__putaway').element
expect(putawayGuide.compareDocumentPosition(
card.get('.weight-card__value').element,
) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
expect(card.find('.weight-card__putaway').exists()).toBe(false)
expect(card.get('.weight-card__facts').text()).toContain('库位A01 · 待上架')
})
it('renders the authoritative whole-inbound reservation summary and an empty reserved slot', async () => {
@@ -274,12 +269,13 @@ describe('WeightOcrPanel confirmation behavior', () => {
expect(guide.text()).toContain('A03预留空位本票预留空位')
})
it('shows an explicit whole-inbound unassigned state when no guide exists', async () => {
it('does not render a full-width placeholder when no whole-inbound guide exists', async () => {
vi.mocked(getWeightWorkspace).mockResolvedValue({ ...workspace, palletLocationGuide: null })
const wrapper = mountPanel()
await flushPromises()
expect(wrapper.text()).toContain('尚未分配整票预留库位')
expect(wrapper.text()).not.toContain('尚未分配整票预留库位')
expect(wrapper.find('.putaway-guide-empty').exists()).toBe(false)
})
it('marks A0 as a temporary overflow location from the server flag', async () => {
@@ -299,7 +295,7 @@ describe('WeightOcrPanel confirmation behavior', () => {
await flushPromises()
expect(wrapper.text()).toContain('A0 临时溢出位')
expect(wrapper.get('.weight-card__putaway').classes()).toContain('is-overflow')
expect(wrapper.get('.weight-card__facts').text()).toContain('库位A0 · 待上架 · A0 临时溢出位')
expect(wrapper.get('.putaway-guide__slots li').classes()).toContain('is-overflow')
})
@@ -336,8 +332,8 @@ describe('WeightOcrPanel confirmation behavior', () => {
const wrapper = mountPanel()
await flushPromises()
expect(wrapper.text()).toContain('托盘未分配')
expect(wrapper.text()).toContain('目标库位未分配')
expect(wrapper.text()).not.toContain('托盘未分配')
expect(wrapper.get('.weight-card__facts').text()).toContain('库位未分配')
})
it('deletes a pending image with its optimistic-lock version', async () => {
@@ -35,7 +35,7 @@ describe('WeightOcrPanel contract', () => {
expect(source).toContain('货物重量')
expect(source).toContain('palletTareWeightKg')
expect(source).toContain('netWeightKg')
expect(source).toContain('row.palletSequence')
expect(source).toContain('slot.palletSequence')
expect(source).toContain('row.locationCode')
expect(source).toContain('row.sharedOverflow')
expect(source).toContain('putawayStatusLabel(row.slotStatus)')
@@ -43,6 +43,9 @@ describe('WeightOcrPanel contract', () => {
expect(source).toContain('workspace.palletLocationGuide.actualPalletCount')
expect(source).toContain('workspace.palletLocationGuide.reservedEmptySlotCount')
expect(source).toContain('本票预留空位')
expect(source).not.toContain('尚未分配整票预留库位')
expect(source).not.toContain('class="weight-card__putaway"')
expect(source).toContain('<div><dt>库位</dt><dd')
expect(source).toContain('对应库位仍为本票保留,不会释放给其他订单')
expect(source).toContain("emit('summaryChanged', workspace.value?.actualGrossWeightKg ?? null, workspace.value?.actualNetWeightKg ?? null)")
})
@@ -588,10 +588,6 @@ defineExpose({ reload: loadWorkspace })
</li>
</ol>
</section>
<div v-else-if="workspace" class="putaway-guide-empty" role="status">
<strong>尚未分配整票预留库位</strong>
<span>称重图片绑定库位后,将按服务端上架引导显示目标库位。</span>
</div>
<LoadErrorState
v-if="palletError"
title="可选托盘加载失败"
@@ -639,20 +635,6 @@ defineExpose({ reload: loadWorkspace })
><Trash2 :size="16" /></el-button>
</el-tooltip>
<div class="weight-card__body">
<div class="weight-card__putaway" :class="{ 'is-overflow': row.sharedOverflow }">
<div class="weight-card__putaway-title">
<strong>{{ row.palletSequence == null ? '托盘未分配' : `第 ${row.palletSequence} 托` }}</strong>
<el-tag size="small" effect="light" :type="putawayStatusType(row.slotStatus)">
{{ putawayStatusLabel(row.slotStatus) }}
</el-tag>
</div>
<div class="weight-card__location">
<span>目标库位</span>
<strong>{{ row.locationCode || '未分配' }}</strong>
</div>
<span v-if="row.sharedOverflow" class="weight-card__overflow">A0 临时溢出位</span>
<span v-else-if="row.locationCode" class="weight-card__normal-location">整票预留库位</span>
</div>
<button
type="button"
class="weight-card__value"
@@ -662,6 +644,7 @@ defineExpose({ reload: loadWorkspace })
<dl class="weight-card__facts">
<div><dt>托盘编码</dt><dd :title="row.palletCode">{{ row.palletCode || '未记录编码' }}</dd></div>
<div><dt>托盘类型</dt><dd>{{ row.palletType || '未记录类型' }}</dd></div>
<div><dt>库位</dt><dd :title="row.locationCode || '未分配'">{{ row.locationCode || '未分配' }}<template v-if="row.locationCode"> · {{ putawayStatusLabel(row.slotStatus) }}</template><template v-if="row.sharedOverflow"> · A0 临时溢出位</template></dd></div>
<div><dt>服务端确认毛重</dt><dd>{{ formatWeight(row.grossWeightKg) }}</dd></div>
<div><dt>托盘皮重</dt><dd>{{ formatWeight(row.palletTareWeightKg) }}</dd></div>
<div><dt>货物重量</dt><dd>{{ formatWeight(row.netWeightKg) }}</dd></div>
@@ -768,26 +751,12 @@ defineExpose({ reload: loadWorkspace })
.putaway-guide__slots li.is-overflow .putaway-guide__slot-title strong { color: #93370d; }
.putaway-guide__slots li > span { color: #475467; font-size: 12px; overflow-wrap: anywhere; }
.putaway-guide__slots small { width: fit-content; color: #93370d; font-weight: 600; }
.putaway-guide-empty { display: grid; gap: 3px; margin: 14px 0 18px; padding: 13px 15px; border: 1px dashed #98a2b3; border-radius: 8px; background: #f9fafb; }
.putaway-guide-empty strong { color: #344054; font-size: 14px; }
.putaway-guide-empty span { color: #667085; font-size: 12px; }
.weight-list { min-height: 0; margin-top: 14px; }
.weight-empty { display: flex; min-height: 0; align-items: center; gap: 10px; padding: 4px 0 0; color: var(--cc-muted); }
.weight-empty strong { color: #344054; font-size: 14px; }
.weight-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.weight-card { position: relative; min-width: 0; overflow: hidden; border: 1px solid var(--cc-border); border-radius: 6px; background: #fff; }
.weight-card__body { padding: 12px; text-align: center; }
.weight-card__putaway { display: grid; gap: 8px; margin: -12px -12px 12px; padding: 12px; border-bottom: 1px solid #b2ddff; background: #eff8ff; text-align: left; }
.weight-card__putaway.is-overflow { border-color: #fec84b; background: #fffaeb; }
.weight-card__putaway-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.weight-card__putaway-title strong { color: #1849a9; font-size: 15px; }
.weight-card__putaway.is-overflow .weight-card__putaway-title strong { color: #93370d; }
.weight-card__location { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.weight-card__location span { color: #475467; font-size: 12px; }
.weight-card__location strong { color: #101828; font-size: 22px; line-height: 1; overflow-wrap: anywhere; }
.weight-card__overflow, .weight-card__normal-location { width: fit-content; padding: 2px 7px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.weight-card__overflow { background: #fef0c7; color: #93370d; }
.weight-card__normal-location { background: #d1e9ff; color: #175cd3; }
.weight-delete { position: absolute; z-index: 2; top: 8px; right: 8px; width: 30px; height: 30px; padding: 0; border: 1px solid rgb(255 255 255 / 82%); background: rgb(255 255 255 / 92%); box-shadow: 0 1px 3px rgb(16 24 40 / 16%); }
.weight-card__value { width: 100%; padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; text-align: center; }
.weight-card__value strong { color: #101828; font-size: 17px; }