From 54d6b9a8ccf2e4f9e7e1db4c5d78e8f4e468fafd Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 7 Aug 2026 17:46:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/CarrierRatesView.test.ts | 2 ++ .../carrier-rates/pages/CarrierRatesView.vue | 3 +- .../inbounds/weight/api/weightOcr.test.ts | 32 +++++++++++++++++-- src/modules/inbounds/weight/api/weightOcr.ts | 21 ++++++++++-- .../weight/components/WeightOcrPanel.test.ts | 1 + .../weight/components/WeightOcrPanel.vue | 3 +- src/modules/inbounds/weight/types.ts | 3 +- 7 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.test.ts b/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.test.ts index f0f533a1..fde6a8c4 100644 --- a/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.test.ts +++ b/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.test.ts @@ -56,6 +56,8 @@ describe('CarrierRatesView price-book source contract', () => { expect(source).toContain('sourceDestinationName') expect(source).toContain('autoSelectExactWarehouseMappings') expect(source).toContain("'DUPLICATE_RATE'") + expect(source).toContain('.channel-tabs { width: 100%; min-width: 0;') + expect(source).toContain('.channel-preview :deep(.el-table) { width: 100%; max-width: 100%; min-width: 0; }') expect(source).not.toContain('tenantId') expect(source).not.toContain('客户选择') }) diff --git a/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue b/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue index 0bf19000..6b5034f6 100644 --- a/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue +++ b/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue @@ -847,7 +847,8 @@ onMounted(() => { .mapping-load-error { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 14px; border: 1px solid color-mix(in srgb, var(--cc-danger) 24%, var(--cc-border)); border-radius: 8px; background: #fff; } .mapping-load-error strong { color: var(--cc-danger); font-size: 13px; } .mapping-load-error p { margin: 4px 0; color: var(--cc-text); font-size: 12px; } -.channel-tabs { margin-bottom: 0; } +.channel-tabs { width: 100%; min-width: 0; margin-bottom: 0; overflow: hidden; } +.channel-preview :deep(.el-table) { width: 100%; max-width: 100%; min-width: 0; } .channel-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: -4px 0 8px; color: var(--cc-muted); font-size: 12px; } @media (max-width: 720px) { .table-actions :deep(.el-button) { min-height: 40px; } diff --git a/src/modules/inbounds/weight/api/weightOcr.test.ts b/src/modules/inbounds/weight/api/weightOcr.test.ts index b8381ca9..62cbe281 100644 --- a/src/modules/inbounds/weight/api/weightOcr.test.ts +++ b/src/modules/inbounds/weight/api/weightOcr.test.ts @@ -5,7 +5,9 @@ import { correctWeightResult, createWeightResult, downloadWeightImage, + getWeightOcrRawText, getWeightWorkspace, + normalizeWeightConfidence, retryWeightRecognition, uploadWeightImage, } from './weightOcr' @@ -23,6 +25,31 @@ describe('inbound weight OCR API', () => { vi.mocked(http.put).mockReset() }) + it('normalizes OCR confidence to the firstleg decimal contract', () => { + expect(normalizeWeightConfidence(0.5097191334)).toBe(0.50972) + expect(normalizeWeightConfidence(1.2)).toBe(1) + expect(normalizeWeightConfidence(-0.2)).toBe(0) + expect(normalizeWeightConfidence(Number.NaN)).toBeNull() + expect(normalizeWeightConfidence(null)).toBeNull() + }) + + it('accepts current and compatible OCR raw-text response fields', () => { + const upload = { + fileId: '1', + fileName: 'weight.jpg', + contentType: 'image/jpeg', + sizeBytes: 100, + recognitionStatus: 'SUCCESS', + weightValue: 12.5, + weightUnit: 'KG', + confidence: 0.98, + error: null, + } + expect(getWeightOcrRawText({ ...upload, ocrRawText: ' 12.5 KG ' })).toBe('12.5 KG') + expect(getWeightOcrRawText({ ...upload, rawText: 'display: 12.5' })).toBe('display: 12.5') + expect(getWeightOcrRawText(upload)).toBeNull() + }) + it('loads the measurement workspace using the real firstleg path', async () => { const detail = { inboundId: '9007199254740993', weightResults: [] } vi.mocked(http.get).mockResolvedValue({ code: '200', message: 'success', data: detail }) @@ -61,13 +88,13 @@ describe('inbound weight OCR API', () => { ocrRawText: null, ocrWeightValue: 12.5, ocrWeightUnit: 'KG', - confidence: 0.98, + confidence: 0.5097191334, } await createWeightResult('10001', '20001', createPayload) expect(http.post).toHaveBeenNthCalledWith( 1, '/platform/v1/first-leg/inbounds/20001/weight-results', - createPayload, + { ...createPayload, confidence: 0.50972 }, { params: { tenantId: '10001' } }, ) @@ -97,4 +124,3 @@ describe('inbound weight OCR API', () => { ) }) }) - diff --git a/src/modules/inbounds/weight/api/weightOcr.ts b/src/modules/inbounds/weight/api/weightOcr.ts index 07c54ec0..811e2d87 100644 --- a/src/modules/inbounds/weight/api/weightOcr.ts +++ b/src/modules/inbounds/weight/api/weightOcr.ts @@ -12,11 +12,25 @@ import type { const measurementBasePath = '/platform/v1/first-leg/inbounds' const imageBasePath = '/platform/v1/files/measurements' const maxErrorEnvelopeBytes = 1024 * 1024 +const confidenceScale = 100_000 function segment(value: string) { return encodeURIComponent(value) } +export function normalizeWeightConfidence(value: number | null) { + if (value == null || !Number.isFinite(value)) return null + const clamped = Math.min(1, Math.max(0, value)) + return Math.round(clamped * confidenceScale) / confidenceScale +} + +export function getWeightOcrRawText(result: WeightImageUploadResult) { + const rawText = result.ocrRawText ?? result.rawText + if (typeof rawText !== 'string') return null + const normalized = rawText.trim() + return normalized ? normalized.slice(0, 1000) : null +} + async function parseBlobError(blob: Blob, status?: number) { if (!blob.type.toLowerCase().includes('json')) return null if (blob.size > maxErrorEnvelopeBytes) { @@ -85,9 +99,13 @@ export async function createWeightResult( inboundId: string, payload: CreateWeightResultRequest, ) { + const normalizedPayload = { + ...payload, + confidence: normalizeWeightConfidence(payload.confidence), + } const response = await http.post, ApiEnvelope>( `${measurementBasePath}/${segment(inboundId)}/weight-results`, - payload, + normalizedPayload, { params: { tenantId } }, ) return unwrapApiResponse(response) @@ -120,4 +138,3 @@ export async function confirmWeightResult( ) return unwrapApiResponse(response) } - diff --git a/src/modules/inbounds/weight/components/WeightOcrPanel.test.ts b/src/modules/inbounds/weight/components/WeightOcrPanel.test.ts index 3bb3b263..210e1d88 100644 --- a/src/modules/inbounds/weight/components/WeightOcrPanel.test.ts +++ b/src/modules/inbounds/weight/components/WeightOcrPanel.test.ts @@ -29,6 +29,7 @@ describe('WeightOcrPanel contract', () => { expect(source).toContain("['image/jpeg', 'image/png', 'image/bmp']") expect(source).toContain('5 * 1024 * 1024') expect(source).toContain('图片服务未返回 OCR 原文') + expect(source).toContain('ocrRawText: getWeightOcrRawText(upload)') expect(source).toContain("adjustmentReason: 'OCR 重试识别结果'") }) diff --git a/src/modules/inbounds/weight/components/WeightOcrPanel.vue b/src/modules/inbounds/weight/components/WeightOcrPanel.vue index 6efc8cc7..cd9c9eba 100644 --- a/src/modules/inbounds/weight/components/WeightOcrPanel.vue +++ b/src/modules/inbounds/weight/components/WeightOcrPanel.vue @@ -20,6 +20,7 @@ import { correctWeightResult, createWeightResult, downloadWeightImage, + getWeightOcrRawText, getWeightWorkspace, retryWeightRecognition, uploadWeightImage, @@ -153,7 +154,7 @@ async function handleFileChange(event: Event) { await createWeightResult(customerId.value, props.inboundId, { fileId: String(upload.fileId), ocrProvider: 'FILE_WEIGHT_OCR', - ocrRawText: null, + ocrRawText: getWeightOcrRawText(upload), ocrWeightValue: upload.weightValue, ocrWeightUnit: upload.weightUnit, confidence: upload.confidence, diff --git a/src/modules/inbounds/weight/types.ts b/src/modules/inbounds/weight/types.ts index 436d4bb2..c0c61630 100644 --- a/src/modules/inbounds/weight/types.ts +++ b/src/modules/inbounds/weight/types.ts @@ -37,6 +37,8 @@ export interface WeightImageUploadResult { weightValue: number | null weightUnit: string | null confidence: number | null + ocrRawText?: string | null + rawText?: string | null error: string | null } @@ -59,4 +61,3 @@ export interface CorrectWeightResultRequest { export interface ConfirmWeightResultRequest { version: number } -