优化
This commit is contained in:
@@ -149,13 +149,13 @@ describe('InboundMeasurementPanel', () => {
|
||||
const wrapper = await mountPanel()
|
||||
|
||||
expect(getInboundMeasurement).toHaveBeenCalledWith('10001', '7001')
|
||||
expect((wrapper.find('input[readonly]').element as HTMLInputElement).value).toBe('RK202608040001')
|
||||
expect(wrapper.text()).toContain('RK202608040001')
|
||||
expect(wrapper.text()).toContain('周长(cm)')
|
||||
expect(wrapper.find('.measurement-table').text()).toContain('190')
|
||||
expect(wrapper.find('.measurement-table').text()).toContain('0.6')
|
||||
expect(wrapper.find('.measurement-table').text()).not.toContain('周长')
|
||||
await wrapper.find('.el-table__expand-icon').trigger('click')
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).toContain('箱规周长')
|
||||
expect(wrapper.text()).toContain('190 cm')
|
||||
expect(wrapper.text()).toContain('MJ20210327')
|
||||
expect(wrapper.text()).toContain('2026-08-04 10:30:00+08:00')
|
||||
expect(wrapper.find('button[aria-label="预览测量图片"]').exists()).toBe(true)
|
||||
@@ -189,27 +189,29 @@ describe('InboundMeasurementPanel', () => {
|
||||
|
||||
const wrapper = await mountPanel()
|
||||
|
||||
expect(wrapper.findAll('input[readonly]').some((input) => (input.element as HTMLInputElement).value === '未知来源')).toBe(true)
|
||||
expect(wrapper.text()).toContain('未知来源')
|
||||
expect(wrapper.text()).not.toContain('LEGACY_DEVICE')
|
||||
})
|
||||
|
||||
it('follows the prototype grouping, labels, and editable field order', async () => {
|
||||
it('keeps the first view focused on key totals and moves secondary fields behind disclosure', async () => {
|
||||
const wrapper = await mountPanel()
|
||||
const text = wrapper.text()
|
||||
|
||||
expect(text).toContain('原单数据与测量汇总')
|
||||
expect(text).toContain('扫描箱测量数据明细')
|
||||
expect(text).toContain('订单总箱数')
|
||||
expect(text).toContain('确认箱数合计')
|
||||
expect(text).toContain('货物总重量')
|
||||
expect(text).toContain('实测总体积')
|
||||
expect(text).toContain('实测总材积重')
|
||||
expect(text).toContain('实测箱数')
|
||||
expect(text).toContain('货物重量')
|
||||
expect(text).toContain('总体积')
|
||||
expect(text).toContain('材积重')
|
||||
expect(text).toContain('申报信息')
|
||||
expect(text).toContain('箱规明细')
|
||||
expect(text).not.toContain('租户')
|
||||
expect(text).not.toContain('数据版本')
|
||||
|
||||
expect(wrapper.find('.measurement-table').exists()).toBe(true)
|
||||
expect(wrapper.find('.measurement-item').exists()).toBe(false)
|
||||
expect(wrapper.find('.measurement-table').text()).toContain('周长(cm)')
|
||||
expect(wrapper.find('.measurement-table').text()).not.toContain('周长')
|
||||
const source = await import('./InboundMeasurementPanel.vue?raw').then((module) => module.default)
|
||||
expect(source).toContain('<el-collapse-item name="declaration" title="申报信息">')
|
||||
expect(source).toContain('grid-template-columns: repeat(4, minmax(0, 1fr))')
|
||||
expect(source).toContain('.measurement-form-grid, .measurement-data-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));')
|
||||
expect(source).toContain('.measurement-table { width: 100%; font-size: 12px; }')
|
||||
expect(source).toContain('.measurement-data-grid :deep(.el-input__wrapper)')
|
||||
@@ -224,7 +226,7 @@ describe('InboundMeasurementPanel', () => {
|
||||
wrapper.vm.updateActualGrossWeight(125.75)
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.findAll('input[readonly]').some((input) => (input.element as HTMLInputElement).value === '125.75')).toBe(true)
|
||||
expect(wrapper.find('.measurement-metrics').text()).toContain('125.75')
|
||||
expect((countInput.element as HTMLInputElement).value).toBe('9')
|
||||
})
|
||||
|
||||
@@ -232,8 +234,8 @@ describe('InboundMeasurementPanel', () => {
|
||||
const wrapper = await mountPanel()
|
||||
|
||||
expect(wrapper.classes()).toContain('surface-panel')
|
||||
expect(wrapper.find('.measurement-panel__heading').exists()).toBe(true)
|
||||
expect(wrapper.findAll('input[readonly]').some((input) => (input.element as HTMLInputElement).value === '测量中')).toBe(true)
|
||||
expect(wrapper.find('.measurement-summary-header').exists()).toBe(true)
|
||||
expect(wrapper.find('.measurement-summary-status').text()).toContain('测量中')
|
||||
})
|
||||
|
||||
it('saves only the changed confirmed package count with the current measurement version', async () => {
|
||||
@@ -343,8 +345,9 @@ describe('InboundMeasurementPanel', () => {
|
||||
await flushPromises()
|
||||
|
||||
expect(getInboundMeasurement).toHaveBeenLastCalledWith('10002', '7002')
|
||||
expect(wrapper.findAll('input[readonly]').some((input) => (input.element as HTMLInputElement).value === 'RK202608040002')).toBe(true)
|
||||
expect(wrapper.findAll('input[readonly]').some((input) => (input.element as HTMLInputElement).value === '测试企业')).toBe(false)
|
||||
expect(wrapper.find('.measurement-summary-header').text()).toContain('RK202608040002')
|
||||
expect(wrapper.find('.measurement-summary-header').text()).toContain('第二企业')
|
||||
expect(wrapper.find('.measurement-summary-header').text()).not.toContain('测试企业')
|
||||
})
|
||||
|
||||
it('renders a permission-specific read-only state without requesting data', async () => {
|
||||
|
||||
@@ -516,32 +516,45 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
<form class="measurement-form" @submit.prevent="saveDraft">
|
||||
<fieldset :disabled="!mayMaintain || saving">
|
||||
<legend class="sr-only">测量草稿</legend>
|
||||
<section class="measurement-section">
|
||||
<div class="measurement-section__heading measurement-panel__heading">
|
||||
<div><h3>原单数据与测量汇总</h3></div>
|
||||
</div>
|
||||
<div class="measurement-data-grid">
|
||||
<label><span>入仓号</span><el-input :model-value="detail.inboundCode || '—'" readonly /></label>
|
||||
<label><span>公司</span><el-input :model-value="detail.companyName || '—'" readonly /></label>
|
||||
<label><span>渠道</span><el-input :model-value="detail.channelName || detail.channelCode || '—'" readonly /></label>
|
||||
<label><span>测量来源</span><el-input :model-value="sourceLabel" readonly /></label>
|
||||
<label><span>当前状态</span><el-input :model-value="processStatusLabel(detail.processStatus)" readonly /></label>
|
||||
<label><span>数据版本</span><el-input :model-value="String(form.version)" readonly /></label>
|
||||
<label><span>确认箱数合计</span><el-input :model-value="formatNumber(confirmedPackageCount, 0)" readonly /></label>
|
||||
<label><span>订单总箱数</span><el-input :model-value="formatNumber(expectedPackageCount, 0)" readonly /></label>
|
||||
<label><span>货物总重量(kg)</span><el-input :model-value="formatNumber(detail.actualGrossWeightKg)" readonly /></label>
|
||||
<label><span>原单总毛重(T.K.GW)</span><el-input-number v-model="form.originalGrossWeightKg" :min="0" :precision="3" controls-position="right" /></label>
|
||||
<label><span>实测总体积(T.CBM)</span><el-input :model-value="formatNumber(detail.actualVolumeCbm, 4)" readonly /></label>
|
||||
<label><span>原单总体积(T.CBM)</span><el-input-number v-model="form.originalVolumeCbm" :min="0" :precision="4" controls-position="right" /></label>
|
||||
<label><span>实测总材积重(kg)</span><el-input :model-value="formatNumber(detail.volumeWeightKg)" readonly /></label>
|
||||
<label><span>原单据号码(CKW)</span><el-input v-model="form.originalDocumentNo" placeholder="请输入原单据号码" maxlength="128" /></label>
|
||||
<label><span>实际品名</span><el-input v-model="form.actualGoodsName" placeholder="请输入实际品名" maxlength="128" /></label>
|
||||
</div>
|
||||
<section class="measurement-section measurement-summary-section">
|
||||
<header class="measurement-summary-header">
|
||||
<div>
|
||||
<span>入仓码</span>
|
||||
<strong>{{ detail.inboundCode || '—' }}</strong>
|
||||
<p>{{ detail.companyName || '客户未命名' }} · {{ detail.channelName || detail.channelCode || '渠道未填写' }}</p>
|
||||
</div>
|
||||
<div class="measurement-summary-status">
|
||||
<el-tag effect="light">{{ processStatusLabel(detail.processStatus) }}</el-tag>
|
||||
<span>{{ sourceLabel }}</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<dl class="measurement-metrics" aria-label="测量结果汇总">
|
||||
<div :class="{ 'measurement-metric--warning': !packageCountMatched }">
|
||||
<dt>实测箱数</dt>
|
||||
<dd>{{ formatNumber(confirmedPackageCount, 0) }} <small>/ 申报 {{ formatNumber(expectedPackageCount, 0) }}</small></dd>
|
||||
</div>
|
||||
<div class="measurement-metric--primary"><dt>货物重量</dt><dd>{{ formatNumber(detail.actualGrossWeightKg) }} <small>kg</small></dd></div>
|
||||
<div><dt>总体积</dt><dd>{{ formatNumber(detail.actualVolumeCbm, 4) }} <small>m³</small></dd></div>
|
||||
<div><dt>材积重</dt><dd>{{ formatNumber(detail.volumeWeightKg) }} <small>kg</small></dd></div>
|
||||
</dl>
|
||||
|
||||
<el-collapse class="measurement-more">
|
||||
<el-collapse-item name="declaration" title="申报信息">
|
||||
<div class="measurement-data-grid">
|
||||
<label><span>申报箱数</span><el-input :model-value="formatNumber(expectedPackageCount, 0)" readonly /></label>
|
||||
<label><span>申报毛重(kg)</span><el-input-number v-model="form.originalGrossWeightKg" :min="0" :precision="3" controls-position="right" /></label>
|
||||
<label><span>申报体积(m³)</span><el-input-number v-model="form.originalVolumeCbm" :min="0" :precision="4" controls-position="right" /></label>
|
||||
<label><span>实际品名</span><el-input v-model="form.actualGoodsName" placeholder="请输入实际品名" maxlength="128" /></label>
|
||||
<label><span>原单据号码</span><el-input v-model="form.originalDocumentNo" placeholder="请输入原单据号码" maxlength="128" /></label>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</section>
|
||||
|
||||
<section class="measurement-section measurement-items-section">
|
||||
<div class="measurement-section__heading">
|
||||
<div><h3>扫描箱测量数据明细</h3><p>每条记录对应一个实际扫描箱;人工只确认该条记录代表的箱数,设备实测值不可在此修改。</p></div>
|
||||
<div><h3>箱规明细</h3></div>
|
||||
<el-button v-if="canManualEntry" type="primary" plain :disabled="!mayCreateManualEntry" @click="openManualEntry"><Plus :size="15" />手动录入箱规</el-button>
|
||||
</div>
|
||||
|
||||
@@ -559,7 +572,10 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
<dl class="measurement-row-details">
|
||||
<div><dt>机器编号</dt><dd>{{ row.machineNo || '人工录入' }}</dd></div>
|
||||
<div><dt>测量时间</dt><dd>{{ row.measuredAt ? row.measuredAt.replace('T', ' ') : '—' }}</dd></div>
|
||||
<div><dt>每箱毛重</dt><dd>{{ formatNumber(row.unitWeightKg) }} kg</dd></div>
|
||||
<div><dt>单箱体积</dt><dd>{{ formatNumber(row.serverValues.unitVolumeCbm, 4) }} m³</dd></div>
|
||||
<div><dt>箱规周长</dt><dd>{{ formatNumber(row.serverValues.girthCm) }} cm</dd></div>
|
||||
<div><dt>总材积重</dt><dd>{{ formatNumber(row.serverValues.volumeWeightKg) }} kg</dd></div>
|
||||
<div><dt>备注</dt><dd>{{ row.remark || '—' }}</dd></div>
|
||||
</dl>
|
||||
</template>
|
||||
@@ -585,24 +601,12 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="每箱毛重(kg)" width="106" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.unitWeightKg) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单箱体积(m³)" width="112" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.serverValues.unitVolumeCbm, 4) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="周长(cm)" width="92" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.serverValues.girthCm) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总毛重(kg)" width="104" align="right">
|
||||
<el-table-column label="总重量(kg)" width="112" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.serverValues.totalWeightKg) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总体积(m³)" width="108" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.serverValues.totalVolumeCbm, 4) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总材积重(kg)" width="116" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.serverValues.volumeWeightKg) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图片" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip :content="row.intelligentImageFileId ? '预览测量图片' : '暂无测量图片'">
|
||||
@@ -620,7 +624,7 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
|
||||
<footer v-if="canEdit || canSubmit" class="measurement-panel__footer">
|
||||
<span v-if="isDirty"><AlertTriangle :size="15" />有尚未保存的修改</span>
|
||||
<span v-else>当前显示版本 {{ form.version }}</span>
|
||||
<span v-else>所有修改已保存</span>
|
||||
<div>
|
||||
<el-button v-if="canEdit" type="primary" plain :loading="saving" :disabled="!mayMaintain" @click="saveDraft"><Save :size="15" />保存测量数据</el-button>
|
||||
<el-button v-if="canSubmit" type="primary" :loading="submitting" :disabled="!maySubmit" @click="submitForReview"><Send :size="15" />提交审核</el-button>
|
||||
@@ -680,20 +684,33 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
.measurement-panel__actions, .measurement-panel__footer > div { display: flex; flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
||||
.measurement-panel__actions :deep(.el-button), .measurement-panel__footer :deep(.el-button) { margin-left: 0; }
|
||||
.measurement-skeleton { padding: 24px; }
|
||||
.measurement-context { padding: 16px 20px; border-bottom: 1px solid var(--cc-border); }
|
||||
.measurement-context__identity { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
||||
.measurement-context__identity > div:first-child { display: flex; min-width: 0; flex-direction: column; gap: 4px; }
|
||||
.measurement-context__identity strong { overflow-wrap: anywhere; color: var(--cc-text); font-size: 15px; }
|
||||
.measurement-context__identity span { color: var(--cc-muted); font-size: 12px; line-height: 1.5; }
|
||||
.measurement-tags { display: flex; flex: 0 0 auto; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 7px; }
|
||||
.measurement-tags > span:last-child { color: var(--cc-muted); font-size: 11px; }
|
||||
.measurement-metrics { display: none; }
|
||||
.measurement-panel > :deep(.el-alert), .measurement-alert { margin: 16px 20px 0; width: auto; }
|
||||
.measurement-alert p { margin: 5px 0 0; line-height: 1.55; }
|
||||
.measurement-alert ul { margin: 7px 0 0; padding-left: 18px; font-size: 12px; line-height: 1.65; }
|
||||
.measurement-alert .el-button { margin-top: 9px; }
|
||||
.measurement-form fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
|
||||
.measurement-section { padding: 18px 20px; border-top: 1px solid var(--cc-border); }
|
||||
.measurement-summary-section { display: grid; gap: 16px; border-top: 0; }
|
||||
.measurement-summary-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
|
||||
.measurement-summary-header > div:first-child { display: grid; min-width: 0; gap: 3px; }
|
||||
.measurement-summary-header span { color: var(--cc-muted); font-size: 11px; }
|
||||
.measurement-summary-header strong { overflow-wrap: anywhere; color: var(--cc-text); font-size: 20px; line-height: 1.3; }
|
||||
.measurement-summary-header p { margin: 0; color: var(--cc-muted); font-size: 12px; }
|
||||
.measurement-summary-status { display: flex; flex: 0 0 auto; align-items: center; gap: 9px; }
|
||||
.measurement-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: hidden; border: 1px solid var(--cc-border); border-radius: 6px; background: #fff; }
|
||||
.measurement-metrics > div { display: grid; min-width: 0; min-height: 78px; align-content: center; gap: 6px; padding: 13px 16px; border-right: 1px solid var(--cc-border); }
|
||||
.measurement-metrics > div:last-child { border-right: 0; }
|
||||
.measurement-metrics dt { color: var(--cc-muted); font-size: 12px; }
|
||||
.measurement-metrics dd { min-width: 0; margin: 0; color: var(--cc-text); font-size: 19px; font-weight: 700; overflow-wrap: anywhere; }
|
||||
.measurement-metrics small { color: var(--cc-muted); font-size: 11px; font-weight: 500; }
|
||||
.measurement-metric--primary { background: #f0f7ff; }
|
||||
.measurement-metric--primary dd { color: var(--cc-primary); font-size: 23px; }
|
||||
.measurement-metric--warning { background: var(--el-color-warning-light-9); }
|
||||
.measurement-metric--warning dd { color: var(--el-color-warning-dark-2); }
|
||||
.measurement-more { border-top: 0; border-bottom: 0; }
|
||||
.measurement-more :deep(.el-collapse-item__header) { height: 38px; color: var(--cc-muted); font-size: 12px; }
|
||||
.measurement-more :deep(.el-collapse-item__wrap) { border-bottom: 0; }
|
||||
.measurement-more :deep(.el-collapse-item__content) { padding: 4px 0 2px; }
|
||||
.measurement-section__heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 16px; }
|
||||
.measurement-section__heading > div { min-width: 0; }
|
||||
.measurement-form-grid, .measurement-data-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 24px; }
|
||||
@@ -732,11 +749,11 @@ defineExpose({ saveDraft, submitForReview, updateActualGrossWeight, mayMaintain,
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.measurement-panel__heading, .measurement-context__identity, .measurement-section__heading, .measurement-panel__footer { align-items: stretch; flex-direction: column; }
|
||||
.measurement-panel__heading, .measurement-summary-header, .measurement-section__heading, .measurement-panel__footer { align-items: stretch; flex-direction: column; }
|
||||
.measurement-panel__actions, .measurement-panel__actions :deep(.el-button), .measurement-panel__footer > div, .measurement-panel__footer :deep(.el-button) { width: 100%; }
|
||||
.measurement-panel__actions :deep(.el-button), .measurement-panel__footer :deep(.el-button), .measurement-section__heading :deep(.el-button) { min-height: 44px; }
|
||||
.measurement-tags { justify-content: flex-start; }
|
||||
.measurement-context, .measurement-section { padding-right: 14px; padding-left: 14px; }
|
||||
.measurement-section { padding-right: 14px; padding-left: 14px; }
|
||||
.measurement-panel > :deep(.el-alert), .measurement-alert { margin-right: 14px; margin-left: 14px; }
|
||||
.measurement-form-grid, .measurement-data-grid { grid-template-columns: 1fr; }
|
||||
.measurement-row-details { grid-template-columns: 1fr; padding-left: 54px; }
|
||||
|
||||
Reference in New Issue
Block a user