feat: span transport plan list by plan and delivery column props
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
e241a17077
commit
47cd09d1e5
2 files changed
+155
-12
No files matched your search
@@ -2,8 +2,12 @@ import assert from 'node:assert/strict'
|
||||
import { describe, it } from 'node:test'
|
||||
import type { Plan, PlanStopProduct } from '@/api/pl'
|
||||
import {
|
||||
buildPlPlanListSpanMethod,
|
||||
flattenPlanArchivePairRows,
|
||||
matchLoadProduct
|
||||
flattenPlanListRows,
|
||||
matchLoadProduct,
|
||||
PL_DELIVERY_SPAN_PROPS,
|
||||
PL_PLAN_SPAN_PROPS
|
||||
} from './pl-plan-list-display-rows'
|
||||
|
||||
function sp(partial: Partial<PlanStopProduct> & Pick<PlanStopProduct, 'productId'>): PlanStopProduct {
|
||||
@@ -93,3 +97,95 @@ describe('flattenPlanArchivePairRows product rows', () => {
|
||||
assert.equal(rows[0].deliveryRowSpan, 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildPlPlanListSpanMethod two-level', () => {
|
||||
it('merges plan and delivery columns independently', () => {
|
||||
const rows = flattenPlanArchivePairRows([samplePlan()])
|
||||
const span = buildPlPlanListSpanMethod()
|
||||
const planFirst = span({
|
||||
row: rows[0],
|
||||
column: { property: 'loadCustomer' },
|
||||
rowIndex: 0,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.deepEqual(planFirst, { rowspan: 3, colspan: 1 })
|
||||
const planSecond = span({
|
||||
row: rows[1],
|
||||
column: { property: 'loadCustomer' },
|
||||
rowIndex: 1,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.deepEqual(planSecond, { rowspan: 0, colspan: 0 })
|
||||
const delFirst = span({
|
||||
row: rows[0],
|
||||
column: { property: 'deliveryCustomer' },
|
||||
rowIndex: 0,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.deepEqual(delFirst, { rowspan: 2, colspan: 1 })
|
||||
const delThird = span({
|
||||
row: rows[2],
|
||||
column: { property: 'deliveryCustomer' },
|
||||
rowIndex: 2,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.deepEqual(delThird, { rowspan: 1, colspan: 1 })
|
||||
const leaf = span({
|
||||
row: rows[0],
|
||||
column: { property: 'productName' },
|
||||
rowIndex: 0,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.equal(leaf, undefined)
|
||||
const sel = span({
|
||||
row: rows[0],
|
||||
column: { type: 'selection' },
|
||||
rowIndex: 0,
|
||||
columnIndex: 0
|
||||
})
|
||||
assert.deepEqual(sel, { rowspan: 3, colspan: 1 })
|
||||
assert.equal(PL_PLAN_SPAN_PROPS.has('loadAddressTime'), true)
|
||||
assert.equal(PL_DELIVERY_SPAN_PROPS.has('deliveryContract'), true)
|
||||
})
|
||||
|
||||
it('non-pair rows merge only plan columns by planRowSpan', () => {
|
||||
const rows = flattenPlanListRows([samplePlan()])
|
||||
const span = buildPlPlanListSpanMethod([], 3)
|
||||
assert.deepEqual(
|
||||
span({
|
||||
row: rows[0],
|
||||
column: { property: 'planDate' },
|
||||
rowIndex: 0,
|
||||
columnIndex: 0
|
||||
}),
|
||||
{ rowspan: 3, colspan: 1 }
|
||||
)
|
||||
assert.deepEqual(
|
||||
span({
|
||||
row: rows[1],
|
||||
column: { property: 'planDate' },
|
||||
rowIndex: 1,
|
||||
columnIndex: 0
|
||||
}),
|
||||
{ rowspan: 0, colspan: 0 }
|
||||
)
|
||||
assert.equal(
|
||||
span({
|
||||
row: rows[1],
|
||||
column: { property: 'deliveryCustomer' },
|
||||
rowIndex: 1,
|
||||
columnIndex: 0
|
||||
}),
|
||||
undefined
|
||||
)
|
||||
assert.equal(
|
||||
span({
|
||||
row: rows[2],
|
||||
column: { property: 'deliveryContract' },
|
||||
rowIndex: 2,
|
||||
columnIndex: 0
|
||||
}),
|
||||
undefined
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -18,7 +18,7 @@ export interface PlPlanListDisplayRow {
|
||||
stop: PlanLoad | PlanDelivery
|
||||
deliverySeq?: number
|
||||
/**
|
||||
* 归档配对行:一行 = 装货 × 一送货。
|
||||
* 归档配对行:一行 = 送货段 × 一产品。
|
||||
* 为 true 时 stop 为送货段,pairLoad 为装货段;kind 固定为 delivery。
|
||||
*/
|
||||
isPairRow?: boolean
|
||||
@@ -177,7 +177,7 @@ const EMPTY_DELIVERY_STOP: PlanDelivery = {
|
||||
}
|
||||
|
||||
/**
|
||||
* 归档列表配对展平:一行 = 装货 × 一个送货。
|
||||
* 归档列表配对展平:一行 = 送货段 × 一个产品(带配对装货产品)。
|
||||
* 无送货段时仍输出一行(送货侧为空),避免有装无送时整单消失。
|
||||
*/
|
||||
export function flattenPlanArchivePairRows(
|
||||
@@ -469,23 +469,70 @@ export function isPlPlanListPlanMergeColumn(
|
||||
return planColIndex >= 0 && planColIndex < visiblePlanProps.length
|
||||
}
|
||||
|
||||
export const PL_PLAN_SPAN_PROPS = new Set([
|
||||
'planNo',
|
||||
'followStatus',
|
||||
'planDate',
|
||||
'deliveryTimes',
|
||||
'planType',
|
||||
'licensePlate',
|
||||
'personnelSummary',
|
||||
'followUserName',
|
||||
'arrangeCopy',
|
||||
'archiveStatus',
|
||||
'documentAttachments',
|
||||
'erpEntered',
|
||||
'planAttachments',
|
||||
'carrierName',
|
||||
'hazardCertReady',
|
||||
'loadCustomer',
|
||||
'loadAddressTime',
|
||||
'loadContract',
|
||||
'loadDibang',
|
||||
'loadContractGap'
|
||||
])
|
||||
|
||||
export const PL_DELIVERY_SPAN_PROPS = new Set([
|
||||
'deliveryCustomer',
|
||||
'deliveryAddressTime',
|
||||
'deliveryContract',
|
||||
'deliveryDibang',
|
||||
'deliveryContractGap'
|
||||
])
|
||||
|
||||
export function buildPlPlanListSpanMethod(
|
||||
visiblePlanProps: string[],
|
||||
fixedMergeColCount: number = PLAN_FIXED_MERGE_COL_COUNT
|
||||
_visiblePlanProps?: string[],
|
||||
_fixedMergeColCount?: number
|
||||
): (args: {
|
||||
row: PlPlanListDisplayRow
|
||||
column: { type?: string; property?: string }
|
||||
rowIndex: number
|
||||
columnIndex: number
|
||||
}) => { rowspan: number; colspan: number } | undefined {
|
||||
const fixed = Math.max(0, fixedMergeColCount)
|
||||
const planMergeCount = fixed + visiblePlanProps.length
|
||||
return ({ row, columnIndex }) => {
|
||||
if (columnIndex >= planMergeCount) return undefined
|
||||
if (row.isPlanFirstRow) {
|
||||
return { rowspan: row.planRowSpan, colspan: 1 }
|
||||
return ({ row, column }) => {
|
||||
const type = column?.type
|
||||
const prop = column?.property || ''
|
||||
const isPlanCol =
|
||||
type === 'selection' || type === 'index' || PL_PLAN_SPAN_PROPS.has(prop)
|
||||
const isDeliveryCol = PL_DELIVERY_SPAN_PROPS.has(prop)
|
||||
|
||||
if (!row.isPairRow) {
|
||||
if (isPlanCol) {
|
||||
if (row.isPlanFirstRow) return { rowspan: row.planRowSpan, colspan: 1 }
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
|
||||
if (isPlanCol) {
|
||||
if (row.isPlanFirstRow) return { rowspan: row.planRowSpan, colspan: 1 }
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
}
|
||||
if (isDeliveryCol) {
|
||||
if (row.isDeliveryFirstRow) return { rowspan: row.deliveryRowSpan || 1, colspan: 1 }
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user