From ce9d836194d5ef0d3e90cdb84ec78088d61d1f2f Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Mon, 12 Oct 2026 13:46:54 +0800 Subject: [PATCH] feat(web-admin): add freight config sample partition helper Co-authored-by: Cursor --- .../utils/sample-freight-config-guard.test.ts | 51 +++++++++++++++++++ .../src/utils/sample-freight-config-guard.ts | 30 +++++++++++ 2 files changed, 81 insertions(+) create mode 100644 web-admin/src/utils/sample-freight-config-guard.test.ts create mode 100644 web-admin/src/utils/sample-freight-config-guard.ts diff --git a/web-admin/src/utils/sample-freight-config-guard.test.ts b/web-admin/src/utils/sample-freight-config-guard.test.ts new file mode 100644 index 00000000..addc30bb --- /dev/null +++ b/web-admin/src/utils/sample-freight-config-guard.test.ts @@ -0,0 +1,51 @@ +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import { + partitionFreightConfigSamples, + freightConfigSkipMessage, + freightConfigAllConfiguredMessage +} from './sample-freight-config-guard' + +function row(partial: Record) { + return partial +} + +describe('partitionFreightConfigSamples', () => { + it('splits configured vs unconfigured (id / draft / freightId)', () => { + const selected = [ + row({ id: 'a', freight: { id: 'f1' } }), + row({ id: 'b', freightDraft: { clientKey: 'k1' } }), + row({ id: 'c', freightId: 'f2' }), + row({ id: 'd' }), + row({ id: 'e', freight: null, freightId: '' }) + ] + const { configurable, skipped } = partitionFreightConfigSamples(selected) + assert.deepEqual( + configurable.map((r) => r.id), + ['d', 'e'] + ) + assert.deepEqual( + skipped.map((r) => r.id), + ['a', 'b', 'c'] + ) + }) + + it('treats empty selection as no configurable', () => { + const { configurable, skipped } = partitionFreightConfigSamples([]) + assert.equal(configurable.length, 0) + assert.equal(skipped.length, 0) + }) +}) + +describe('freight config messages', () => { + it('builds skip and all-configured copy', () => { + assert.equal( + freightConfigSkipMessage(2), + '已跳过 2 个已配置运费的样本,将仅为其余样本配置运费' + ) + assert.equal( + freightConfigAllConfiguredMessage(), + '所选样本均已配置运费,请先取消运费后再配置' + ) + }) +}) diff --git a/web-admin/src/utils/sample-freight-config-guard.ts b/web-admin/src/utils/sample-freight-config-guard.ts new file mode 100644 index 00000000..097c1528 --- /dev/null +++ b/web-admin/src/utils/sample-freight-config-guard.ts @@ -0,0 +1,30 @@ +/** 协议单/运费配置:区分可配置与已配样本 */ + +export function sampleHasFreight(row: Record | null | undefined): boolean { + if (!row) return false + if (row.freight && typeof row.freight === 'object' && row.freight.id) return true + if (row.freightDraft && typeof row.freightDraft === 'object') return true + const fid = String(row.freightId || '').trim() + return !!fid +} + +export function partitionFreightConfigSamples>(selected: T[]): { + configurable: T[] + skipped: T[] +} { + const configurable: T[] = [] + const skipped: T[] = [] + for (const row of selected || []) { + if (sampleHasFreight(row)) skipped.push(row) + else configurable.push(row) + } + return { configurable, skipped } +} + +export function freightConfigSkipMessage(skippedCount: number): string { + return `已跳过 ${skippedCount} 个已配置运费的样本,将仅为其余样本配置运费` +} + +export function freightConfigAllConfiguredMessage(): string { + return '所选样本均已配置运费,请先取消运费后再配置' +}