This commit is contained in:
2026-09-14 15:33:35 +08:00
parent 23d956ba15
commit b0de9c026f
30 changed files with 270 additions and 240 deletions
@@ -62,7 +62,7 @@ describe('MeasurementReviewPanel', () => {
vi.mocked(listMeasurementReviewHistory).mockResolvedValue({ records: [], page: 1, size: 20, total: 0, pages: 0 })
})
it('keeps customer context and pending actions in one non-sticky first-screen toolbar', async () => {
it('keeps customer context and pending actions in one sticky toolbar while reviewing long content', async () => {
const wrapper = mount(MeasurementReviewPanel, { props: { customerId: '10001', inboundId: '90001' }, global: { plugins: [ElementPlus] } })
await flushPromises()
@@ -83,7 +83,7 @@ describe('MeasurementReviewPanel', () => {
expect(wrapper.text()).not.toContain('审核历史')
expect(listMeasurementReviewHistory).not.toHaveBeenCalled()
const source = await import('./MeasurementReviewPanel.vue?raw').then((module) => module.default)
expect(source).not.toContain('position: sticky')
expect(source).toContain('position: sticky')
expect(source).toContain('review-toolbar__context')
expect(source.indexOf('class="review-toolbar"')).toBeLessThan(source.indexOf('<WeightOcrPanel'))
expect(source).not.toContain('reasonDialog')
@@ -1,4 +1,5 @@
<script setup lang="ts">
import '@/styles/adminDensity.css'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Check, Pencil, RotateCcw } from '@lucide/vue'
@@ -139,7 +140,7 @@ async function confirmApprove() {
await ElMessageBox.confirm(
`审核通过后,入库单将进入${approvalTargetLabel.value}。系统会尝试生成初算费用,但初算失败不影响审核通过,后续可由平台人员补充调整。是否继续?`,
'确认测量审核通过',
{ confirmButtonText: approvalButtonLabel.value, cancelButtonText: '返回', type: 'warning' },
{ customClass: 'admin-density-confirm', confirmButtonText: approvalButtonLabel.value, cancelButtonText: '返回', type: 'warning' },
)
} catch {
return
@@ -242,7 +243,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
<div v-if="detail.items.length" class="review-table-scroll">
<el-table :data="detail.items" border stripe table-layout="fixed" class="review-table">
<el-table-column type="index" label="#" width="44" align="center" />
<el-table-column label="箱号" min-width="100" show-overflow-tooltip>
<el-table-column label="箱号" width="240" show-overflow-tooltip>
<template #default="{ row }">{{ row.boxCode || row.itemNo || '—' }}</template>
</el-table-column>
<el-table-column label="测量图片" width="98" align="center">
@@ -257,7 +258,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
/>
</template>
</el-table-column>
<el-table-column label="尺寸 长×宽×高(cm)" width="132" align="center">
<el-table-column label="尺寸 长×宽×高(cm)" min-width="200" align="center">
<template #default="{ row }">{{ formatNumber(row.lengthCm) }} × {{ formatNumber(row.widthCm) }} × {{ formatNumber(row.heightCm) }}</template>
</el-table-column>
<el-table-column prop="packageCount" label="箱数" width="54" align="right">
@@ -272,7 +273,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
<el-table-column label="体积重(kg)" width="96" align="right">
<template #default="{ row }">{{ formatNumber(row.volumeWeightKg) }}</template>
</el-table-column>
<el-table-column label="测量时间" width="152" class-name="review-time-cell">
<el-table-column label="测量时间" width="190" class-name="review-time-cell">
<template #default="{ row }">{{ formatDate(row.deviceMeasuredAt) }}</template>
</el-table-column>
</el-table>
@@ -289,7 +290,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
/>
</template>
<el-dialog v-model="imagePreviewOpen" :title="imagePreviewTitle" width="min(760px, 92vw)" destroy-on-close append-to-body @closed="releaseImagePreview">
<el-dialog class="admin-density-dialog" v-model="imagePreviewOpen" :title="imagePreviewTitle" width="min(760px, 92vw)" destroy-on-close append-to-body @closed="releaseImagePreview">
<div class="review-image-preview">
<el-skeleton v-if="imagePreviewLoading" :rows="5" animated />
<div v-else-if="imagePreviewError" class="review-image-preview__error">
@@ -304,8 +305,8 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
</template>
<style scoped>
.review-panel { display: grid; gap: 16px; color: var(--cc-text); }
.review-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin: -20px -24px 0; padding: 14px 24px; border-bottom: 1px solid var(--cc-border); background: #fff; }
.review-panel { display: grid; gap: 12px; color: var(--cc-text); }
.review-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; position: sticky; top: -12px; z-index: 3; flex-wrap: wrap; margin: -12px -16px 0; padding: 8px 16px; border-bottom: 1px solid var(--cc-border); background: #fff; }
.review-toolbar__status, .review-toolbar__actions { display: flex; min-width: 0; align-items: center; flex-wrap: wrap; gap: 8px; }
.review-toolbar__status > span { color: var(--cc-muted); font-size: 12px; }
.review-toolbar__actions { justify-content: flex-end; }
@@ -324,14 +325,14 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
.review-metrics, .review-declaration { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px 16px; min-width: 0; margin: 0; }
.review-declaration { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.review-metrics > div, .review-declaration > div { display: flex; min-width: 0; align-items: baseline; gap: 6px; }
.review-metrics dt, .review-declaration dt { color: var(--cc-muted); font-size: 11px; line-height: 1.4; }
.review-metrics dd { margin: 0; overflow-wrap: anywhere; color: #172033; font-size: 15px; font-weight: 700; line-height: 1.35; }
.review-metrics dd small, .review-declaration dd small { color: var(--cc-muted); font-size: 11px; font-weight: 500; }
.review-metrics dt, .review-declaration dt { color: var(--cc-muted); font-size: 12px; line-height: 1.4; }
.review-metrics dd { margin: 0; overflow-wrap: anywhere; color: #172033; font-size: 14px; font-weight: 600; line-height: 1.35; }
.review-metrics dd small, .review-declaration dd small { color: var(--cc-muted); font-size: 12px; font-weight: 500; }
.review-metrics .review-metric--primary dd { color: #067647; }
.review-declaration dd { margin: 0; overflow-wrap: anywhere; color: var(--cc-text); font-size: 13px; font-weight: 650; line-height: 1.4; }
.review-table-scroll { width: 100%; min-width: 0; overflow: hidden; }
.review-table { width: 100%; font-size: 12px; }
.review-table :deep(.el-table__header th) { padding: 8px 0; background: #f6f8fa; color: #475467; font-size: 11px; font-weight: 700; }
.review-table :deep(.el-table__header th) { padding: 8px 0; background: #f6f8fa; color: #475467; font-size: 12px; font-weight: 700; }
.review-table :deep(.el-table__header .cell) { white-space: nowrap; }
.review-table :deep(.el-table__cell) { padding: 7px 0; }
.review-table :deep(.review-time-cell .cell) { white-space: nowrap; }