From ea38a386c9ab42e27394f6cdb96e760a42291eda Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Mon, 23 Oct 2023 17:17:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=A4=84=E7=90=86=E6=80=BB?= =?UTF-8?q?=E8=AE=A1=E5=B0=8F=E8=AE=A1=E5=9C=A8=20indexData=20=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E5=AD=98=E5=82=A8=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/__tests__/unit/facet/util.ts | 1 + .../unit/utils/dataset/pivot-dataset-spec.ts | 7 +- packages/s2-core/src/common/constant/basic.ts | 1 + .../data-set/custom-tree-pivot-data-set.ts | 6 +- packages/s2-core/src/data-set/interface.ts | 4 - .../s2-core/src/data-set/pivot-data-set.ts | 28 +++--- .../s2-core/src/data-set/table-data-set.ts | 2 +- .../facet/layout/build-row-tree-hierarchy.ts | 4 +- .../s2-core/src/utils/data-set-operate.ts | 9 +- .../src/utils/dataset/pivot-data-set.ts | 85 +++++++------------ 10 files changed, 56 insertions(+), 91 deletions(-) diff --git a/packages/s2-core/__tests__/unit/facet/util.ts b/packages/s2-core/__tests__/unit/facet/util.ts index 0a606dbf4c..e404e4ee32 100644 --- a/packages/s2-core/__tests__/unit/facet/util.ts +++ b/packages/s2-core/__tests__/unit/facet/util.ts @@ -13,6 +13,7 @@ export function getMockPivotMeta() { return transformIndexesData({ rows: fields.rows, columns: fields.columns, + values: fields.values, originData: data, indexesData: rawIndexesData, totalData, diff --git a/packages/s2-core/__tests__/unit/utils/dataset/pivot-dataset-spec.ts b/packages/s2-core/__tests__/unit/utils/dataset/pivot-dataset-spec.ts index 8dd7afa222..00f7ee3201 100644 --- a/packages/s2-core/__tests__/unit/utils/dataset/pivot-dataset-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/dataset/pivot-dataset-spec.ts @@ -35,13 +35,14 @@ describe('PivotDataSet util test', () => { }); test('for transformIndexesData function', () => { - const { rows, columns } = dataCfg.fields; + const { rows, columns, values } = dataCfg.fields; const sortedDimensionValues = {}; const rowPivotMeta = new Map(); const colPivotMeta = new Map(); const result = transformIndexesData({ rows, columns: columns as string[], + values, originData: dataCfg.data, totalData: [], indexesData: [], @@ -105,7 +106,6 @@ describe('PivotDataSet util test', () => { rowPivotMeta, colPivotMeta, isFirstCreate: true, - careUndefined: false, rowFields: rows, colFields: columns, }); @@ -124,7 +124,6 @@ describe('PivotDataSet util test', () => { rowPivotMeta, colPivotMeta, isFirstCreate: false, - careUndefined: false, }); expect(rowPivotMeta.size).toEqual(0); expect(colPivotMeta.size).toEqual(0); @@ -142,7 +141,6 @@ describe('PivotDataSet util test', () => { rowPivotMeta, colPivotMeta, isFirstCreate: true, - careUndefined: false, }); expect(rowPivotMeta.get(rowDimensionValues[0]).childField).toBeUndefined(); expect(colPivotMeta.get(colDimensionValues[0]).childField).toBeUndefined(); @@ -162,7 +160,6 @@ describe('PivotDataSet util test', () => { rowPivotMeta, colPivotMeta, isFirstCreate: true, - careUndefined: false, rowFields: rows, colFields: columns, }); diff --git a/packages/s2-core/src/common/constant/basic.ts b/packages/s2-core/src/common/constant/basic.ts index 913615b674..68c5b3e27d 100644 --- a/packages/s2-core/src/common/constant/basic.ts +++ b/packages/s2-core/src/common/constant/basic.ts @@ -3,6 +3,7 @@ export const VALUE_FIELD = '$$value$$'; export const EXTRA_FIELD = '$$extra$$'; export const EXTRA_COLUMN_FIELD = '$$extra_column$$'; export const TOTAL_VALUE = '$$total$$'; +export const MULTI_VALUE = '$$multi$$'; export const SERIES_NUMBER_FIELD = '$$series_number$$'; export const BACK_GROUND_GROUP_CONTAINER_Z_INDEX = 0; diff --git a/packages/s2-core/src/data-set/custom-tree-pivot-data-set.ts b/packages/s2-core/src/data-set/custom-tree-pivot-data-set.ts index c67f5df10d..02a1d871a0 100644 --- a/packages/s2-core/src/data-set/custom-tree-pivot-data-set.ts +++ b/packages/s2-core/src/data-set/custom-tree-pivot-data-set.ts @@ -13,7 +13,7 @@ import { PivotDataSet } from './pivot-data-set'; export class CustomTreePivotDataSet extends PivotDataSet { getCellData(params: CellDataParams): DataType { const { query } = params; - const { columns, rows } = this.fields; + const { rows, columns } = this.fields; const rowDimensionValues = transformDimensionsValues(query, rows); // 透视表下columns只支持简单结构 const colDimensionValues = transformDimensionsValues( @@ -25,10 +25,6 @@ export class CustomTreePivotDataSet extends PivotDataSet { colDimensionValues, rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, - isFirstCreate: true, - careUndefined: true, - rowFields: rows, - colFields: columns as string[], }); const data = get(this.indexesData, path); if (data) { diff --git a/packages/s2-core/src/data-set/interface.ts b/packages/s2-core/src/data-set/interface.ts index ff2f6a04c2..1af7fbd1b1 100644 --- a/packages/s2-core/src/data-set/interface.ts +++ b/packages/s2-core/src/data-set/interface.ts @@ -25,15 +25,11 @@ export type DataPathParams = { isFirstCreate?: boolean; // callback when pivot map create node onFirstCreate?: (params: { - // 是否是行头字段 - isRow: boolean; // 维度 id,如 city dimension: string; // 维度数组 ['四川省', '成都市'] dimensionPath: string[]; }) => void; - // use for multiple data queries(path contains undefined) - careUndefined?: boolean; // use in row tree mode to append fields information rowFields?: string[]; colFields?: string[]; diff --git a/packages/s2-core/src/data-set/pivot-data-set.ts b/packages/s2-core/src/data-set/pivot-data-set.ts index cf1d356476..f02983b0c2 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -40,14 +40,13 @@ import type { } from '../common/interface'; import { Node } from '../facet/layout/node'; import { - filterUndefined, + filterTotal, flatten as customFlatten, flattenDeep as customFlattenDeep, getAggregationAndCalcFuncByQuery, getFieldKeysByDimensionValues, getListBySorted, isEveryUndefined, - isTotalData, splitTotal, } from '../utils/data-set-operate'; import { @@ -165,7 +164,6 @@ export class PivotDataSet extends BaseDataSet { originData, totalData, indexesData: this.indexesData, - sortedDimensionValues: this.sortedDimensionValues, rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, @@ -329,7 +327,7 @@ export class PivotDataSet extends BaseDataSet { field, }), ); - return filterUndefined( + return filterTotal( uniq(getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues])), ); } @@ -371,16 +369,16 @@ export class PivotDataSet extends BaseDataSet { if (isEmpty(sortedMeta)) { return []; } - return filterUndefined(getListBySorted([...meta.keys()], sortedMeta)); + return filterTotal(getListBySorted([...meta.keys()], sortedMeta)); } if (this.sortedDimensionValues[field]) { - return filterUndefined( + return filterTotal( getDimensionsWithoutPathPre([...this.sortedDimensionValues[field]]), ); } - return filterUndefined([...meta.keys()]); + return filterTotal([...meta.keys()]); } getTotalValue(query: Query, totalStatus?: TotalStatus) { @@ -429,6 +427,7 @@ export class PivotDataSet extends BaseDataSet { if (!isTotals || isDrillDown) { rows = Node.getFieldPath(rowNode, isDrillDown) ?? originRows; } + const rowDimensionValues = transformDimensionsValues(query, rows); const colDimensionValues = transformDimensionsValues( query, @@ -437,8 +436,6 @@ export class PivotDataSet extends BaseDataSet { const path = getDataPath({ rowDimensionValues, colDimensionValues, - careUndefined: - isTotals || isTotalData([].concat(originRows).concat(columns), query), rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); @@ -447,7 +444,10 @@ export class PivotDataSet extends BaseDataSet { // 如果已经有数据则取已有数据 return DataHandler.createProxyData(data, query[EXTRA_FIELD]); } - return isTotals ? this.getTotalValue(query, totalStatus) : data; + + if (isTotals) { + return this.getTotalValue(query, totalStatus); + } } getCustomData = (path: number[]) => { @@ -630,9 +630,6 @@ export class PivotDataSet extends BaseDataSet { const path = getDataPath({ rowDimensionValues, colDimensionValues, - careUndefined: true, - rowFields: rows, - colFields: columns as string[], rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); @@ -646,7 +643,7 @@ export class PivotDataSet extends BaseDataSet { query: Query, isTotals?: boolean, isRow?: boolean, - drillDownFields?: string[], + drillDownFields: string[] = [], includeTotalData?: boolean, ): DataType[] { if (isEmpty(query)) { @@ -672,9 +669,6 @@ export class PivotDataSet extends BaseDataSet { const path = getDataPath({ rowDimensionValues, colDimensionValues, - careUndefined: true, - rowFields: rows, - colFields: columns as string[], rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); diff --git a/packages/s2-core/src/data-set/table-data-set.ts b/packages/s2-core/src/data-set/table-data-set.ts index e9926b6189..cfc94c41a7 100644 --- a/packages/s2-core/src/data-set/table-data-set.ts +++ b/packages/s2-core/src/data-set/table-data-set.ts @@ -171,7 +171,7 @@ export class TableDataSet extends BaseDataSet { return rowData[query.col]; } - public getMultiData(query: Query, isTotals?: boolean): DataType[] { + public getMultiData(): DataType[] { return this.displayData; } diff --git a/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts b/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts index 28697f9c11..052d8115a0 100644 --- a/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-row-tree-hierarchy.ts @@ -2,7 +2,7 @@ import { isNumber } from 'lodash'; import { i18n, ID_SEPARATOR, ROOT_ID } from '../../common'; import type { PivotDataSet } from '../../data-set'; import type { SpreadSheet } from '../../sheet-type'; -import { filterUndefined, getListBySorted } from '../../utils/data-set-operate'; +import { filterTotal, getListBySorted } from '../../utils/data-set-operate'; import { generateId } from '../../utils/layout/generate-id'; import type { FieldValue, TreeHeaderParams } from '../layout/interface'; import { layoutArrange, layoutHierarchy } from '../layout/layout-hooks'; @@ -53,7 +53,7 @@ export const buildRowTreeHierarchy = (params: TreeHeaderParams) => { const sortedDimensionValues = (dataSet as PivotDataSet)?.sortedDimensionValues?.[currentField] || []; - const unsortedDimValues = filterUndefined(Array.from(pivotMeta.keys())); + const unsortedDimValues = filterTotal(Array.from(pivotMeta.keys())); const dimValues = getListBySorted( unsortedDimValues, sortedDimensionValues, diff --git a/packages/s2-core/src/utils/data-set-operate.ts b/packages/s2-core/src/utils/data-set-operate.ts index 917fe0faff..5733e0a63d 100644 --- a/packages/s2-core/src/utils/data-set-operate.ts +++ b/packages/s2-core/src/utils/data-set-operate.ts @@ -1,4 +1,5 @@ -import { every, filter, get, isUndefined, keys, reduce } from 'lodash'; +import { every, get, isUndefined, keys, reduce } from 'lodash'; +import { TOTAL_VALUE } from '../common/constant/basic'; import type { Data, Fields, Totals, TotalsStatus } from '../common/interface'; export const getListBySorted = ( @@ -27,8 +28,8 @@ export const getListBySorted = ( }); }; -export const filterUndefined = (values: string[]) => { - return filter(values, (t) => !isUndefined(t) && t !== 'undefined'); +export const filterTotal = (values: string[] = []) => { + return values.filter((v) => v !== TOTAL_VALUE); }; export const flattenDeep = (data: Record[] | Record) => @@ -108,7 +109,7 @@ export const sortByItems = (arr1: string[], arr2: string[]) => { * @returns */ export const isTotalData = (ids: string[], data: Data): boolean => { - return !every(ids, (id) => data[id]); + return !every(ids, (id) => id in data); }; /** diff --git a/packages/s2-core/src/utils/dataset/pivot-data-set.ts b/packages/s2-core/src/utils/dataset/pivot-data-set.ts index a01caa2ec8..81f68af473 100644 --- a/packages/s2-core/src/utils/dataset/pivot-data-set.ts +++ b/packages/s2-core/src/utils/dataset/pivot-data-set.ts @@ -4,7 +4,6 @@ import { get, intersection, isEmpty, - isUndefined, last, reduce, set, @@ -12,6 +11,7 @@ import { import { EXTRA_FIELD, ID_SEPARATOR, + MULTI_VALUE, ROOT_ID, TOTAL_VALUE, } from '../../common/constant'; @@ -44,6 +44,7 @@ import type { Node } from '../../facet/layout/node'; export function transformDimensionsValues( record: DataType, dimensions: string[], + placeholder: string = TOTAL_VALUE, ): string[] { return reduce( dimensions, @@ -54,7 +55,7 @@ export function transformDimensionsValues( // push undefined when not exist const value = record[dimension]; if (!(dimension in record)) { - res.push(TOTAL_VALUE); + res.push(placeholder); } else { res.push(String(value)); } @@ -134,7 +135,6 @@ export function getDataPath(params: DataPathParams) { const { rowDimensionValues, colDimensionValues, - careUndefined, isFirstCreate, onFirstCreate, rowFields, @@ -156,55 +156,40 @@ export function getDataPath(params: DataPathParams) { }; // 根据行、列维度值生成对应的 path 路径,始终将总计小计置于第 0 位,明细数据从第 1 位开始,有两个情况: - // 如果是汇总格子: path = [0,0,0,0] path中会存在 0 的值 - // 如果是明细格子: path = [1,1,1] 数字均不为 0 + // 如果是汇总格子: path = [0, 0, 0, 0] path 中会存在 0 的值 + // 如果是明细格子: path = [1, 1, 1] 数字均不为 0 const getPath = ( + dimensions: string[], dimensionValues: string[], - isRow = true, - rowMeta: PivotMeta, - colMeta: PivotMeta, + pivotMeta: PivotMeta, ): number[] => { - let currentMeta = isRow ? rowMeta : colMeta; - const fields = isRow ? rowFields : colFields; + let currentMeta = pivotMeta; const path = []; for (let i = 0; i < dimensionValues.length; i++) { const value = dimensionValues[i]; - const isTotal = isUndefined(value); - if (!currentMeta.has(value)) { - if (isFirstCreate) { - currentMeta.set(value, { - level: isTotal ? 0 : currentMeta.size + 1, - children: - dimensionValues[i + 1] === EXTRA_FIELD - ? appendValues() - : new Map(), - }); - onFirstCreate?.({ - isRow, - dimension: fields?.[i], - dimensionPath: dimensionValues.slice(0, i + 1), - }); - } else { - const meta = currentMeta.get(value); - if (meta) { - path.push(meta.level); - } - if (!careUndefined) { - break; - } - } + if (isFirstCreate && !currentMeta.has(value)) { + const isTotal = value === TOTAL_VALUE; + + currentMeta.set(value, { + level: isTotal ? 0 : currentMeta.size + 1, + children: + dimensionValues[i + 1] === EXTRA_FIELD ? appendValues() : new Map(), + }); + + onFirstCreate?.({ + dimension: dimensions?.[i], + dimensionPath: dimensionValues.slice(0, i + 1), + }); } const meta = currentMeta.get(value); - if (isUndefined(value) && careUndefined) { - path.push(value); - } else { - path.push(meta?.level); - } + + path.push(value === MULTI_VALUE ? value : meta?.level); + if (meta) { - if (isFirstCreate) { + if (isFirstCreate && meta.childField !== dimensions?.[i + i]) { // mark the child field // NOTE: should take more care when reset meta.childField to undefined, the meta info is shared with brother nodes. - meta.childField = fields?.[i + 1]; + meta.childField = dimensions?.[i + 1]; } currentMeta = meta?.children; } @@ -212,13 +197,8 @@ export function getDataPath(params: DataPathParams) { return path; }; - const rowPath = getPath(rowDimensionValues, true, rowPivotMeta, colPivotMeta); - const colPath = getPath( - colDimensionValues, - false, - rowPivotMeta, - colPivotMeta, - ); + const rowPath = getPath(rowFields, rowDimensionValues, rowPivotMeta); + const colPath = getPath(colFields, colDimensionValues, colPivotMeta); return rowPath.concat(...colPath); } interface Param { @@ -258,8 +238,8 @@ export function transformIndexesData(params: Param) { /** * 在 PivotMap 创建新节点时,填充 sortedDimensionValues 维度数据 */ - const onFirstCreate = ({ isRow, dimension, dimensionPath }) => { - if (!isRow && repeatedDimensionSet.has(dimension)) { + const onFirstCreate = ({ dimension, dimensionPath }) => { + if (repeatedDimensionSet.has(dimension)) { // 当行、列都配置了同一维度字段时,因为 getDataPath 先处理行、再处理列 // 所有重复字段的维度值无需再加入到 sortedDimensionValues return; @@ -289,12 +269,11 @@ export function transformIndexesData(params: Param) { colDimensionValues, rowPivotMeta, colPivotMeta, - isFirstCreate: true, - onFirstCreate, - careUndefined: totalData?.length > 0, rowFields: rows, colFields: columns, valueFields: values, + isFirstCreate: true, + onFirstCreate, }); paths.push(path); set(indexesData, path, data);