From 9b5f285b72e68a0d2722411880bbd7c1f39d3382 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 24 Aug 2023 16:27:33 +0800 Subject: [PATCH 01/39] =?UTF-8?q?feat(Api):=20=E6=B7=BB=E5=8A=A0=20totalDi?= =?UTF-8?q?mensionGroup/subTotalDimensionGroup=20api=EF=BC=8C=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E4=B8=80=E4=BA=9B=E4=B8=B4=E6=97=B6=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/UTIL.ts | 6 + .../unit/data-process/new-total-spec.tsx | 191 ++++++++++++++++++ packages/s2-core/scripts/test-live.mjs | 4 +- .../s2-core/src/common/interface/basic.ts | 4 + 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 packages/s2-core/UTIL.ts create mode 100644 packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx diff --git a/packages/s2-core/UTIL.ts b/packages/s2-core/UTIL.ts new file mode 100644 index 0000000000..ffff5a5e32 --- /dev/null +++ b/packages/s2-core/UTIL.ts @@ -0,0 +1,6 @@ +import { cloneDeep } from 'lodash'; +// JUZEMARK +export const JUZELOG = (a, e?: any) => { + // eslint-disable-next-line no-console + console.log('**************\n', e || '', cloneDeep(a)); +}; diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx new file mode 100644 index 0000000000..380996173d --- /dev/null +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -0,0 +1,191 @@ +/** + * 透视表核心数据流程(保证基本数据正确) + * */ +// eslint-disable-next-line import/no-extraneous-dependencies +import { Aggregation } from '@antv/s2'; +import { assembleDataCfg, assembleOptions } from '../../util'; +import { getContainer } from '../../util/helpers'; +import { PivotSheet } from '@/sheet-type'; + +const myData = [ + { + cost: 537, + number: 7789, + province: '浙江省', + city: '杭州市', + type: '家具', + sub_type: '桌子', + }, + { + cost: 356, + number: 3877, + province: '浙江省', + city: '宁波市', + type: '家具', + sub_type: '桌子', + }, + { + cost: 5734, + number: 5343, + province: '浙江省', + city: '杭州市', + type: '家具', + sub_type: '沙发', + }, + { + cost: 957, + number: 7234, + province: '浙江省', + city: '宁波市', + type: '家具', + sub_type: '沙发', + }, + { + cost: 486, + number: 945, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '笔', + }, + { + cost: 357, + number: 1145, + province: '浙江省', + city: '宁波市', + type: '办公用品', + sub_type: '笔', + }, + { + cost: 513, + number: 1343, + province: '浙江省', + city: '杭州市', + type: '办公用品', + sub_type: '纸张', + }, + { + cost: 234, + number: 1523, + province: '浙江省', + city: '宁波市', + type: '办公用品', + sub_type: '纸张', + }, + { + cost: 456, + number: 1822, + province: '四川省', + city: '绵阳市', + type: '家具', + sub_type: '桌子', + }, + { + cost: 2654, + number: 1943, + province: '四川省', + city: '南充市', + type: '家具', + sub_type: '桌子', + }, + { + cost: 578, + number: 2244, + province: '四川省', + city: '绵阳市', + type: '家具', + sub_type: '沙发', + }, + { + cost: 687, + number: 2333, + province: '四川省', + city: '南充市', + type: '家具', + sub_type: '沙发', + }, + { + cost: 345, + number: 245, + province: '四川省', + city: '绵阳市', + type: '办公用品', + sub_type: '笔', + }, + { + cost: 756, + number: 2457, + province: '四川省', + city: '南充市', + type: '办公用品', + sub_type: '笔', + }, + { + cost: 243, + number: 3077, + province: '四川省', + city: '绵阳市', + type: '办公用品', + sub_type: '纸张', + }, + { + cost: 123, + number: 3551, + province: '四川省', + city: '南充市', + type: '办公用品', + sub_type: '纸张', + }, +]; +describe('Pivot Table Core Data Process', () => { + const s2 = new PivotSheet( + getContainer(), + assembleDataCfg({ + data: myData, + fields: { + rows: ['province', 'city', 'type'], + columns: ['sub_type'], + values: ['number'], + valueInCols: false, + customValueOrder: 2, + }, + totalData: [], + }), + assembleOptions({ + // hierarchyType: 'tree', + debug: false, + width: 1024, + height: 360, + totals: { + row: { + totalDimensionGroup: [], + calcTotals: { + aggregation: Aggregation.SUM, + }, + calcSubTotals: { + aggregation: Aggregation.SUM, + }, + showGrandTotals: true, + showSubTotals: true, + reverseLayout: true, + reverseSubLayout: true, + subTotalsDimensions: ['province'], + }, + col: { + calcTotals: { + aggregation: Aggregation.SUM, + }, + calcSubTotals: { + aggregation: Aggregation.SUM, + }, + showGrandTotals: true, + showSubTotals: true, + reverseLayout: true, + reverseSubLayout: true, + subTotalsDimensions: ['province'], + }, + }, + }), + ); + s2.render(); +}); diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index 1e49382250..daec8caa25 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,8 +9,8 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; +// JUZEMARK + const defaultPath = '__tests__/unit/data-process/new-total-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index 62d5c0a57f..605fd57285 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -151,6 +151,10 @@ export interface Total { label?: string; // sub label's display name, default = '小计' subLabel?: string; + /** 总计分组维度 */ + totalDimensionGroup?: string[]; + /** 小计分组维度 */ + subTotalDimensionGroup?: string[]; } /** From 66b633790504c76cb1a4da39f4dcf340016941e5 Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 25 Aug 2023 19:05:00 +0800 Subject: [PATCH 02/39] =?UTF-8?q?feat(Hierarchy):=20=E6=80=BB=E8=AE=A1?= =?UTF-8?q?=E5=B0=8F=E8=AE=A1=E7=BB=93=E7=82=B9=E4=B8=8B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?Hierarchy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 9 ++--- .../s2-core/src/common/interface/basic.ts | 4 +-- .../s2-core/src/data-set/base-data-set.ts | 22 ++++++++++++ .../s2-core/src/data-set/pivot-data-set.ts | 29 +++++++++++++++ packages/s2-core/src/facet/bbox/baseBBox.ts | 3 ++ .../src/facet/layout/build-gird-hierarchy.ts | 35 +++++++++++++++++-- .../s2-core/src/facet/layout/interface.ts | 6 ++++ .../s2-core/src/sheet-type/spread-sheet.ts | 2 ++ .../src/utils/layout/generate-header-nodes.ts | 19 ++++------ .../src/utils/layout/whether-leaf-by-level.ts | 13 +++++++ 10 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 packages/s2-core/src/utils/layout/whether-leaf-by-level.ts diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index 380996173d..44b2b87222 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -145,9 +145,9 @@ describe('Pivot Table Core Data Process', () => { fields: { rows: ['province', 'city', 'type'], columns: ['sub_type'], - values: ['number'], + values: ['number', 'cost'], valueInCols: false, - customValueOrder: 2, + // customValueOrder: 2, }, totalData: [], }), @@ -155,10 +155,11 @@ describe('Pivot Table Core Data Process', () => { // hierarchyType: 'tree', debug: false, width: 1024, - height: 360, + height: 600, totals: { row: { - totalDimensionGroup: [], + subTotalsDimensionsGroup: ['type'], + totalsDimensionsGroup: ['city'], calcTotals: { aggregation: Aggregation.SUM, }, diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index 605fd57285..94b7b22767 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -152,9 +152,9 @@ export interface Total { // sub label's display name, default = '小计' subLabel?: string; /** 总计分组维度 */ - totalDimensionGroup?: string[]; + totalsDimensionsGroup?: string[]; /** 小计分组维度 */ - subTotalDimensionGroup?: string[]; + subTotalsDimensionsGroup?: string[]; } /** diff --git a/packages/s2-core/src/data-set/base-data-set.ts b/packages/s2-core/src/data-set/base-data-set.ts index 49d0c36072..023d535e44 100644 --- a/packages/s2-core/src/data-set/base-data-set.ts +++ b/packages/s2-core/src/data-set/base-data-set.ts @@ -165,6 +165,28 @@ export abstract class BaseDataSet { */ public abstract getDimensionValues(field: string, query?: DataType): string[]; + /** + * province city type + * 辽宁省 + * 达州市 A + * B + * 芜湖市 C + * 浙江省 + * 杭州市 B + * D + * 宁波市 E + * query = {province: "浙江省"} + * field = 'type' + * * => [A,B,C] + * + * @param field current dimensions + * @param query dimension value query + */ + public abstract getTotalDimensionValues( + field: string, + query?: DataType, + ): string[]; + /** * In most cases, this function to get the specific * cross data cell data 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 af71751c04..622e921f77 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -317,6 +317,35 @@ export class PivotDataSet extends BaseDataSet { }; } + public getTotalDimensionValues(field: string, query?: DataType): string[] { + const { rows = [], columns = [] } = this.fields || {}; + let dimensions: string[] = []; + if (includes(rows, field)) { + dimensions = rows; + } else if (includes(columns, field)) { + dimensions = columns as string[]; + } + const allCurrentFieldDimensionValues = this.sortedDimensionValues[field]; + if (allCurrentFieldDimensionValues) { + for (const [dimension, index] of dimensions) { + if (field === dimension) { + break; + } + const value = get(query, dimension); + if (value) { + allCurrentFieldDimensionValues.filter((dim) => { + const arrTypeValue = dim.split(ID_SEPARATOR); + return arrTypeValue[index] === value; + }); + } + } + return uniq( + getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues]), + ); + } + return []; + } + public getDimensionValues(field: string, query?: DataType): string[] { const { rows = [], columns = [] } = this.fields || {}; let meta: PivotMeta = new Map(); diff --git a/packages/s2-core/src/facet/bbox/baseBBox.ts b/packages/s2-core/src/facet/bbox/baseBBox.ts index c7f304c474..480ac48d6b 100644 --- a/packages/s2-core/src/facet/bbox/baseBBox.ts +++ b/packages/s2-core/src/facet/bbox/baseBBox.ts @@ -2,6 +2,7 @@ import type { BBox } from '@antv/g-canvas'; import type { LayoutResult } from '../../common/interface'; import type { SpreadSheet } from '../../sheet-type'; import type { BaseFacet } from '../base-facet'; +import { JUZELOG } from '../../../UTIL'; // BBox相同数据结构,便于已有逻辑的直接复用 export abstract class BaseBBox implements BBox { @@ -41,6 +42,8 @@ export abstract class BaseBBox implements BBox { this.facet = facet; this.spreadsheet = facet.spreadsheet; this.layoutResult = facet.layoutResult; + // JUZEMARK + JUZELOG(this.layoutResult, 'layoutResult'); if (autoCalculateBBoxWhenCreated) { this.calculateBBox(); diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index bec4de2b0d..866e28ff86 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -7,6 +7,8 @@ import { getDimsCondition } from '../../utils/layout/get-dims-condition-by-node' import type { FieldValue, GridHeaderParams } from '../layout/interface'; import { layoutArrange } from '../layout/layout-hooks'; import { TotalMeasure } from '../layout/total-measure'; +import { whetherLeafByLevel } from '../../utils/layout/whether-leaf-by-level'; +import { TotalClass } from './total-class'; const hideMeasureColumn = ( fieldValues: FieldValue[], @@ -45,11 +47,38 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { let query = {}; if (parentNode.isTotals) { - // add total measures - if (addTotalMeasureInTotal) { - query = getDimsCondition(parentNode.parent, true); + const totalsConfig = spreadsheet.getTotalsConfig(currentField); + const dimensionGroup = parentNode.isGrandTotals + ? totalsConfig.totalsDimensionsGroup + : totalsConfig.subTotalsDimensionsGroup; + if (dimensionGroup?.includes(currentField)) { + query = getDimsCondition(parentNode); + const dimValues = dataSet.getTotalDimensionValues(currentField, query); + fieldValues.push( + ...(dimValues || []).map( + (v) => + new TotalClass(v, parentNode.isSubTotals, parentNode.isGrandTotals), + ), + ); + } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { // add total measures + query = getDimsCondition(parentNode.parent, true); fieldValues.push(...values.map((v) => new TotalMeasure(v))); + } else { + if (whetherLeafByLevel({ facetCfg, level: index, fields })) { + parentNode.isLeaf = true; + } else { + buildGridHierarchy({ + addTotalMeasureInTotal, + addMeasureInTotalQuery, + parentNode, + currentField: fields[index + 1], + fields, + facetCfg, + hierarchy, + }); + } + return; } } else { // field(dimension)'s all values diff --git a/packages/s2-core/src/facet/layout/interface.ts b/packages/s2-core/src/facet/layout/interface.ts index ab051f243d..45cae6244e 100644 --- a/packages/s2-core/src/facet/layout/interface.ts +++ b/packages/s2-core/src/facet/layout/interface.ts @@ -93,3 +93,9 @@ export interface CustomTreeHeaderParams { hierarchy: Hierarchy; customTreeItems: CustomTreeItem[]; } + +export interface WhetherLeafParams { + facetCfg: SpreadSheetFacetCfg; + fields: string[]; + level: number; +} diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 6fae391b5b..8b3e07b3ca 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -622,6 +622,8 @@ export abstract class SpreadSheet extends EE { reverseSubLayout: totalConfig.reverseSubLayout, label: totalConfig.label || i18n('总计'), subLabel: totalConfig.subLabel || i18n('小计'), + totalsDimensionsGroup: totalConfig.totalsDimensionsGroup, + subTotalsDimensionsGroup: totalConfig.subTotalsDimensionsGroup, }; } diff --git a/packages/s2-core/src/utils/layout/generate-header-nodes.ts b/packages/s2-core/src/utils/layout/generate-header-nodes.ts index 9a1db34d0f..dcb40a527e 100644 --- a/packages/s2-core/src/utils/layout/generate-header-nodes.ts +++ b/packages/s2-core/src/utils/layout/generate-header-nodes.ts @@ -12,6 +12,8 @@ import { TotalClass } from '../../facet/layout/total-class'; import { TotalMeasure } from '../../facet/layout/total-measure'; import { generateId } from '../../utils/layout/generate-id'; import type { Columns } from '../../common'; +import { JUZELOG } from '../../../UTIL'; +import { whetherLeafByLevel } from './whether-leaf-by-level'; export const generateHeaderNodes = (params: HeaderNodesParams) => { const { @@ -26,7 +28,7 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { addMeasureInTotalQuery, addTotalMeasureInTotal, } = params; - const { spreadsheet, collapsedCols, colCfg } = facetCfg; + const { spreadsheet, collapsedCols } = facetCfg; for (const [index, fieldValue] of fieldValues.entries()) { const isTotals = fieldValue instanceof TotalClass; @@ -48,20 +50,17 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { ...query, [EXTRA_FIELD]: spreadsheet?.dataSet?.fields.values[0], }; - isLeaf = true; } else { // root[&]四川[&]总计 => {province: '四川'} nodeQuery = query; - if (!addTotalMeasureInTotal) { - isLeaf = true; - } } + isLeaf = whetherLeafByLevel({ facetCfg, level, fields }); } else if (isTotalMeasure) { value = i18n((fieldValue as TotalMeasure).label); // root[&]四川[&]总计[&]price => {province: '四川',EXTRA_FIELD: 'price' } nodeQuery = { ...query, [EXTRA_FIELD]: value }; adjustedField = EXTRA_FIELD; - isLeaf = true; + isLeaf = whetherLeafByLevel({ facetCfg, level, fields }); } else if (spreadsheet.isTableMode()) { value = fieldValue; adjustedField = fields[index]; @@ -71,13 +70,7 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { value = fieldValue; // root[&]四川[&]成都 => {province: '四川', city: '成都' } nodeQuery = { ...query, [currentField]: value }; - const isValueInCols = spreadsheet.dataCfg.fields?.valueInCols ?? true; - const isHideMeasure = - colCfg?.hideMeasureColumn && - isValueInCols && - includes(fields, EXTRA_FIELD); - const extraSize = isHideMeasure ? 2 : 1; - isLeaf = level === fields.length - extraSize; + isLeaf = whetherLeafByLevel({ facetCfg, level, fields }); } const uniqueId = generateId(parentNode.id, value); if (!uniqueId) { diff --git a/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts b/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts new file mode 100644 index 0000000000..120d75db2c --- /dev/null +++ b/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts @@ -0,0 +1,13 @@ +import { includes } from 'lodash'; +import type { WhetherLeafParams } from '../../facet/layout/interface'; +import { EXTRA_FIELD } from '../../common'; + +export const whetherLeafByLevel = (params: WhetherLeafParams) => { + const { facetCfg, level, fields } = params; + const { colCfg, spreadsheet } = facetCfg; + const isValueInCols = spreadsheet.dataCfg.fields?.valueInCols ?? true; + const isHideMeasure = + colCfg?.hideMeasureColumn && isValueInCols && includes(fields, EXTRA_FIELD); + const extraSize = isHideMeasure ? 2 : 1; + return level === fields.length - extraSize; +}; From 800a919b5da2e6bace39f6a8708a3579df4d6655 Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 25 Aug 2023 20:54:05 +0800 Subject: [PATCH 03/39] =?UTF-8?q?feat(Render):=20getMultipleMap=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=8C=E8=AE=A1=E7=AE=97=E6=80=BB=E8=AE=A1?= =?UTF-8?q?=E5=B0=8F=E8=AE=A1=E4=B8=8B=E7=9A=84=E5=B8=83=E5=B1=80=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/facet/base-facet.ts | 1 + .../src/facet/layout/build-gird-hierarchy.ts | 6 ++-- packages/s2-core/src/facet/pivot-facet.ts | 29 +++++++++++++++++++ .../s2-core/src/sheet-type/spread-sheet.ts | 2 ++ .../src/utils/layout/generate-header-nodes.ts | 3 +- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 122ca8b64a..8ea72288a8 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -56,6 +56,7 @@ import { getAllChildCells } from '../utils/get-all-child-cells'; import { getColsForGrid, getRowsForGrid } from '../utils/grid'; import { diffPanelIndexes, type PanelIndexes } from '../utils/indexes'; import { isMobile, isWindows } from '../utils/is-mobile'; +import { JUZELOG } from '../../UTIL'; import { CornerBBox } from './bbox/cornerBBox'; import { PanelBBox } from './bbox/panelBBox'; import { diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index 866e28ff86..aadeadedef 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -44,6 +44,7 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { const { dataSet, values, spreadsheet } = facetCfg; const fieldValues: FieldValue[] = []; + const fieldName = dataSet.getFieldName(currentField); let query = {}; if (parentNode.isTotals) { @@ -60,6 +61,9 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { new TotalClass(v, parentNode.isSubTotals, parentNode.isGrandTotals), ), ); + if (isEmpty(fieldValues)) { + fieldValues.push(fieldName); + } } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { // add total measures query = getDimsCondition(parentNode.parent, true); @@ -96,8 +100,6 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { // add skeleton for empty data - const fieldName = dataSet.getFieldName(currentField); - if (isEmpty(fieldValues)) { if (currentField === EXTRA_FIELD) { fieldValues.push(...dataSet.fields?.values); diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index 559a2a43a8..ce4cc43464 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -31,6 +31,7 @@ import { getSubTotalNodeWidthOrHeightByLevel, } from '../utils/facet'; import { getCellWidth, safeJsonParse } from '../utils/text'; +import { JUZELOG } from '../../UTIL'; import { BaseFacet } from './base-facet'; import { buildHeaderHierarchy } from './layout/build-header-hierarchy'; import type { Hierarchy } from './layout/hierarchy'; @@ -517,6 +518,32 @@ export class PivotFacet extends BaseFacet { } } + private getMultipleMap( + hierarchy: Hierarchy, + isRowHeader?: boolean, + isSubTotal?: boolean, + ) { + const { maxLevel } = hierarchy; + const { totals, dataSet } = this.cfg; + const moreThanOneValue = dataSet.moreThanOneValue(); + const { rows, columns } = dataSet.fields; + const fields = isRowHeader ? rows : columns; + const totalConfig = isRowHeader ? totals.row : totals.col; + const dimensionGroup = isSubTotal + ? totalConfig.totalsDimensionsGroup + : totalConfig.subTotalsDimensionsGroup; + const multipleMap: number[] = Array.from({ length: maxLevel + 1 }, () => 1); + for (let level = maxLevel; level > 0; level--) { + const currentField = fields[level] as string; + // 若不符合【分组维度包含此维度】或【者指标维度下非单指标维度】,此表头单元格为空,将宽高合并到上级单元格 + const existValueField = currentField === EXTRA_FIELD && moreThanOneValue; + if (!(dimensionGroup.includes(currentField) || existValueField)) { + multipleMap[level - 1] += multipleMap[level]; + multipleMap[level] = 0; + } + } + } + /** * @description adjust the coordinate of total nodes and their children * @param hierarchy Hierarchy @@ -525,7 +552,9 @@ export class PivotFacet extends BaseFacet { private adjustTotalNodesCoordinate( hierarchy: Hierarchy, isRowHeader?: boolean, + isSubTotal?: boolean, ) { + this.getMultipleMap(hierarchy, isRowHeader, isSubTotal); const moreThanOneValue = this.cfg.dataSet.moreThanOneValue(); const { maxLevel } = hierarchy; const grandTotalNode = find( diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 8b3e07b3ca..0b093d28ee 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -69,6 +69,7 @@ import { getSafetyOptions, } from '../utils/merge'; import { getTooltipData, getTooltipOptions } from '../utils/tooltip'; +import { JUZELOG } from '../../UTIL'; export abstract class SpreadSheet extends EE { // theme config @@ -413,6 +414,7 @@ export abstract class SpreadSheet extends EE { this.clearDrillDownData('', true); this.dataSet.setDataCfg(this.dataCfg); } + this.buildFacet(); if (reBuildHiddenColumnsDetail) { this.initHiddenColumnsDetail(); diff --git a/packages/s2-core/src/utils/layout/generate-header-nodes.ts b/packages/s2-core/src/utils/layout/generate-header-nodes.ts index dcb40a527e..bb059e4323 100644 --- a/packages/s2-core/src/utils/layout/generate-header-nodes.ts +++ b/packages/s2-core/src/utils/layout/generate-header-nodes.ts @@ -1,4 +1,4 @@ -import { includes, isBoolean } from 'lodash'; +import { isBoolean } from 'lodash'; import { EXTRA_FIELD, SERIES_NUMBER_FIELD } from '../../common/constant'; import { i18n } from '../../common/i18n'; import { buildGridHierarchy } from '../../facet/layout/build-gird-hierarchy'; @@ -12,7 +12,6 @@ import { TotalClass } from '../../facet/layout/total-class'; import { TotalMeasure } from '../../facet/layout/total-measure'; import { generateId } from '../../utils/layout/generate-id'; import type { Columns } from '../../common'; -import { JUZELOG } from '../../../UTIL'; import { whetherLeafByLevel } from './whether-leaf-by-level'; export const generateHeaderNodes = (params: HeaderNodesParams) => { From a39c9ede9c4750ae66427afe1f5e56398a09e745 Mon Sep 17 00:00:00 2001 From: JuZe Date: Sun, 27 Aug 2023 18:57:12 +0800 Subject: [PATCH 04/39] =?UTF-8?q?feat(Render):=20=E6=8C=89=E7=BB=B4?= =?UTF-8?q?=E5=BA=A6=E5=88=86=E7=BB=84=E7=9A=84=E5=B0=8F=E8=AE=A1=E6=80=BB?= =?UTF-8?q?=E8=AE=A1=E4=B8=8B=E8=A1=A8=E5=A4=B4=E4=BD=8D=E7=BD=AE=E7=9A=84?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=92=8C=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 2 +- packages/s2-core/src/facet/pivot-facet.ts | 128 ++++-------------- packages/s2-core/src/utils/facet.ts | 12 -- 3 files changed, 28 insertions(+), 114 deletions(-) diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index 44b2b87222..a343a1a6a9 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -145,7 +145,7 @@ describe('Pivot Table Core Data Process', () => { fields: { rows: ['province', 'city', 'type'], columns: ['sub_type'], - values: ['number', 'cost'], + values: ['number'], valueInCols: false, // customValueOrder: 2, }, diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index ce4cc43464..c61670a13a 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -1,4 +1,5 @@ import { + filter, find, forEach, get, @@ -26,12 +27,8 @@ import { DebuggerUtil } from '../common/debug'; import type { LayoutResult, ViewMeta } from '../common/interface'; import { getDataCellId, handleDataItem } from '../utils/cell/data-cell'; import { getActionIconConfig } from '../utils/cell/header-cell'; -import { - getIndexRangeWithOffsets, - getSubTotalNodeWidthOrHeightByLevel, -} from '../utils/facet'; +import { getIndexRangeWithOffsets } from '../utils/facet'; import { getCellWidth, safeJsonParse } from '../utils/text'; -import { JUZELOG } from '../../UTIL'; import { BaseFacet } from './base-facet'; import { buildHeaderHierarchy } from './layout/build-header-hierarchy'; import type { Hierarchy } from './layout/hierarchy'; @@ -221,8 +218,8 @@ export class PivotFacet extends BaseFacet { } this.autoCalculateColNodeWidthAndX(colLeafNodes); if (!isEmpty(this.spreadsheet.options.totals?.col)) { - this.adjustTotalNodesCoordinate(colsHierarchy); - this.adjustSubTotalNodesCoordinate(colsHierarchy); + this.adjustTotalNodesCoordinate(colsHierarchy, false, true); + this.adjustTotalNodesCoordinate(colsHierarchy, false, false); } } @@ -488,8 +485,8 @@ export class PivotFacet extends BaseFacet { if (!isTree) { this.autoCalculateRowNodeHeightAndY(rowLeafNodes); if (!isEmpty(spreadsheet.options.totals?.row)) { - this.adjustTotalNodesCoordinate(rowsHierarchy, true); - this.adjustSubTotalNodesCoordinate(rowsHierarchy, true); + this.adjustTotalNodesCoordinate(rowsHierarchy, true, false); + this.adjustTotalNodesCoordinate(rowsHierarchy, true, true); } } } @@ -530,8 +527,8 @@ export class PivotFacet extends BaseFacet { const fields = isRowHeader ? rows : columns; const totalConfig = isRowHeader ? totals.row : totals.col; const dimensionGroup = isSubTotal - ? totalConfig.totalsDimensionsGroup - : totalConfig.subTotalsDimensionsGroup; + ? totalConfig.subTotalsDimensionsGroup + : totalConfig.totalsDimensionsGroup; const multipleMap: number[] = Array.from({ length: maxLevel + 1 }, () => 1); for (let level = maxLevel; level > 0; level--) { const currentField = fields[level] as string; @@ -542,109 +539,38 @@ export class PivotFacet extends BaseFacet { multipleMap[level] = 0; } } + return multipleMap; } /** - * @description adjust the coordinate of total nodes and their children + * @description adjust the coordinate of total / subTotal nodes and their children * @param hierarchy Hierarchy * @param isRowHeader boolean + * @param isSubTotal boolean */ private adjustTotalNodesCoordinate( hierarchy: Hierarchy, isRowHeader?: boolean, isSubTotal?: boolean, ) { - this.getMultipleMap(hierarchy, isRowHeader, isSubTotal); - const moreThanOneValue = this.cfg.dataSet.moreThanOneValue(); - const { maxLevel } = hierarchy; - const grandTotalNode = find( - hierarchy.getNodes(0), - (node: Node) => node.isGrandTotals, + const multipleMap = this.getMultipleMap(hierarchy, isRowHeader, isSubTotal); + const totalNodes = filter(hierarchy.getNodes(), (node: Node) => + isSubTotal ? node.isSubTotals : node.isGrandTotals, ); - if (!(grandTotalNode instanceof Node)) { - return; - } - const grandTotalChildren = grandTotalNode.children; - // 总计节点层级 (有且有两级) - if (isRowHeader) { - // 填充行总单元格宽度 - grandTotalNode.width = hierarchy.width; - // 调整其叶子节点位置和宽度 - forEach(grandTotalChildren, (node: Node) => { - const maxLevelNode = hierarchy.getNodes(maxLevel)[0]; - node.x = maxLevelNode.x; - node.width = maxLevelNode.width; - }); - } else if (maxLevel > 1 || (maxLevel <= 1 && !moreThanOneValue)) { - // 只有当列头总层级大于1级或列头为1级单指标时总计格高度才需要填充 - // 填充列总计单元格高度 - const grandTotalChildrenHeight = grandTotalChildren?.[0]?.height ?? 0; - grandTotalNode.height = hierarchy.height - grandTotalChildrenHeight; - // 调整其叶子结点位置, 以非小计行为准 - const positionY = find( - hierarchy.getNodes(maxLevel), - (node: Node) => !node.isTotalMeasure, - )?.y; - forEach(grandTotalChildren, (node: Node) => { - node.y = positionY; - }); - } - } - - /** - * @description adust the coordinate of subTotal nodes when there is just one value - * @param hierarchy Hierarchy - * @param isRowHeader boolean - */ - private adjustSubTotalNodesCoordinate( - hierarchy: Hierarchy, - isRowHeader?: boolean, - ) { - const subTotalNodes = hierarchy - .getNodes() - .filter((node: Node) => node.isSubTotals); - - if (isEmpty(subTotalNodes)) { - return; - } - const { maxLevel } = hierarchy; - forEach(subTotalNodes, (subTotalNode: Node) => { - const subTotalNodeChildren = subTotalNode.children; - if (isRowHeader) { - // 填充行总单元格宽度 - subTotalNode.width = getSubTotalNodeWidthOrHeightByLevel( - hierarchy.sampleNodesForAllLevels, - subTotalNode.level, - 'width', - ); - - // 调整其叶子结点位置 - forEach(subTotalNodeChildren, (node: Node) => { - node.x = hierarchy.getNodes(maxLevel)[0].x; - }); - } else { - // 填充列总单元格高度 - const totalHeight = getSubTotalNodeWidthOrHeightByLevel( - hierarchy.sampleNodesForAllLevels, - subTotalNode.level, - 'height', - ); - const subTotalNodeChildrenHeight = - subTotalNodeChildren?.[0]?.height ?? 0; - subTotalNode.height = totalHeight - subTotalNodeChildrenHeight; - // 调整其叶子结点位置,以非小计单元格为准 - forEach(subTotalNodeChildren, (node: Node) => { - node.y = hierarchy.getNodes(maxLevel)[0].y; - }); - // 调整其叶子结点位置, 以非小计行为准 - const positionY = find( - hierarchy.getNodes(maxLevel), - (node: Node) => !node.isTotalMeasure, - )?.y; - forEach(subTotalNodeChildren, (node: Node) => { - node.y = positionY; - }); + const key = isRowHeader ? 'width' : 'height'; + forEach(totalNodes, (node: Node) => { + let multiple = multipleMap[node.level]; + // 小计根节点倍数最小为1 + if (!multiple && isSubTotal) { + multiple = 1; + } + let res = 0; + for (let i = 0; i < multiple; i++) { + res += hierarchy.sampleNodesForAllLevels.find( + (sampleNode) => sampleNode.level === node.level + i, + )[key]; } + node[key] = res; }); } diff --git a/packages/s2-core/src/utils/facet.ts b/packages/s2-core/src/utils/facet.ts index 56377cdcf6..74db5444fd 100644 --- a/packages/s2-core/src/utils/facet.ts +++ b/packages/s2-core/src/utils/facet.ts @@ -1,16 +1,4 @@ import { findIndex } from 'lodash'; -import type { Node } from '../facet/layout/node'; - -export const getSubTotalNodeWidthOrHeightByLevel = ( - sampleNodesForAllLevels: Node[], - level: number, - key: 'width' | 'height', -) => { - return sampleNodesForAllLevels - .filter((node: Node) => node.level >= level) - .map((value) => value[key]) - .reduce((sum, current) => sum + current, 0); -}; /** * 根据视窗高度计算需要展示的数据数组下标 From d07e072a8a3255da5e32dea5d06bc119666bff1e Mon Sep 17 00:00:00 2001 From: JuZe Date: Tue, 29 Aug 2023 15:09:35 +0800 Subject: [PATCH 05/39] =?UTF-8?q?feat(DataSet):=20=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E5=88=86=E7=BB=84=E6=97=B6=E7=9A=84=E6=B1=87?= =?UTF-8?q?=E6=80=BB=E5=80=BC=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/UTIL.ts | 1 - .../unit/data-process/new-total-spec.tsx | 2 +- packages/s2-core/scripts/test-live.mjs | 1 - .../s2-core/src/data-set/base-data-set.ts | 2 +- packages/s2-core/src/data-set/interface.ts | 9 + .../s2-core/src/data-set/pivot-data-set.ts | 221 +++++++++++++----- .../s2-core/src/data-set/table-data-set.ts | 4 + packages/s2-core/src/facet/base-facet.ts | 1 - packages/s2-core/src/facet/bbox/baseBBox.ts | 3 - .../src/facet/layout/build-gird-hierarchy.ts | 9 +- packages/s2-core/src/facet/layout/node.ts | 5 + .../s2-core/src/facet/layout/total-class.ts | 5 + packages/s2-core/src/facet/pivot-facet.ts | 39 +++- .../s2-core/src/sheet-type/spread-sheet.ts | 5 +- .../src/utils/dataset/pivot-data-set.ts | 6 +- packages/s2-core/src/utils/export/copy.ts | 12 + .../s2-core/src/utils/layout/add-totals.ts | 4 +- .../src/utils/layout/generate-header-nodes.ts | 19 +- .../layout/get-dims-condition-by-node.ts | 2 +- 19 files changed, 252 insertions(+), 98 deletions(-) diff --git a/packages/s2-core/UTIL.ts b/packages/s2-core/UTIL.ts index ffff5a5e32..6e6d0c5af9 100644 --- a/packages/s2-core/UTIL.ts +++ b/packages/s2-core/UTIL.ts @@ -1,5 +1,4 @@ import { cloneDeep } from 'lodash'; -// JUZEMARK export const JUZELOG = (a, e?: any) => { // eslint-disable-next-line no-console console.log('**************\n', e || '', cloneDeep(a)); diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index a343a1a6a9..44b2b87222 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -145,7 +145,7 @@ describe('Pivot Table Core Data Process', () => { fields: { rows: ['province', 'city', 'type'], columns: ['sub_type'], - values: ['number'], + values: ['number', 'cost'], valueInCols: false, // customValueOrder: 2, }, diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index daec8caa25..8f919b7092 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,7 +9,6 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); -// JUZEMARK const defaultPath = '__tests__/unit/data-process/new-total-spec.tsx'; spinner.stop(); diff --git a/packages/s2-core/src/data-set/base-data-set.ts b/packages/s2-core/src/data-set/base-data-set.ts index 023d535e44..1c95f5e736 100644 --- a/packages/s2-core/src/data-set/base-data-set.ts +++ b/packages/s2-core/src/data-set/base-data-set.ts @@ -177,7 +177,7 @@ export abstract class BaseDataSet { * 宁波市 E * query = {province: "浙江省"} * field = 'type' - * * => [A,B,C] + * * => [B,D,E] * * @param field current dimensions * @param query dimension value query diff --git a/packages/s2-core/src/data-set/interface.ts b/packages/s2-core/src/data-set/interface.ts index c1570113d3..3d250ecad5 100644 --- a/packages/s2-core/src/data-set/interface.ts +++ b/packages/s2-core/src/data-set/interface.ts @@ -47,6 +47,15 @@ export interface CellDataParams { rowNode?: Node; // mark row's cell isRow?: boolean; + // use with isTotals + totalStatus?: TotalStatus; +} + +export interface TotalStatus { + isRowTotal: boolean; + isRowSubTotal: boolean; + isColTotal: boolean; + isColSubTotal: boolean; } export interface SortActionParams { 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 622e921f77..515422c732 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -1,5 +1,6 @@ import { compact, + concat, difference, each, every, @@ -64,6 +65,7 @@ import type { DataType, PivotMeta, SortedDimensionValues, + TotalStatus, } from './interface'; export class PivotDataSet extends BaseDataSet { @@ -396,10 +398,11 @@ export class PivotDataSet extends BaseDataSet { return filterUndefined([...meta.keys()]); } - getTotalValue(query: DataType) { + getTotalValue(query: DataType, totalStatus?: TotalStatus) { + const status = totalStatus || this.getTotalStatus(query); const { aggregation, calcFunc } = getAggregationAndCalcFuncByQuery( - this.getTotalStatus(query), + status, this.spreadsheet.options?.totals, ) || {}; const calcAction = calcActionByType[aggregation]; @@ -408,13 +411,11 @@ export class PivotDataSet extends BaseDataSet { if (calcAction || calcFunc) { const data = this.getMultiData(query); let totalValue: number; - if (calcFunc) { totalValue = calcFunc(query, data); } else if (calcAction) { totalValue = calcAction(data, VALUE_FIELD); } - return { ...query, [VALUE_FIELD]: totalValue, @@ -424,7 +425,7 @@ export class PivotDataSet extends BaseDataSet { } public getCellData(params: CellDataParams): DataType { - const { query, rowNode, isTotals = false } = params || {}; + const { query, rowNode, isTotals = false, totalStatus } = params || {}; const { columns, rows: originRows } = this.fields; let rows = originRows; @@ -456,8 +457,7 @@ export class PivotDataSet extends BaseDataSet { // 如果已经有数据则取已有数据 return data; } - - return isTotals ? this.getTotalValue(query) : data; + return isTotals ? this.getTotalValue(query, totalStatus) : data; } getCustomData = (path: number[]) => { @@ -511,6 +511,72 @@ export class PivotDataSet extends BaseDataSet { }; }; + // [undefined , '杭州市' , undefined , 'number'] => true + // ['浙江省' , '杭州市' , undefined , 'number'] => true + private checkExistDimensionGroup(query: DataType): boolean { + const { rows, columns } = this.fields; + const check = (dimensions: string[]) => { + let existDimensionValue = false; + for (let i = dimensions.length; i > 0; i--) { + const key = dimensions[i - 1]; + if (keys(query).includes(key)) { + if (key !== EXTRA_FIELD) { + existDimensionValue = true; + } + } else if (existDimensionValue) { + return true; + } + } + return false; + }; + return check(rows) || check(columns as string[]); + } + + /** + * 补足分组汇总场景的前置 undefined + * {undefined,'可乐','undefined','price'} + * => [ + * {'可口公司','可乐','undefined','price'}, + * {'百事公司','可乐','undefined','price'}, + * ] + */ + private getTotalGroupQueries(dimensions: string[], query) { + let queryArray = [query]; + let existDimensionGroupKey = null; + for (let i = dimensions.length; i > 0; i--) { + const key = dimensions[i - 1]; + if (keys(query).includes(key)) { + if (key !== EXTRA_FIELD) { + existDimensionGroupKey = key; + } + } else if (existDimensionGroupKey) { + const allCurrentFieldDimensionValues = + this.sortedDimensionValues[existDimensionGroupKey]; + const resKeys = []; + let res = []; + const arrayLength = + allCurrentFieldDimensionValues[0].split(ID_SEPARATOR).length; + for (const queryItem of queryArray) { + for (const dim of allCurrentFieldDimensionValues) { + const arrTypeValue = dim.split(ID_SEPARATOR); + if ( + arrTypeValue[arrayLength - 1] === + queryItem[existDimensionGroupKey] + ) { + resKeys.push(arrTypeValue[arrayLength - 2]); + } + } + const queryList = uniq(resKeys).map((v) => { + return { ...query, [key]: v }; + }); + res = concat(res, queryList); + } + queryArray = res; + } + } + return queryArray; + } + public getMultiData( query: DataType, isTotals?: boolean, @@ -524,68 +590,99 @@ export class PivotDataSet extends BaseDataSet { const totalRows = !isEmpty(drillDownFields) ? rows.concat(drillDownFields) : rows; - const rowDimensionValues = getQueryDimValues(totalRows, query); - const colDimensionValues = getQueryDimValues(columns as string[], query); - const path = getDataPath({ - rowDimensionValues, - colDimensionValues, - careUndefined: true, - isFirstCreate: true, - rowFields: rows, - colFields: columns as string[], - rowPivotMeta: this.rowPivotMeta, - colPivotMeta: this.colPivotMeta, - }); - const currentData = this.getCustomData(path); - let result = compact(customFlatten(currentData)); - if (isTotals) { - // 总计/小计(行/列) - // need filter extra data - // grand total => {$$extra$$: 'price'} - // sub total => {$$extra$$: 'price', category: 'xxxx'} - // [undefined, undefined, "price"] => [category] - let fieldKeys = []; - const rowKeys = getFieldKeysByDimensionValues(rowDimensionValues, rows); - const colKeys = getFieldKeysByDimensionValues( - colDimensionValues, - columns as string[], - ); - if (isRow) { - // 行总计 - fieldKeys = rowKeys; - } else { - // 只有一个值,此时为列总计 - const isCol = keys(query)?.length === 1 && has(query, EXTRA_FIELD); + // 当 undefined 维度后面有非 undefined,为维度分组场景,将非 undefined 维度前的维度填充为所有可能的维度值。 + // 如 [undefined , '杭州市' , undefined , 'number'] + const existDimensionGroup = this.checkExistDimensionGroup(query); + let result = []; + const getDataPathByRowCol = (row: string[], col: string[]) => + getDataPath({ + rowDimensionValues: row, + colDimensionValues: col, + careUndefined: true, + isFirstCreate: true, + rowFields: rows, + colFields: columns as string[], + rowPivotMeta: this.rowPivotMeta, + colPivotMeta: this.colPivotMeta, + }); - if (isCol) { - fieldKeys = colKeys; + if (existDimensionGroup) { + const rowTotalGroupQueries = this.getTotalGroupQueries(totalRows, query); + let totalGroupQueries = []; + for (const queryItem of rowTotalGroupQueries) { + totalGroupQueries = concat( + totalGroupQueries, + this.getTotalGroupQueries(columns as string[], queryItem), + ); + } + for (const queryItem of totalGroupQueries) { + const rowDimensionValues = getQueryDimValues(totalRows, queryItem); + const colDimensionValues = getQueryDimValues( + columns as string[], + queryItem, + ); + const path = getDataPathByRowCol( + rowDimensionValues, + colDimensionValues, + ); + const currentData = this.getCustomData(path); + result = concat(result, compact(customFlatten(currentData))); + } + } else { + const rowDimensionValues = getQueryDimValues(totalRows, query); + const colDimensionValues = getQueryDimValues(columns as string[], query); + const path = getDataPathByRowCol(rowDimensionValues, colDimensionValues); + const currentData = this.getCustomData(path); + result = compact(customFlatten(currentData)); + if (isTotals) { + // 总计/小计(行/列) + // need filter extra data + // grand total => {$$extra$$: 'price'} + // sub total => {$$extra$$: 'price', category: 'xxxx'} + // [undefined, undefined, "price"] => [category] + let fieldKeys = []; + const rowKeys = getFieldKeysByDimensionValues(rowDimensionValues, rows); + const colKeys = getFieldKeysByDimensionValues( + colDimensionValues, + columns as string[], + ); + if (isRow) { + // 行总计 + fieldKeys = rowKeys; } else { - const getTotalStatus = (dimensions: string[]) => { - return isEveryUndefined( - dimensions?.filter((item) => !valueList?.includes(item)), - ); - }; - const isRowTotal = getTotalStatus(colDimensionValues); - const isColTotal = getTotalStatus(rowDimensionValues); - - if (isRowTotal) { - // 行小计 - fieldKeys = rowKeys; - } else if (isColTotal) { - // 列小计 + // 只有一个值,此时为列总计 + const isCol = keys(query)?.length === 1 && has(query, EXTRA_FIELD); + + if (isCol) { fieldKeys = colKeys; } else { - // 行小计+列 or 列小计+行 - fieldKeys = [...rowKeys, ...colKeys]; + const getTotalStatus = (dimensions: string[]) => { + return isEveryUndefined( + dimensions?.filter((item) => !valueList?.includes(item)), + ); + }; + const isRowTotal = getTotalStatus(colDimensionValues); + const isColTotal = getTotalStatus(rowDimensionValues); + + if (isRowTotal) { + // 行小计 + fieldKeys = rowKeys; + } else if (isColTotal) { + // 列小计 + fieldKeys = colKeys; + } else { + // 行小计+列 or 列小计+行 + fieldKeys = [...rowKeys, ...colKeys]; + } } } + result = result.filter( + (r) => + !fieldKeys?.find( + (item) => item !== EXTRA_FIELD && keys(r)?.includes(item), + ), + ); } - result = result.filter( - (r) => - !fieldKeys?.find( - (item) => item !== EXTRA_FIELD && keys(r)?.includes(item), - ), - ); } return result || []; 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 0acd418e4e..c93a7c920b 100644 --- a/packages/s2-core/src/data-set/table-data-set.ts +++ b/packages/s2-core/src/data-set/table-data-set.ts @@ -149,6 +149,10 @@ export class TableDataSet extends BaseDataSet { }); }; + public getTotalDimensionValues(field: string, query?: DataType): string[] { + return []; + } + public getDimensionValues(field: string, query?: DataType): string[] { return []; } diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 8ea72288a8..122ca8b64a 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -56,7 +56,6 @@ import { getAllChildCells } from '../utils/get-all-child-cells'; import { getColsForGrid, getRowsForGrid } from '../utils/grid'; import { diffPanelIndexes, type PanelIndexes } from '../utils/indexes'; import { isMobile, isWindows } from '../utils/is-mobile'; -import { JUZELOG } from '../../UTIL'; import { CornerBBox } from './bbox/cornerBBox'; import { PanelBBox } from './bbox/panelBBox'; import { diff --git a/packages/s2-core/src/facet/bbox/baseBBox.ts b/packages/s2-core/src/facet/bbox/baseBBox.ts index 480ac48d6b..c7f304c474 100644 --- a/packages/s2-core/src/facet/bbox/baseBBox.ts +++ b/packages/s2-core/src/facet/bbox/baseBBox.ts @@ -2,7 +2,6 @@ import type { BBox } from '@antv/g-canvas'; import type { LayoutResult } from '../../common/interface'; import type { SpreadSheet } from '../../sheet-type'; import type { BaseFacet } from '../base-facet'; -import { JUZELOG } from '../../../UTIL'; // BBox相同数据结构,便于已有逻辑的直接复用 export abstract class BaseBBox implements BBox { @@ -42,8 +41,6 @@ export abstract class BaseBBox implements BBox { this.facet = facet; this.spreadsheet = facet.spreadsheet; this.layoutResult = facet.layoutResult; - // JUZEMARK - JUZELOG(this.layoutResult, 'layoutResult'); if (autoCalculateBBoxWhenCreated) { this.calculateBBox(); diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index aadeadedef..d4a3f7003c 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -58,7 +58,12 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { fieldValues.push( ...(dimValues || []).map( (v) => - new TotalClass(v, parentNode.isSubTotals, parentNode.isGrandTotals), + new TotalClass( + v, + parentNode.isSubTotals, + parentNode.isGrandTotals, + false, + ), ), ); if (isEmpty(fieldValues)) { @@ -66,7 +71,7 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { } } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { // add total measures - query = getDimsCondition(parentNode.parent, true); + query = getDimsCondition(parentNode); fieldValues.push(...values.map((v) => new TotalMeasure(v))); } else { if (whetherLeafByLevel({ facetCfg, level: index, fields })) { diff --git a/packages/s2-core/src/facet/layout/node.ts b/packages/s2-core/src/facet/layout/node.ts index 195bf0051a..cfc09d5466 100644 --- a/packages/s2-core/src/facet/layout/node.ts +++ b/packages/s2-core/src/facet/layout/node.ts @@ -21,6 +21,7 @@ export interface BaseNodeConfig { isSubTotals?: boolean; isCollapsed?: boolean; isGrandTotals?: boolean; + isTotalRoot?: boolean; hierarchy?: Hierarchy; isPivotMode?: boolean; seriesNumberWidth?: number; @@ -62,6 +63,7 @@ export class Node { isGrandTotals, isSubTotals, isCollapsed, + isTotalRoot, hierarchy, isPivotMode, seriesNumberWidth, @@ -95,6 +97,7 @@ export class Node { this.isLeaf = isLeaf; this.isGrandTotals = isGrandTotals; this.isSubTotals = isSubTotals; + this.isTotalRoot = isTotalRoot; this.extra = extra; } @@ -301,6 +304,8 @@ export class Node { public isSubTotals?: boolean; + public isTotalRoot?: boolean; + public hiddenChildNodeInfo?: HiddenColumnsInfo | null; public extra?: Record; diff --git a/packages/s2-core/src/facet/layout/total-class.ts b/packages/s2-core/src/facet/layout/total-class.ts index 51df2d35c1..75f3e40ef2 100644 --- a/packages/s2-core/src/facet/layout/total-class.ts +++ b/packages/s2-core/src/facet/layout/total-class.ts @@ -8,13 +8,18 @@ export class TotalClass { public isGrandTotals: boolean; + // 是否为 小计 总计 根结点,即value = “小计”,单元格,此类结点不参与 query + public isTotalRoot: boolean; + public constructor( label: string, isSubTotals = false, isGrandTotals = false, + isTotalRoot = false, ) { this.label = label; this.isSubTotals = isSubTotals; this.isGrandTotals = isGrandTotals; + this.isTotalRoot = isTotalRoot; } } diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index c61670a13a..5702001501 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -95,10 +95,17 @@ export class PivotFacet extends BaseFacet { } : {}; const dataQuery = merge({}, rowQuery, colQuery, measureInfo); + const totalStatus = { + isRowTotal: row.isGrandTotals, + isRowSubTotal: row.isSubTotals, + isColTotal: col.isGrandTotals, + isColSubTotal: col.isSubTotals, + }; const data = dataSet.getCellData({ query: dataQuery, rowNode: row, isTotals, + totalStatus, }); let valueField: string; let fieldValue = null; @@ -180,9 +187,17 @@ export class PivotFacet extends BaseFacet { ) { let preLeafNode = Node.blankNode(); const allNodes = colsHierarchy.getNodes(); - for (const levelSample of colsHierarchy.sampleNodesForAllLevels) { + const sampleNodesForAllLevels = colsHierarchy.sampleNodesForAllLevels; + for (let level = 0; level < sampleNodesForAllLevels.length; level++) { + const levelSample = sampleNodesForAllLevels[level]; levelSample.height = this.getColNodeHeight(levelSample); colsHierarchy.height += levelSample.height; + if (levelSample.level === 0) { + levelSample.y = 0; + } else { + const preLevelSample = sampleNodesForAllLevels[level - 1]; + levelSample.y = preLevelSample?.y + preLevelSample?.height ?? 0; + } } let currentCollIndex = 0; for (let i = 0; i < allNodes.length; i++) { @@ -209,11 +224,7 @@ export class PivotFacet extends BaseFacet { ); currentNode.y = preLevelSample?.y + preLevelSample?.height ?? 0; } - // 数值置于行头时, 列头的总计即叶子节点, 此时应该用列高: https://github.com/antvis/S2/issues/1715 - currentNode.height = - currentNode.isGrandTotals && currentNode.isLeaf - ? colsHierarchy.height - : this.getColNodeHeight(currentNode); + currentNode.height = this.getColNodeHeight(currentNode); layoutCoordinate(this.cfg, null, currentNode); } this.autoCalculateColNodeWidthAndX(colLeafNodes); @@ -309,6 +320,12 @@ export class PivotFacet extends BaseFacet { col.isTotalMeasure || rowNode.isTotals || rowNode.isTotalMeasure, + totalStatus: { + isRowTotal: rowNode.isGrandTotals, + isRowSubTotal: rowNode.isSubTotals, + isColTotal: col.isGrandTotals, + isColSubTotal: col.isSubTotals, + }, }); if (cellData) { @@ -527,8 +544,8 @@ export class PivotFacet extends BaseFacet { const fields = isRowHeader ? rows : columns; const totalConfig = isRowHeader ? totals.row : totals.col; const dimensionGroup = isSubTotal - ? totalConfig.subTotalsDimensionsGroup - : totalConfig.totalsDimensionsGroup; + ? totalConfig.subTotalsDimensionsGroup || [] + : totalConfig.totalsDimensionsGroup || []; const multipleMap: number[] = Array.from({ length: maxLevel + 1 }, () => 1); for (let level = maxLevel; level > 0; level--) { const currentField = fields[level] as string; @@ -654,6 +671,12 @@ export class PivotFacet extends BaseFacet { col.isTotalMeasure || rowNode.isTotals || rowNode.isTotalMeasure, + totalStatus: { + isRowTotal: rowNode.isGrandTotals, + isRowSubTotal: rowNode.isSubTotals, + isColTotal: col.isGrandTotals, + isColSubTotal: col.isSubTotals, + }, }); const cellDataKeys = keys(cellData); diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 0b093d28ee..78c6b7e508 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -69,7 +69,6 @@ import { getSafetyOptions, } from '../utils/merge'; import { getTooltipData, getTooltipOptions } from '../utils/tooltip'; -import { JUZELOG } from '../../UTIL'; export abstract class SpreadSheet extends EE { // theme config @@ -624,8 +623,8 @@ export abstract class SpreadSheet extends EE { reverseSubLayout: totalConfig.reverseSubLayout, label: totalConfig.label || i18n('总计'), subLabel: totalConfig.subLabel || i18n('小计'), - totalsDimensionsGroup: totalConfig.totalsDimensionsGroup, - subTotalsDimensionsGroup: totalConfig.subTotalsDimensionsGroup, + totalsDimensionsGroup: totalConfig.totalsDimensionsGroup || [], + subTotalsDimensionsGroup: totalConfig.subTotalsDimensionsGroup || [], }; } 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 85b3f7570f..e6b95a70aa 100644 --- a/packages/s2-core/src/utils/dataset/pivot-data-set.ts +++ b/packages/s2-core/src/utils/dataset/pivot-data-set.ts @@ -8,7 +8,6 @@ import { reduce, set, } from 'lodash'; -import { i18n } from '../../common/i18n'; import { EXTRA_FIELD, ID_SEPARATOR, ROOT_ID } from '../../common/constant'; import type { DataPathParams, @@ -189,7 +188,6 @@ export function getDataPath(params: DataPathParams) { } return path; }; - const rowPath = getPath(rowDimensionValues, true, rowPivotMeta, colPivotMeta); const colPath = getPath( colDimensionValues, @@ -197,9 +195,7 @@ export function getDataPath(params: DataPathParams) { rowPivotMeta, colPivotMeta, ); - const result = rowPath.concat(...colPath); - - return result; + return rowPath.concat(...colPath); } /** diff --git a/packages/s2-core/src/utils/export/copy.ts b/packages/s2-core/src/utils/export/copy.ts index 0c691d353d..479f9faf72 100644 --- a/packages/s2-core/src/utils/export/copy.ts +++ b/packages/s2-core/src/utils/export/copy.ts @@ -115,6 +115,12 @@ const getValueFromMeta = ( rowNode.isTotalMeasure || colNode.isTotals || colNode.isTotalMeasure, + totalStatus: { + isRowTotal: rowNode.isGrandTotals, + isRowSubTotal: rowNode.isSubTotals, + isColTotal: colNode.isGrandTotals, + isColSubTotal: colNode.isSubTotals, + }, }); return cell?.[VALUE_FIELD] ?? ''; } @@ -394,6 +400,12 @@ const getDataMatrix = ( rowNode.isTotalMeasure || colNode.isTotals || colNode.isTotalMeasure, + totalStatus: { + isRowTotal: rowNode.isGrandTotals, + isRowSubTotal: rowNode.isSubTotals, + isColTotal: colNode.isGrandTotals, + isColSubTotal: colNode.isSubTotals, + }, }); return getFormat( colNode.colIndex, diff --git a/packages/s2-core/src/utils/layout/add-totals.ts b/packages/s2-core/src/utils/layout/add-totals.ts index c267da8c33..ed87291a18 100644 --- a/packages/s2-core/src/utils/layout/add-totals.ts +++ b/packages/s2-core/src/utils/layout/add-totals.ts @@ -15,7 +15,7 @@ export const addTotals = (params: TotalParams) => { // check to see if grand total is added if (totalsConfig?.showGrandTotals) { action = totalsConfig.reverseLayout ? 'unshift' : 'push'; - totalValue = new TotalClass(totalsConfig.label, false, true); + totalValue = new TotalClass(totalsConfig.label, false, true, true); } } else if ( /** @@ -29,7 +29,7 @@ export const addTotals = (params: TotalParams) => { currentField !== EXTRA_FIELD ) { action = totalsConfig.reverseSubLayout ? 'unshift' : 'push'; - totalValue = new TotalClass(totalsConfig.subLabel, true); + totalValue = new TotalClass(totalsConfig.subLabel, true, false, true); } fieldValues[action]?.(totalValue); diff --git a/packages/s2-core/src/utils/layout/generate-header-nodes.ts b/packages/s2-core/src/utils/layout/generate-header-nodes.ts index bb059e4323..c72e7b62fe 100644 --- a/packages/s2-core/src/utils/layout/generate-header-nodes.ts +++ b/packages/s2-core/src/utils/layout/generate-header-nodes.ts @@ -37,21 +37,23 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { let isLeaf = false; let isGrandTotals = false; let isSubTotals = false; + let isTotalRoot = false; let adjustedField = currentField; if (isTotals) { const totalClass = fieldValue as TotalClass; isGrandTotals = totalClass.isGrandTotals; isSubTotals = totalClass.isSubTotals; + isTotalRoot = totalClass.isTotalRoot; value = i18n((fieldValue as TotalClass).label); - if (addMeasureInTotalQuery) { - // root[&]四川[&]总计 => {province: '四川', EXTRA_FIELD: 'price'} - nodeQuery = { - ...query, - [EXTRA_FIELD]: spreadsheet?.dataSet?.fields.values[0], - }; + if (isTotalRoot) { + nodeQuery = query; } else { // root[&]四川[&]总计 => {province: '四川'} - nodeQuery = query; + nodeQuery = { ...query, [currentField]: value }; + } + if (addMeasureInTotalQuery) { + // root[&]四川[&]总计 => {province: '四川', EXTRA_FIELD: 'price'} + nodeQuery[EXTRA_FIELD] = spreadsheet?.dataSet?.fields.values[0]; } isLeaf = whetherLeafByLevel({ facetCfg, level, fields }); } else if (isTotalMeasure) { @@ -59,6 +61,8 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { // root[&]四川[&]总计[&]price => {province: '四川',EXTRA_FIELD: 'price' } nodeQuery = { ...query, [EXTRA_FIELD]: value }; adjustedField = EXTRA_FIELD; + isGrandTotals = parentNode.isGrandTotals; + isSubTotals = parentNode.isSubTotals; isLeaf = whetherLeafByLevel({ facetCfg, level, fields }); } else if (spreadsheet.isTableMode()) { value = fieldValue; @@ -92,6 +96,7 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { isSubTotals, isTotalMeasure, isCollapsed, + isTotalRoot, hierarchy, query: nodeQuery, spreadsheet, diff --git a/packages/s2-core/src/utils/layout/get-dims-condition-by-node.ts b/packages/s2-core/src/utils/layout/get-dims-condition-by-node.ts index 35befc837a..3bc44b3b31 100644 --- a/packages/s2-core/src/utils/layout/get-dims-condition-by-node.ts +++ b/packages/s2-core/src/utils/layout/get-dims-condition-by-node.ts @@ -8,7 +8,7 @@ export function getDimsCondition(parent: Node, force?: boolean) { * 当为表格布局时,小计行的内容是“小计”不需要作为筛选条件 * 当为树状布局时,force可以强行指定小计行,即父类目作为筛选条件 */ - if (!p.isTotals || force) { + if (!p.isTotalRoot || force) { cond[p.key] = p.value; } p = p.parent; From 14a667a5edc0db6aab03aec1878e4863b30c8d0c Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 30 Aug 2023 13:56:43 +0800 Subject: [PATCH 06/39] =?UTF-8?q?feat(DataSet):=20=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E5=88=86=E7=BB=84=E6=97=B6=E7=9A=84=E6=B1=87?= =?UTF-8?q?=E6=80=BB=E5=80=BC=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 71 ++++++++++++++----- .../s2-core/src/data-set/pivot-data-set.ts | 9 ++- packages/s2-core/src/facet/base-facet.ts | 1 + .../src/facet/layout/build-gird-hierarchy.ts | 3 + packages/s2-core/src/facet/pivot-facet.ts | 10 ++- .../src/interaction/row-column-resize.ts | 2 + .../s2-core/src/sheet-type/spread-sheet.ts | 2 + 7 files changed, 75 insertions(+), 23 deletions(-) diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index 44b2b87222..8249ef4d70 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -137,16 +137,49 @@ const myData = [ sub_type: '纸张', }, ]; +const meta = [ + { + field: 'number', + name: '数量', + description: '数量说明。。', + }, + { + field: 'province', + name: '省份', + description: '省份说明。。', + }, + { + field: 'city', + name: '城市', + description: '城市说明。。', + }, + { + field: 'type', + name: '类别', + description: '类别说明。。', + }, + { + field: 'sub_type', + name: '子类别', + description: '子类别说明。。', + }, + { + field: 'cost', + name: '价格', + description: 'Value2', + }, +]; describe('Pivot Table Core Data Process', () => { const s2 = new PivotSheet( getContainer(), assembleDataCfg({ data: myData, + meta, fields: { - rows: ['province', 'city', 'type'], - columns: ['sub_type'], + rows: ['province', 'city', 'type', 'sub_type'], + columns: [], values: ['number', 'cost'], - valueInCols: false, + // valueInCols: false, // customValueOrder: 2, }, totalData: [], @@ -158,21 +191,8 @@ describe('Pivot Table Core Data Process', () => { height: 600, totals: { row: { - subTotalsDimensionsGroup: ['type'], - totalsDimensionsGroup: ['city'], - calcTotals: { - aggregation: Aggregation.SUM, - }, - calcSubTotals: { - aggregation: Aggregation.SUM, - }, - showGrandTotals: true, - showSubTotals: true, - reverseLayout: true, - reverseSubLayout: true, - subTotalsDimensions: ['province'], - }, - col: { + totalsDimensionsGroup: ['city', 'type'], + subTotalsDimensionsGroup: ['sub_type'], calcTotals: { aggregation: Aggregation.SUM, }, @@ -185,6 +205,21 @@ describe('Pivot Table Core Data Process', () => { reverseSubLayout: true, subTotalsDimensions: ['province'], }, + // col: { + // subTotalsDimensionsGroup: ['city'], + // totalsDimensionsGroup: ['sub_type'], + // calcTotals: { + // aggregation: Aggregation.SUM, + // }, + // calcSubTotals: { + // aggregation: Aggregation.SUM, + // }, + // showGrandTotals: true, + // showSubTotals: true, + // reverseLayout: true, + // reverseSubLayout: true, + // subTotalsDimensions: ['province'], + // }, }, }), ); 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 515422c732..7afaabd65a 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -202,6 +202,7 @@ export class PivotDataSet extends BaseDataSet { } // 2. 删除 rowPivotMeta 当前下钻层级对应 meta 信息 deleteMetaById(this.rowPivotMeta, rowNodeId); + // 3. 删除下钻缓存路径 idPathMap.delete(rowNodeId); @@ -359,7 +360,6 @@ export class PivotDataSet extends BaseDataSet { meta = this.colPivotMeta; dimensions = columns as string[]; } - if (!isEmpty(query)) { let sortedMeta = []; const dimensionValuePath = []; @@ -549,6 +549,10 @@ export class PivotDataSet extends BaseDataSet { if (key !== EXTRA_FIELD) { existDimensionGroupKey = key; } + queryArray = filter( + queryArray, + (queryItem) => queryItem[key] === query[key], + ); } else if (existDimensionGroupKey) { const allCurrentFieldDimensionValues = this.sortedDimensionValues[existDimensionGroupKey]; @@ -567,11 +571,12 @@ export class PivotDataSet extends BaseDataSet { } } const queryList = uniq(resKeys).map((v) => { - return { ...query, [key]: v }; + return { ...queryItem, [key]: v }; }); res = concat(res, queryList); } queryArray = res; + existDimensionGroupKey = key; } } return queryArray; diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 122ca8b64a..8ea72288a8 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -56,6 +56,7 @@ import { getAllChildCells } from '../utils/get-all-child-cells'; import { getColsForGrid, getRowsForGrid } from '../utils/grid'; import { diffPanelIndexes, type PanelIndexes } from '../utils/indexes'; import { isMobile, isWindows } from '../utils/is-mobile'; +import { JUZELOG } from '../../UTIL'; import { CornerBBox } from './bbox/cornerBBox'; import { PanelBBox } from './bbox/panelBBox'; import { diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index d4a3f7003c..25f3412275 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -75,7 +75,10 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { fieldValues.push(...values.map((v) => new TotalMeasure(v))); } else { if (whetherLeafByLevel({ facetCfg, level: index, fields })) { + // 如果最后一级没有分组维度,则将上一个结点设为叶子结点 parentNode.isLeaf = true; + hierarchy.pushIndexNode(parentNode); + parentNode.rowIndex = hierarchy.getIndexNodes().length - 1; } else { buildGridHierarchy({ addTotalMeasureInTotal, diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index 5702001501..f549e4f7dd 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -1,6 +1,5 @@ import { filter, - find, forEach, get, isArray, @@ -577,9 +576,14 @@ export class PivotFacet extends BaseFacet { const key = isRowHeader ? 'width' : 'height'; forEach(totalNodes, (node: Node) => { let multiple = multipleMap[node.level]; - // 小计根节点倍数最小为1 + // 小计根节点若为0,则改为最近上级倍数 - level 差 if (!multiple && isSubTotal) { - multiple = 1; + let lowerLevelIndex = 1; + while (!multiple) { + multiple = + multipleMap[node.level - lowerLevelIndex] - lowerLevelIndex; + lowerLevelIndex++; + } } let res = 0; for (let i = 0; i < multiple; i++) { diff --git a/packages/s2-core/src/interaction/row-column-resize.ts b/packages/s2-core/src/interaction/row-column-resize.ts index c0cedae59a..43df27d78a 100644 --- a/packages/s2-core/src/interaction/row-column-resize.ts +++ b/packages/s2-core/src/interaction/row-column-resize.ts @@ -25,6 +25,7 @@ import type { ResizeInfo, ResizePosition, } from '../common/interface/resize'; +import { JUZELOG } from '../../UTIL'; import { BaseEvent, type BaseEventImplement } from './base-interaction'; export class RowColumnResize extends BaseEvent implements BaseEventImplement { @@ -155,6 +156,7 @@ export class RowColumnResize extends BaseEvent implements BaseEventImplement { private bindMouseDown() { this.spreadsheet.on(S2Event.LAYOUT_RESIZE_MOUSE_DOWN, (event) => { + JUZELOG(this.spreadsheet.dataSet, 'resize-render-mouseDown'); const shape = event.target as IGroup; const originalEvent = event.originalEvent as MouseEvent; const resizeInfo = this.getCellAppendInfo(event.target); diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 78c6b7e508..b0cb5bd1e6 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -69,6 +69,7 @@ import { getSafetyOptions, } from '../utils/merge'; import { getTooltipData, getTooltipOptions } from '../utils/tooltip'; +import { JUZELOG } from '../../UTIL'; export abstract class SpreadSheet extends EE { // theme config @@ -406,6 +407,7 @@ export abstract class SpreadSheet extends EE { const { reBuildDataSet = false, reBuildHiddenColumnsDetail = true } = options; this.emit(S2Event.LAYOUT_BEFORE_RENDER); + JUZELOG(this.dataSet, 'render'); if (reBuildDataSet) { this.dataSet = this.getDataSet(this.options); } From e9d7e56374c9af6d01e72c4d4878b668b54d83dd Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 30 Aug 2023 16:00:19 +0800 Subject: [PATCH 07/39] =?UTF-8?q?feat(DataSet):=20=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E5=88=86=E7=BB=84=E6=97=B6=E7=9A=84=E6=B1=87?= =?UTF-8?q?=E6=80=BB=E5=80=BC=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../s2-core/src/data-set/pivot-data-set.ts | 83 ++++++++++++------- packages/s2-core/src/facet/base-facet.ts | 2 +- .../src/interaction/row-column-resize.ts | 2 - .../s2-core/src/sheet-type/spread-sheet.ts | 2 - 4 files changed, 54 insertions(+), 35 deletions(-) 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 7afaabd65a..d9b7874565 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -328,25 +328,20 @@ export class PivotDataSet extends BaseDataSet { } else if (includes(columns, field)) { dimensions = columns as string[]; } - const allCurrentFieldDimensionValues = this.sortedDimensionValues[field]; - if (allCurrentFieldDimensionValues) { - for (const [dimension, index] of dimensions) { - if (field === dimension) { - break; - } - const value = get(query, dimension); - if (value) { - allCurrentFieldDimensionValues.filter((dim) => { - const arrTypeValue = dim.split(ID_SEPARATOR); - return arrTypeValue[index] === value; - }); - } - } - return uniq( - getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues]), - ); - } - return []; + let allCurrentFieldDimensionValues = + this.sortedDimensionValues[field] || []; + allCurrentFieldDimensionValues = allCurrentFieldDimensionValues.filter( + (dimValue) => + this.checkAccordQueryWithDimensionValue( + dimValue, + query, + dimensions, + field, + ), + ); + return uniq( + getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues]), + ); } public getDimensionValues(field: string, query?: DataType): string[] { @@ -532,6 +527,35 @@ export class PivotDataSet extends BaseDataSet { return check(rows) || check(columns as string[]); } + /** + * 检查 DimensionValue 是否符合 query 条件 + * dimensions = ['province','city'] + * query = [province: '杭州市', type: '文具'] + * 浙江省[&]杭州市[&]家具[&]桌子 => true + * 四川省[&]成都市[&]文具[&]笔 => false + */ + private checkAccordQueryWithDimensionValue( + dimensionValues: string, + query, + dimensions: string[], + field: string, + ): boolean { + for (const [index, dimension] of dimensions.entries()) { + const queryValue = get(query, dimension); + if (queryValue) { + const arrTypeValue = dimensionValues.split(ID_SEPARATOR); + const dimensionValue = arrTypeValue[index]; + if (dimensionValue !== queryValue) { + return false; + } + } + if (field === dimension) { + break; + } + } + return true; + } + /** * 补足分组汇总场景的前置 undefined * {undefined,'可乐','undefined','price'} @@ -549,24 +573,24 @@ export class PivotDataSet extends BaseDataSet { if (key !== EXTRA_FIELD) { existDimensionGroupKey = key; } - queryArray = filter( - queryArray, - (queryItem) => queryItem[key] === query[key], - ); } else if (existDimensionGroupKey) { const allCurrentFieldDimensionValues = this.sortedDimensionValues[existDimensionGroupKey]; - const resKeys = []; let res = []; const arrayLength = allCurrentFieldDimensionValues[0].split(ID_SEPARATOR).length; for (const queryItem of queryArray) { - for (const dim of allCurrentFieldDimensionValues) { - const arrTypeValue = dim.split(ID_SEPARATOR); + const resKeys = []; + for (const dimValue of allCurrentFieldDimensionValues) { if ( - arrTypeValue[arrayLength - 1] === - queryItem[existDimensionGroupKey] + this.checkAccordQueryWithDimensionValue( + dimValue, + queryItem, + dimensions, + existDimensionGroupKey, + ) ) { + const arrTypeValue = dimValue.split(ID_SEPARATOR); resKeys.push(arrTypeValue[arrayLength - 2]); } } @@ -610,7 +634,6 @@ export class PivotDataSet extends BaseDataSet { rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); - if (existDimensionGroup) { const rowTotalGroupQueries = this.getTotalGroupQueries(totalRows, query); let totalGroupQueries = []; @@ -620,6 +643,7 @@ export class PivotDataSet extends BaseDataSet { this.getTotalGroupQueries(columns as string[], queryItem), ); } + for (const queryItem of totalGroupQueries) { const rowDimensionValues = getQueryDimValues(totalRows, queryItem); const colDimensionValues = getQueryDimValues( @@ -689,7 +713,6 @@ export class PivotDataSet extends BaseDataSet { ); } } - return result || []; } diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index 8ea72288a8..bf525db462 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -56,7 +56,6 @@ import { getAllChildCells } from '../utils/get-all-child-cells'; import { getColsForGrid, getRowsForGrid } from '../utils/grid'; import { diffPanelIndexes, type PanelIndexes } from '../utils/indexes'; import { isMobile, isWindows } from '../utils/is-mobile'; -import { JUZELOG } from '../../UTIL'; import { CornerBBox } from './bbox/cornerBBox'; import { PanelBBox } from './bbox/panelBBox'; import { @@ -1329,6 +1328,7 @@ export abstract class BaseFacet { this.spreadsheet.interaction.clearHoverTimer(); this.realCellRender(scrollX, scrollY); + this.updatePanelScrollGroup(); this.translateRelatedGroups(scrollX, scrollY, rowHeaderScrollX); this.clip(scrollX, scrollY); diff --git a/packages/s2-core/src/interaction/row-column-resize.ts b/packages/s2-core/src/interaction/row-column-resize.ts index 43df27d78a..c0cedae59a 100644 --- a/packages/s2-core/src/interaction/row-column-resize.ts +++ b/packages/s2-core/src/interaction/row-column-resize.ts @@ -25,7 +25,6 @@ import type { ResizeInfo, ResizePosition, } from '../common/interface/resize'; -import { JUZELOG } from '../../UTIL'; import { BaseEvent, type BaseEventImplement } from './base-interaction'; export class RowColumnResize extends BaseEvent implements BaseEventImplement { @@ -156,7 +155,6 @@ export class RowColumnResize extends BaseEvent implements BaseEventImplement { private bindMouseDown() { this.spreadsheet.on(S2Event.LAYOUT_RESIZE_MOUSE_DOWN, (event) => { - JUZELOG(this.spreadsheet.dataSet, 'resize-render-mouseDown'); const shape = event.target as IGroup; const originalEvent = event.originalEvent as MouseEvent; const resizeInfo = this.getCellAppendInfo(event.target); diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index b0cb5bd1e6..78c6b7e508 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -69,7 +69,6 @@ import { getSafetyOptions, } from '../utils/merge'; import { getTooltipData, getTooltipOptions } from '../utils/tooltip'; -import { JUZELOG } from '../../UTIL'; export abstract class SpreadSheet extends EE { // theme config @@ -407,7 +406,6 @@ export abstract class SpreadSheet extends EE { const { reBuildDataSet = false, reBuildHiddenColumnsDetail = true } = options; this.emit(S2Event.LAYOUT_BEFORE_RENDER); - JUZELOG(this.dataSet, 'render'); if (reBuildDataSet) { this.dataSet = this.getDataSet(this.options); } From 4ed13e1e39cd9f4dfc43777b02b1099ba4930443 Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 30 Aug 2023 17:50:10 +0800 Subject: [PATCH 08/39] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/data-set/pivot-data-set.ts | 10 ++++++++-- packages/s2-core/src/facet/base-facet.ts | 1 - .../s2-core/src/facet/layout/build-gird-hierarchy.ts | 1 + packages/s2-react/scripts/test-live.mjs | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) 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 d9b7874565..11cb774190 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -320,6 +320,8 @@ export class PivotDataSet extends BaseDataSet { }; } + // rows :['province','city','type'] + // query: ['浙江省',undefined] => return: ['文具','家具'] public getTotalDimensionValues(field: string, query?: DataType): string[] { const { rows = [], columns = [] } = this.fields || {}; let dimensions: string[] = []; @@ -506,8 +508,11 @@ export class PivotDataSet extends BaseDataSet { }; }; - // [undefined , '杭州市' , undefined , 'number'] => true - // ['浙江省' , '杭州市' , undefined , 'number'] => true + /** + * 检查是否属于需要填充中间汇总维度的场景 + * [undefined , '杭州市' , undefined , 'number'] => true + * ['浙江省' , '杭州市' , undefined , 'number'] => true + */ private checkExistDimensionGroup(query: DataType): boolean { const { rows, columns } = this.fields; const check = (dimensions: string[]) => { @@ -634,6 +639,7 @@ export class PivotDataSet extends BaseDataSet { rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); + // 有中间维度汇总的分组场景,将有中间汇总值的 query 处理为一组合法 query 后查询数据 if (existDimensionGroup) { const rowTotalGroupQueries = this.getTotalGroupQueries(totalRows, query); let totalGroupQueries = []; diff --git a/packages/s2-core/src/facet/base-facet.ts b/packages/s2-core/src/facet/base-facet.ts index bf525db462..122ca8b64a 100644 --- a/packages/s2-core/src/facet/base-facet.ts +++ b/packages/s2-core/src/facet/base-facet.ts @@ -1328,7 +1328,6 @@ export abstract class BaseFacet { this.spreadsheet.interaction.clearHoverTimer(); this.realCellRender(scrollX, scrollY); - this.updatePanelScrollGroup(); this.translateRelatedGroups(scrollX, scrollY, rowHeaderScrollX); this.clip(scrollX, scrollY); diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index 25f3412275..5a8d5eb9c8 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -80,6 +80,7 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { hierarchy.pushIndexNode(parentNode); parentNode.rowIndex = hierarchy.getIndexNodes().length - 1; } else { + // 如果是空维度,则跳转到下一级 level buildGridHierarchy({ addTotalMeasureInTotal, addMeasureInTotalQuery, diff --git a/packages/s2-react/scripts/test-live.mjs b/packages/s2-react/scripts/test-live.mjs index 6c92d162dc..33f08d1de8 100644 --- a/packages/s2-react/scripts/test-live.mjs +++ b/packages/s2-react/scripts/test-live.mjs @@ -10,7 +10,7 @@ async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; + const defaultPath = '__tests__/unit/data-process/new-total-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ From 5707e730e8c51daea76491b638ae7e92f0dd3c74 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 31 Aug 2023 10:14:05 +0800 Subject: [PATCH 09/39] =?UTF-8?q?feat:=20=E5=8D=95=E6=B5=8B=E5=BF=AB?= =?UTF-8?q?=E7=85=A7=E6=9B=B4=E6=96=B0=EF=BC=8C=E6=B7=BB=E5=8A=A0isTotalRo?= =?UTF-8?q?ot=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/corner-spec.ts.snap | 24 +++++++++++++++++++ .../__tests__/unit/utils/facet-spec.ts | 19 +-------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap index aa859d5c67..b3dc716fbd 100644 --- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap +++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap @@ -18,6 +18,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -47,6 +48,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -81,6 +83,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -110,6 +113,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -139,6 +143,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -173,6 +178,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city/数值", @@ -207,6 +213,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -236,6 +243,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city/数值", @@ -270,6 +278,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -299,6 +308,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -333,6 +343,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -362,6 +373,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -391,6 +403,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -425,6 +438,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city", @@ -459,6 +473,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -488,6 +503,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city", @@ -522,6 +538,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -551,6 +568,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -585,6 +603,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -614,6 +633,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "province", "label": "province", @@ -643,6 +663,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "city", "label": "city", @@ -677,6 +698,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city", @@ -711,6 +733,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "series-number-node", "label": "序号", @@ -740,6 +763,7 @@ Array [ "isPivotMode": true, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "province/city", diff --git a/packages/s2-core/__tests__/unit/utils/facet-spec.ts b/packages/s2-core/__tests__/unit/utils/facet-spec.ts index 6dc2ca2561..6ca9b3cccc 100644 --- a/packages/s2-core/__tests__/unit/utils/facet-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/facet-spec.ts @@ -1,28 +1,11 @@ import { - getSubTotalNodeWidthOrHeightByLevel, getIndexRangeWithOffsets, getAdjustedRowScrollX, getAdjustedScrollOffset, } from '@/utils/facet'; describe('Facet util test', () => { - test('should get correct width of subTotal node', () => { - const sampleNodesForAllLevels = [ - { - id: 'root[&]测试', - value: '测试', - isSubTotals: true, - width: 20, - level: 0, - }, - ]; - expect( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - getSubTotalNodeWidthOrHeightByLevel(sampleNodesForAllLevels, -1, 'width'), - ).toEqual(20); - expect(getSubTotalNodeWidthOrHeightByLevel([], -1, 'width')).toEqual(0); - }); + // JUZEMARK 倍数Map test('should get correct index range for given offsets', () => { const offsets = [0, 30, 60, 90, 120, 150, 160, 170, 190]; From 2d1c143b7ffb367039e83f132036bbaf9bb6f4a3 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 31 Aug 2023 10:32:57 +0800 Subject: [PATCH 10/39] =?UTF-8?q?fix:=20=E6=9C=89=E5=A4=9A=E4=B8=AA=20Valu?= =?UTF-8?q?e=20=E6=97=B6=E4=B8=8D=E5=85=81=E8=AE=B8=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E5=BA=A6=E9=87=8F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/__tests__/bugs/issue-1715-spec.ts | 7 ++++--- .../s2-core/src/utils/layout/whether-leaf-by-level.ts | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/s2-core/__tests__/bugs/issue-1715-spec.ts b/packages/s2-core/__tests__/bugs/issue-1715-spec.ts index 28436e1d61..7018af631d 100644 --- a/packages/s2-core/__tests__/bugs/issue-1715-spec.ts +++ b/packages/s2-core/__tests__/bugs/issue-1715-spec.ts @@ -81,9 +81,10 @@ describe('Multi Values GrandTotal Height Test', () => { const grandTotalsNode = s2 .getColumnNodes() - .find((node) => node.isGrandTotals); + .find((node) => node.isGrandTotals && node.isTotalRoot); - expect(s2.facet.layoutResult.colsHierarchy.height).toBe(60); - expect(grandTotalsNode.height).toEqual(30); + // 有多个 Value 时不允许隐藏度量列 + expect(s2.facet.layoutResult.colsHierarchy.height).toBe(90); + expect(grandTotalsNode.height).toEqual(60); }); }); diff --git a/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts b/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts index 120d75db2c..c03632b673 100644 --- a/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts +++ b/packages/s2-core/src/utils/layout/whether-leaf-by-level.ts @@ -4,10 +4,14 @@ import { EXTRA_FIELD } from '../../common'; export const whetherLeafByLevel = (params: WhetherLeafParams) => { const { facetCfg, level, fields } = params; - const { colCfg, spreadsheet } = facetCfg; + const { colCfg, spreadsheet, dataSet } = facetCfg; + const moreThanOneValue = dataSet.moreThanOneValue(); const isValueInCols = spreadsheet.dataCfg.fields?.valueInCols ?? true; const isHideMeasure = - colCfg?.hideMeasureColumn && isValueInCols && includes(fields, EXTRA_FIELD); + colCfg?.hideMeasureColumn && + isValueInCols && + !moreThanOneValue && + includes(fields, EXTRA_FIELD); const extraSize = isHideMeasure ? 2 : 1; return level === fields.length - extraSize; }; From 0c1686ba342650124c2cc78eaf90ff0f883d7fe0 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 31 Aug 2023 11:02:26 +0800 Subject: [PATCH 11/39] =?UTF-8?q?fix:=20=E6=9C=89=E5=A4=9A=E4=B8=AA=20Valu?= =?UTF-8?q?e=20=E6=97=B6=E4=B8=8D=E5=85=81=E8=AE=B8=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E5=BA=A6=E9=87=8F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../s2-core/__tests__/unit/data-process/new-total-spec.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index 8249ef4d70..1710be49a7 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -178,7 +178,7 @@ describe('Pivot Table Core Data Process', () => { fields: { rows: ['province', 'city', 'type', 'sub_type'], columns: [], - values: ['number', 'cost'], + values: ['number'], // valueInCols: false, // customValueOrder: 2, }, @@ -186,6 +186,11 @@ describe('Pivot Table Core Data Process', () => { }), assembleOptions({ // hierarchyType: 'tree', + style: { + colCfg: { + hideMeasureColumn: true, + }, + }, debug: false, width: 1024, height: 600, From 68e98fea3f0231d7f0bd84db37737e6fef90d197 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 31 Aug 2023 14:36:04 +0800 Subject: [PATCH 12/39] =?UTF-8?q?fix:=20=E5=88=A0=E9=99=A4=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E8=8E=AB=E5=90=8D=E5=85=B6=E5=A6=99=E7=9A=84?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/facet/layout/build-gird-hierarchy.ts | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index bec4de2b0d..e0ec427327 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -1,6 +1,5 @@ import { isEmpty, isUndefined } from 'lodash'; import { EXTRA_FIELD } from '../../common/constant'; -import type { SpreadSheetFacetCfg } from '../../common/interface'; import { addTotals } from '../../utils/layout/add-totals'; import { generateHeaderNodes } from '../../utils/layout/generate-header-nodes'; import { getDimsCondition } from '../../utils/layout/get-dims-condition-by-node'; @@ -8,20 +7,6 @@ import type { FieldValue, GridHeaderParams } from '../layout/interface'; import { layoutArrange } from '../layout/layout-hooks'; import { TotalMeasure } from '../layout/total-measure'; -const hideMeasureColumn = ( - fieldValues: FieldValue[], - field: string, - cfg: SpreadSheetFacetCfg, -) => { - const hideMeasure = cfg.colCfg?.hideMeasureColumn ?? false; - const valueInCol = cfg.dataSet.fields.valueInCols; - for (const value of fieldValues) { - if (hideMeasure && valueInCol && field === EXTRA_FIELD) { - fieldValues.splice(fieldValues.indexOf(value), 1); - } - } -}; - /** * Build grid hierarchy in rows or columns * @@ -76,8 +61,7 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { fieldValues.push(fieldName); } } - // hide measure in columns - hideMeasureColumn(fieldValues, currentField, facetCfg); + // add totals if needed addTotals({ currentField, From ae46e08675b520aa650a0eb492c7d9a5c10350fe Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 31 Aug 2023 18:31:43 +0800 Subject: [PATCH 13/39] =?UTF-8?q?test:=20=E6=8C=89=E7=BB=B4=E5=BA=A6?= =?UTF-8?q?=E5=88=86=E7=BB=84=E6=B1=87=E6=80=BB=E8=83=BD=E5=8A=9B=E5=8D=95?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 25 +- .../data-set/pivot-data-set-total-spec.ts | 240 ++++++++++++++++++ .../__tests__/unit/facet/pivot-facet-spec.ts | 1 + .../unit/utils/export/export-spec.ts | 8 +- .../s2-core/src/data-set/pivot-data-set.ts | 14 +- 5 files changed, 279 insertions(+), 9 deletions(-) diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index 1710be49a7..f7f3f6f1d3 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -9,8 +9,29 @@ import { PivotSheet } from '@/sheet-type'; const myData = [ { - cost: 537, - number: 7789, + cost: 99099, + number: 99099, + city: '杭州市', + type: '家具', + sub_type: '桌子', + }, + { + cost: 99099, + number: 99099, + province: '浙江省', + city: '杭州市', + sub_type: '桌子', + }, + { + cost: 99099, + number: 99099, + province: '浙江省', + city: '杭州市', + type: '家具', + }, + { + cost: 99099, + number: 99099, province: '浙江省', city: '杭州市', type: '家具', diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts index cb791efaed..f87a27ff43 100644 --- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts +++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts @@ -443,6 +443,62 @@ describe('Pivot Dataset Total Test', () => { dataSet = new PivotDataSet(mockSheet); dataSet.setDataCfg(dataCfg); }); + + test('should get correct total cell data when totals calculated by calcFunc and Existential dimension grouping', () => { + const totalStatus = { + isRowTotal: true, + isColTotal: true, + isRowSubTotal: true, + isColSubTotal: true, + }; + + expect( + dataSet.getCellData({ + query: { + province: '浙江省', + sub_type: '桌子', + [EXTRA_FIELD]: 'number', + }, + isTotals: true, + totalStatus, + }), + ).toContainEntries([[VALUE_FIELD, 18375]]); + + expect( + dataSet.getCellData({ + query: { + province: '浙江省', + [EXTRA_FIELD]: 'number', + }, + totalStatus, + isTotals: true, + }), + ).toContainEntries([[VALUE_FIELD, 43098]]); + + expect( + dataSet.getCellData({ + query: { + sub_type: '桌子', + [EXTRA_FIELD]: 'number', + }, + totalStatus, + isTotals: true, + }), + ).toContainEntries([[VALUE_FIELD, 26193]]); + + expect( + dataSet.getCellData({ + query: { + province: '浙江省', + type: '家具', + [EXTRA_FIELD]: 'number', + }, + isTotals: true, + totalStatus, + }), + ).toContainEntries([[VALUE_FIELD, 32418]]); + }); + test('should get correct total cell data when totals calculated by calcFunc', () => { expect( dataSet.getCellData({ @@ -675,4 +731,188 @@ describe('Pivot Dataset Total Test', () => { expect(isColSubTotal4).toBeTrue(); }); }); + + describe('test for total with dimension group', () => { + beforeEach(() => { + MockPivotSheet.mockClear(); + const mockSheet = new MockPivotSheet(); + mockSheet.store = new Store(); + mockSheet.isValueInCols = () => true; + dataSet = new PivotDataSet(mockSheet); + + dataCfg = assembleDataCfg({ + meta: [], + fields: { + rows: ['province', 'city', 'type', 'sub_type'], + columns: [], + }, + }); + dataSet.setDataCfg(dataCfg); + }); + test('should get correct total dimension values', () => { + expect( + dataSet.getTotalDimensionValues('sub_type', { + province: '浙江省', + city: undefined, + }), + ).toEqual(['桌子', '沙发', '笔', '纸张']); + + expect( + dataSet.getTotalDimensionValues('sub_type', { + province: '浙江省', + city: undefined, + }), + ).toEqual(['桌子', '沙发', '笔', '纸张']); + + expect( + dataSet.getTotalDimensionValues('sub_type', { + province: undefined, + city: undefined, + type: '办公用品', + }), + ).toEqual(['笔', '纸张']); + + expect(dataSet.getTotalDimensionValues('city', {})).toEqual([ + '杭州市', + '绍兴市', + '宁波市', + '舟山市', + '成都市', + '绵阳市', + '南充市', + '乐山市', + ]); + + expect( + dataSet.getTotalDimensionValues('sub_type', { + province: undefined, + city: undefined, + type: undefined, + }), + ).toEqual(['桌子', '沙发', '笔', '纸张']); + }); + + test('should get correct boolean of grouping scenarios where query need to be processed', () => { + expect( + dataSet.checkExistDimensionGroup({ + province: 'A', + type: 'A', + sub_type: 'A', + }), + ).toEqual(true); + expect( + dataSet.checkExistDimensionGroup({ + province: 'A', + sub_type: 'A', + }), + ).toEqual(true); + expect( + dataSet.checkExistDimensionGroup({ + province: 'A', + city: 'A', + sub_type: 'A', + }), + ).toEqual(true); + expect( + dataSet.checkExistDimensionGroup({ + city: 'A', + sub_type: 'A', + }), + ).toEqual(true); + expect( + dataSet.checkExistDimensionGroup({ + province: 'A', + city: 'A', + }), + ).toEqual(false); + expect( + dataSet.checkExistDimensionGroup({ + province: 'A', + city: 'A', + type: 'A', + }), + ).toEqual(false); + }); + test('should get correct boolean of dimensionValue is a query condition', () => { + expect( + dataSet.checkAccordQueryWithDimensionValue( + '浙江省[&]杭州市[&]家具[&]桌子', + { + province: '浙江省', + city: 'A', + type: 'Abc', + }, + dataCfg.fields.rows, + 'province', + ), + ).toEqual(true); + expect( + dataSet.checkAccordQueryWithDimensionValue( + '浙江省[&]杭州市[&]家具[&]桌子', + { + province: '浙江省', + city: '杭州市', + type: '家具', + }, + dataCfg.fields.rows, + 'sub_type', + ), + ).toEqual(true); + expect( + dataSet.checkAccordQueryWithDimensionValue( + '浙江省[&]杭州市[&]家具[&]桌子', + { + province: '浙江省', + city: '不是杭州市', + type: '家具', + }, + dataCfg.fields.rows, + 'sub_type', + ), + ).toEqual(false); + expect( + dataSet.checkAccordQueryWithDimensionValue( + '浙江省[&]杭州市[&]家具[&]桌子', + { + province: '浙江省', + }, + dataCfg.fields.rows, + 'sub_type', + ), + ).toEqual(true); + }); + test('get correct query list when query need to be processed', () => { + expect( + dataSet.getTotalGroupQueries(dataCfg.fields.rows, { + province: '浙江省', + sub_type: '桌子', + }), + ).toEqual([ + { province: '浙江省', sub_type: '桌子', type: '家具', city: '杭州市' }, + { province: '浙江省', sub_type: '桌子', type: '家具', city: '绍兴市' }, + { province: '浙江省', sub_type: '桌子', type: '家具', city: '宁波市' }, + { province: '浙江省', sub_type: '桌子', type: '家具', city: '舟山市' }, + ]); + }); + + test('get correct MultiData when query need to be processed', () => { + expect( + dataSet.getMultiData({ + province: '浙江省', + sub_type: '桌子', + }), + ).toMatchSnapshot(); + expect( + dataSet.getMultiData({ + province: '浙江省', + sub_type: '杭州市', + }), + ).toMatchSnapshot(); + expect( + dataSet.getMultiData({ + sub_type: '桌子', + }), + ).toMatchSnapshot(); + }); + }); }); diff --git a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts index a17d7819ad..777ad50409 100644 --- a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts +++ b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts @@ -280,6 +280,7 @@ describe('Pivot Mode Facet Test', () => { }); }); + describe('get layer when summary dimension grouping', () => {}); describe('should get none layer when dataCfg.fields is empty', () => { const fields: Fields = { rows: [], diff --git a/packages/s2-core/__tests__/unit/utils/export/export-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts index 8845f7511e..10e7c3df97 100644 --- a/packages/s2-core/__tests__/unit/utils/export/export-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts @@ -221,6 +221,8 @@ describe('PivotSheet Export Test', () => { subTotalsDimensions: ['province'], }, col: { + totalsDimensionsGroup: ['city', 'type'], + subTotalsDimensionsGroup: ['sub_type'], showGrandTotals: true, showSubTotals: true, subTotalsDimensions: ['type'], @@ -233,7 +235,7 @@ describe('PivotSheet Export Test', () => { const rows = data.split('\n'); expect(rows).toHaveLength(17); rows.forEach((e) => { - expect(e.split('\t')).toHaveLength(53); + expect(e.split('\t')).toHaveLength(60); }); }); @@ -255,6 +257,8 @@ describe('PivotSheet Export Test', () => { subTotalsDimensions: ['province'], }, col: { + totalsDimensionsGroup: ['city', 'sub_type', 'province'], + subTotalsDimensionsGroup: ['sub_type'], showGrandTotals: true, showSubTotals: true, subTotalsDimensions: ['type'], @@ -267,7 +271,7 @@ describe('PivotSheet Export Test', () => { const rows = data.split('\n'); expect(rows).toHaveLength(16); rows.forEach((e) => { - expect(e.split('\t')).toHaveLength(54); + expect(e.split('\t')).toHaveLength(63); }); }); 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 11cb774190..d75bf31047 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -343,7 +343,7 @@ export class PivotDataSet extends BaseDataSet { ); return uniq( getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues]), - ); + ).filter((v) => v !== 'undefined'); } public getDimensionValues(field: string, query?: DataType): string[] { @@ -513,7 +513,7 @@ export class PivotDataSet extends BaseDataSet { * [undefined , '杭州市' , undefined , 'number'] => true * ['浙江省' , '杭州市' , undefined , 'number'] => true */ - private checkExistDimensionGroup(query: DataType): boolean { + checkExistDimensionGroup(query: DataType): boolean { const { rows, columns } = this.fields; const check = (dimensions: string[]) => { let existDimensionValue = false; @@ -536,10 +536,11 @@ export class PivotDataSet extends BaseDataSet { * 检查 DimensionValue 是否符合 query 条件 * dimensions = ['province','city'] * query = [province: '杭州市', type: '文具'] + * field = 'sub_type' * 浙江省[&]杭州市[&]家具[&]桌子 => true * 四川省[&]成都市[&]文具[&]笔 => false */ - private checkAccordQueryWithDimensionValue( + checkAccordQueryWithDimensionValue( dimensionValues: string, query, dimensions: string[], @@ -569,7 +570,7 @@ export class PivotDataSet extends BaseDataSet { * {'百事公司','可乐','undefined','price'}, * ] */ - private getTotalGroupQueries(dimensions: string[], query) { + getTotalGroupQueries(dimensions: string[], query) { let queryArray = [query]; let existDimensionGroupKey = null; for (let i = dimensions.length; i > 0; i--) { @@ -596,7 +597,10 @@ export class PivotDataSet extends BaseDataSet { ) ) { const arrTypeValue = dimValue.split(ID_SEPARATOR); - resKeys.push(arrTypeValue[arrayLength - 2]); + const currentKey = arrTypeValue[arrayLength - 2]; + if (currentKey !== 'undefined') { + resKeys.push(currentKey); + } } } const queryList = uniq(resKeys).map((v) => { From 209e5f5ea618e88c224a3e279904355d25975365 Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 1 Sep 2023 15:14:36 +0800 Subject: [PATCH 14/39] =?UTF-8?q?docs:=20=E6=8C=89=E7=BB=B4=E5=BA=A6?= =?UTF-8?q?=E5=88=86=E7=BB=84=E6=B1=87=E6=80=BB=E8=83=BD=E5=8A=9B=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 41 ++++++------ .../s2-core/src/data-set/pivot-data-set.ts | 10 ++- packages/s2-core/src/facet/pivot-facet.ts | 1 + s2-site/docs/api/basic-class/node.en.md | 3 +- s2-site/docs/api/basic-class/node.zh.md | 63 ++++++++++--------- s2-site/docs/common/totals.en.md | 2 + s2-site/docs/common/totals.zh.md | 2 + s2-site/docs/manual/basic/totals.en.md | 30 +++++---- s2-site/docs/manual/basic/totals.zh.md | 42 +++++++++---- .../analysis/totals/demo/dimension-group.ts | 63 +++++++++++++++++++ .../examples/analysis/totals/demo/meta.json | 8 +++ 11 files changed, 187 insertions(+), 78 deletions(-) create mode 100644 s2-site/examples/analysis/totals/demo/dimension-group.ts diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index f7f3f6f1d3..e111a0cf4e 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -197,8 +197,8 @@ describe('Pivot Table Core Data Process', () => { data: myData, meta, fields: { - rows: ['province', 'city', 'type', 'sub_type'], - columns: [], + rows: ['province', 'city'], + columns: ['type', 'sub_type'], values: ['number'], // valueInCols: false, // customValueOrder: 2, @@ -206,7 +206,7 @@ describe('Pivot Table Core Data Process', () => { totalData: [], }), assembleOptions({ - // hierarchyType: 'tree', + hierarchyType: 'tree', style: { colCfg: { hideMeasureColumn: true, @@ -214,11 +214,25 @@ describe('Pivot Table Core Data Process', () => { }, debug: false, width: 1024, - height: 600, + height: 2600, totals: { row: { - totalsDimensionsGroup: ['city', 'type'], - subTotalsDimensionsGroup: ['sub_type'], + totalsDimensionsGroup: ['type'], + subTotalsDimensionsGroup: ['type', 'sub_type'], + calcTotals: { + aggregation: Aggregation.SUM, + }, + calcSubTotals: { + aggregation: Aggregation.SUM, + }, + showGrandTotals: true, + showSubTotals: true, + reverseLayout: true, + reverseSubLayout: true, + subTotalsDimensions: ['province'], + }, + col: { + totalsDimensionsGroup: ['sub_type'], calcTotals: { aggregation: Aggregation.SUM, }, @@ -231,21 +245,6 @@ describe('Pivot Table Core Data Process', () => { reverseSubLayout: true, subTotalsDimensions: ['province'], }, - // col: { - // subTotalsDimensionsGroup: ['city'], - // totalsDimensionsGroup: ['sub_type'], - // calcTotals: { - // aggregation: Aggregation.SUM, - // }, - // calcSubTotals: { - // aggregation: Aggregation.SUM, - // }, - // showGrandTotals: true, - // showSubTotals: true, - // reverseLayout: true, - // reverseSubLayout: true, - // subTotalsDimensions: ['province'], - // }, }, }), ); 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 d75bf31047..f52e4465d1 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -59,6 +59,7 @@ import { import { calcActionByType } from '../utils/number-calculate'; import { handleSortAction } from '../utils/sort-action'; import type { CellMeta } from '../common'; +import { JUZELOG } from '../../UTIL'; import { BaseDataSet } from './base-data-set'; import type { CellDataParams, @@ -396,7 +397,13 @@ export class PivotDataSet extends BaseDataSet { } getTotalValue(query: DataType, totalStatus?: TotalStatus) { - const status = totalStatus || this.getTotalStatus(query); + let effectiveStatus = false; + forEach(totalStatus, (bol) => { + if (bol) { + effectiveStatus = true; + } + }); + const status = effectiveStatus ? totalStatus : this.getTotalStatus(query); const { aggregation, calcFunc } = getAggregationAndCalcFuncByQuery( status, @@ -413,6 +420,7 @@ export class PivotDataSet extends BaseDataSet { } else if (calcAction) { totalValue = calcAction(data, VALUE_FIELD); } + return { ...query, [VALUE_FIELD]: totalValue, diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index f549e4f7dd..7fc4c7fa8a 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -28,6 +28,7 @@ import { getDataCellId, handleDataItem } from '../utils/cell/data-cell'; import { getActionIconConfig } from '../utils/cell/header-cell'; import { getIndexRangeWithOffsets } from '../utils/facet'; import { getCellWidth, safeJsonParse } from '../utils/text'; +import { JUZELOG } from '../../UTIL'; import { BaseFacet } from './base-facet'; import { buildHeaderHierarchy } from './layout/build-header-hierarchy'; import type { Hierarchy } from './layout/hierarchy'; diff --git a/s2-site/docs/api/basic-class/node.en.md b/s2-site/docs/api/basic-class/node.en.md index 374df5e90a..701f3ed5ea 100644 --- a/s2-site/docs/api/basic-class/node.en.md +++ b/s2-site/docs/api/basic-class/node.en.md @@ -5,7 +5,7 @@ order: 5 Function description: layout node. [details](https://github.com/antvis/S2/blob/master/packages/s2-core/src/facet/layout/node.ts) | parameter | illustrate | type | -| ----------------- | -------------------------------------- | --------------------------------------------------- | +|-------------------|----------------------------------------| --------------------------------------------------- | | id | node id | `string` | | key | node key | `string` | | value | node value | `string` | @@ -17,6 +17,7 @@ Function description: layout node. [details](https://github.com/antvis/S2/blob/m | isTotals | Is it summary | `boolean` | | isSubTotals | Is it a subtotal | `boolean` | | isGrandTotals | Is it total | `boolean` | +| isTotalRoot | Is it total root | `boolean` | | isCollapsed | Whether to expand | `boolean` | | hierarchy | hierarchical structure | [Hierarchy](#) | | isPivotMode | Is it a pivot table | `boolean` | diff --git a/s2-site/docs/api/basic-class/node.zh.md b/s2-site/docs/api/basic-class/node.zh.md index 31b90c3520..e1bc3044c8 100644 --- a/s2-site/docs/api/basic-class/node.zh.md +++ b/s2-site/docs/api/basic-class/node.zh.md @@ -9,34 +9,35 @@ order: 5 node.isTotals // false ``` -| 参数 | 说明 | 类型 | -| --- | --- | --- | -| id | 节点 id | `string` | -| key | 节点 key | `string` | -| value | 节点值 | `string` | -| label | 节点标题 | `string` | -| level | 节点等级 | `number` | -| rowIndex | 行头索引 | `number` | -| colIndex | 列头索引 | `number` | -| parent | 父节点 | [Node](/docs/api/basic-class/node) | -| isTotals | 是否是汇总 | `boolean` | -| isSubTotals | 是否是小计 | `boolean` | -| isGrandTotals | 是否是总计 | `boolean` | -| isCollapsed | 是否展开 | `boolean` | -| hierarchy | 层级结构 | [Hierarchy](#) | -| isPivotMode | 是否是透视表 | `boolean` | -| seriesNumberWidth | 序号宽度 | `number` | -| field | dataCfg 对应的 field | `string` | -| spreadsheet | 表格实例 | [SpreadSheet](/docs/api/basic-class/spreadsheet) | -| query | 当前节点对应的数据 | `Record` | -| belongsCell | 对应的单元格 | [S2CellType](/docs/api/basic-class/base-cell) | -| isTotalMeasure | 是否是数值小计 | `boolean` | -| inCollapseNode | 是否展开的节点 | `boolean` | -| isLeaf | 是否是叶子节点 | `boolean` | -| x | x 轴坐标 | `number` | -| y | y 轴坐标 | `number` | -| width | 宽度 | `number` | -| height | 高度 | `number` | -| padding | 间距 | `number` | -| hiddenChildNodeInfo | 隐藏的子节点信息 | [hiddenColumnsInfo](/api/basic-class/store#hiddencolumnsinfo) | -| children | 子节点 | [Node[]](/docs/api/basic-class/node) | +| 参数 | 说明 | 类型 | +|---------------------|-------------------| --- | +| id | 节点 id | `string` | +| key | 节点 key | `string` | +| value | 节点值 | `string` | +| label | 节点标题 | `string` | +| level | 节点等级 | `number` | +| rowIndex | 行头索引 | `number` | +| colIndex | 列头索引 | `number` | +| parent | 父节点 | [Node](/docs/api/basic-class/node) | +| isTotals | 是否是汇总 | `boolean` | +| isSubTotals | 是否是小计 | `boolean` | +| isGrandTotals | 是否是总计 | `boolean` | +| isCollapsed | 是否展开 | `boolean` | +| isTotalRoot | 是否是汇总结点的根节点 | `boolean` | +| hierarchy | 层级结构 | [Hierarchy](#) | +| isPivotMode | 是否是透视表 | `boolean` | +| seriesNumberWidth | 序号宽度 | `number` | +| field | dataCfg 对应的 field | `string` | +| spreadsheet | 表格实例 | [SpreadSheet](/docs/api/basic-class/spreadsheet) | +| query | 当前节点对应的数据 | `Record` | +| belongsCell | 对应的单元格 | [S2CellType](/docs/api/basic-class/base-cell) | +| isTotalMeasure | 是否是数值小计 | `boolean` | +| inCollapseNode | 是否展开的节点 | `boolean` | +| isLeaf | 是否是叶子节点 | `boolean` | +| x | x 轴坐标 | `number` | +| y | y 轴坐标 | `number` | +| width | 宽度 | `number` | +| height | 高度 | `number` | +| padding | 间距 | `number` | +| hiddenChildNodeInfo | 隐藏的子节点信息 | [hiddenColumnsInfo](/api/basic-class/store#hiddencolumnsinfo) | +| children | 子节点 | [Node[]](/docs/api/basic-class/node) | diff --git a/s2-site/docs/common/totals.en.md b/s2-site/docs/common/totals.en.md index e04c4f7bc0..56f167b9cf 100644 --- a/s2-site/docs/common/totals.en.md +++ b/s2-site/docs/common/totals.en.md @@ -27,6 +27,8 @@ object is **required** , *default: null* Function description: subtotal total co | subLabel | subtotal alias | `string` | | | | calcTotals | Custom Calculated Totals | [CalcTotals](#calctotals) | | | | calcSubTotals | Custom Calculated Subtotals | [CalcTotals](#calctotals) | | | +| totalsDimensionsGroup | grouping dimension of the total |`string[]` | | | +| subTotalsDimensionsGroup | grouping dimension of the subtotal | `string[]` | | | ## CalcTotals diff --git a/s2-site/docs/common/totals.zh.md b/s2-site/docs/common/totals.zh.md index 6c27917856..86ada706c4 100644 --- a/s2-site/docs/common/totals.zh.md +++ b/s2-site/docs/common/totals.zh.md @@ -27,6 +27,8 @@ object **必选**,_default:null_ 功能描述: 小计总计配置 | subLabel | 小计别名 | `string` | | | | calcTotals | 自定义计算总计 | [CalcTotals](#calctotals) | | | | calcSubTotals | 自定义计算小计 | [CalcTotals](#calctotals) | | | +| totalsDimensionsGroup | 总计的分组维度 |`string[]` | | | +| subTotalsDimensionsGroup | 小计的分组维度 | `string[]` | | | ## CalcTotals diff --git a/s2-site/docs/manual/basic/totals.en.md b/s2-site/docs/manual/basic/totals.en.md index 37848725ab..da12aa68d8 100644 --- a/s2-site/docs/manual/basic/totals.en.md +++ b/s2-site/docs/manual/basic/totals.en.md @@ -12,19 +12,21 @@ order: 5 object is **required** , *default: null* Function description: Subtotal calculation configuration -| parameter | illustrate | type | Defaults | required | | -| ------------------- |---------------------------| ------------ | --------------------- | -------- | - | -| showGrandTotals | Whether to display the total | `boolean` | false | ✓ | | -| showSubTotals | Whether to display subtotals. When configured as an object, always controls whether to always display -subtotals when there are less than 2 subdimensions, and does not display by default. | `boolean \| { always: boolean }` -| false | ✓ | | -| subTotalsDimensions | Summary Dimensions for Subtotals | `string[]` | [] | ✓ | | -| reverseLayout | total layout position, default bottom or right | `boolean` | false | ✓ | | -| reverseSubLayout | Subtotal layout position, default bottom or right | `boolean` | false | ✓ | | -| label | total alias | `string` | | | | -| subLabel | subtotal alias | `string` | | | | -| calcTotals | calculate the total | `CalcTotals` | | | | -| calcSubTotals | calculate subtotal | `CalcTotals` | | | | +| parameter | illustrate | type | Defaults | required | | +|--------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|--------------|----------|----------|-----| +| showGrandTotals | Whether to display the total | `boolean` | false | ✓ | | +| showSubTotals | Whether to display subtotals. When configured as an object, always controls whether to always display | | | | | +| subtotals when there are less than 2 subdimensions, and does not display by default. | `boolean \| { always: boolean }` | | | | | +| false | ✓ | | | | | +| subTotalsDimensions | Summary Dimensions for Subtotals | `string[]` | [] | ✓ | | +| reverseLayout | total layout position, default bottom or right | `boolean` | false | ✓ | | +| reverseSubLayout | Subtotal layout position, default bottom or right | `boolean` | false | ✓ | | +| label | total alias | `string` | | | | +| subLabel | subtotal alias | `string` | | | | +| calcTotals | calculate the total | `CalcTotals` | | | | +| calcSubTotals | calculate subtotal | `CalcTotals` | | | | +| totalsDimensionsGroup | grouping dimension of the total |`string[]` | | | +| subTotalsDimensionsGroup | grouping dimension of the subtotal | `string[]` | | | ```typescript const s2Options = { @@ -35,6 +37,8 @@ subtotals when there are less than 2 subdimensions, and does not display by defa reverseLayout: true, reverseSubLayout: true, subTotalsDimensions: [ 'province' ], + totalsDimensionsGroup: ['city'], + subTotalsDimensionsGroup: ['type', 'sub_type'], }, col: { showGrandTotals: true, diff --git a/s2-site/docs/manual/basic/totals.zh.md b/s2-site/docs/manual/basic/totals.zh.md index 0821574acb..3e6f3055d5 100644 --- a/s2-site/docs/manual/basic/totals.zh.md +++ b/s2-site/docs/manual/basic/totals.zh.md @@ -47,6 +47,22 @@ order: 5 row +### 分组汇总 + +按维度进行 小计/总计 的汇总计算,用于进行某一维度的数据对比分析等。 + +#### 行总计小计 + +行总计按 “类别” 分组,行小计按 “类别”,“子类别” 分组: + +图片1 + +#### 列总计小计 + +列总计按 “城市” 分组: + +图片2 + ## 使用 ### 1. 显示配置 @@ -66,17 +82,19 @@ object **必选**,_default:null_ 功能描述: 小计总计配置 object **必选**,_default:null_ 功能描述: 小计总计算配置 -| 参数 | 说明 | 类型 | 默认值 | 必选 | -| ------------------- | ------------------------ | ------------ | ------ | ---- | -| showGrandTotals | 是否显示总计 | `boolean` | false | ✓ | -| showSubTotals | 是否显示小计。当配置为对象时,always 控制是否在子维度不足 2 个时始终展示小计,默认不展示。 | `boolean | { always: boolean }` | false | ✓ | -| subTotalsDimensions | 小计的汇总维度 | `string[]` | [] | ✓ | -| reverseLayout | 总计布局位置,默认下或右 | `boolean` | false | ✓ | -| reverseSubLayout | 小计布局位置,默认下或右 | `boolean` | false | ✓ | -| label | 总计别名 | `string` | | | -| subLabel | 小计别名 | `string` | | | -| calcTotals | 计算总计 | `CalcTotals` | | | -| calcSubTotals | 计算小计 | `CalcTotals` | | | +| 参数 | 说明 | 类型 | 默认值 | 必选 | +|----------------------------------------|----------------------------------------------------|--------------|--------------------| ---- | +| showGrandTotals | 是否显示总计 | `boolean` | false | ✓ | +| showSubTotals | 是否显示小计。当配置为对象时,always 控制是否在子维度不足 2 个时始终展示小计,默认不展示。 | `boolean | { always: boolean }` | false | ✓ | +| subTotalsDimensions | 小计的汇总维度 | `string[]` | [] | ✓ | +| reverseLayout | 总计布局位置,默认下或右 | `boolean` | false | ✓ | +| reverseSubLayout | 小计布局位置,默认下或右 | `boolean` | false | ✓ | +| label | 总计别名 | `string` | | | +| subLabel | 小计别名 | `string` | | | +| calcTotals | 计算总计 | `CalcTotals` | | | +| calcSubTotals | 计算小计 | `CalcTotals` | | | +| totalsDimensionsGroup | 总计的分组维度 |`string[]` | | | +| subTotalsDimensionsGroup | 小计的分组维度 | `string[]` | | | ```ts const s2Options = { @@ -87,6 +105,8 @@ const s2Options = { reverseLayout: true, reverseSubLayout: true, subTotalsDimensions: ['province'], + totalsDimensionsGroup: ['city'], + subTotalsDimensionsGroup: ['type', 'sub_type'], }, col: { showGrandTotals: true, diff --git a/s2-site/examples/analysis/totals/demo/dimension-group.ts b/s2-site/examples/analysis/totals/demo/dimension-group.ts new file mode 100644 index 0000000000..b8db8ac929 --- /dev/null +++ b/s2-site/examples/analysis/totals/demo/dimension-group.ts @@ -0,0 +1,63 @@ +import { PivotSheet } from '@antv/s2'; + +fetch('https://gw.alipayobjects.com/os/bmw-prod/6eede6eb-8021-4da8-bb12-67891a5705b7.json') + .then((res) => res.json()) + .then((data) => { + const container = document.getElementById('container'); + const s2DataConfig = { + fields: { + rows: ['province', 'city', 'type'], + columns: [], + values: ['price' ,'cost'], + }, + meta: [ + { + field: 'province', + name: '省份', + }, + { + field: 'city', + name: '城市', + }, + { + field: 'type', + name: '商品类别', + }, + { + field: 'price', + name: '价格', + }, + { + field: 'cost', + name: '成本', + }, + ], + data, + }; + + const s2Options = { + width: 600, + height: 480, + // 配置小计总计显示,按维度分组 + totals: { + row: { + showGrandTotals: true, + showSubTotals: true, + reverseLayout: true, + reverseSubLayout: true, + subTotalsDimensions: ['province'], + calcTotals: { + aggregation: 'SUM', + }, + calcSubTotals: { + aggregation: 'SUM', + }, + totalsDimensionsGroup: ['city'], + subTotalsDimensionsGroup: ['type'], + }, + }, + }; + const s2 = new PivotSheet(container, s2DataConfig, s2Options); + + s2.render(); + }); diff --git a/s2-site/examples/analysis/totals/demo/meta.json b/s2-site/examples/analysis/totals/demo/meta.json index d751e58992..14921a13b6 100644 --- a/s2-site/examples/analysis/totals/demo/meta.json +++ b/s2-site/examples/analysis/totals/demo/meta.json @@ -20,6 +20,14 @@ }, "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/3SuoQrkTsR/5657d02f-8e7f-4fbc-8159-7a0e8f772462.png" }, + { + "filename": "dimension-group.ts", + "title": { + "zh": "分组汇总", + "en": "Grouping Value Totals" + }, + "screenshot": "" + }, { "filename": "tree.ts", "title": { From a53cd1c3afa46c132fdeca7de90845c1fd385d04 Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 1 Sep 2023 16:14:52 +0800 Subject: [PATCH 15/39] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=EF=BC=8C?= =?UTF-8?q?=E5=A4=9A=E5=BA=A6=E9=87=8F=E6=8C=87=E6=A0=87=E4=B8=8D=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E9=9A=90=E8=97=8F=E6=8C=87=E6=A0=87=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/spreadsheet/corner-spec.ts | 8 ++++ .../unit/data-process/new-total-spec.tsx | 41 ++++++++++--------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/s2-core/__tests__/spreadsheet/corner-spec.ts b/packages/s2-core/__tests__/spreadsheet/corner-spec.ts index bdc06461fd..b2d7396bb8 100644 --- a/packages/s2-core/__tests__/spreadsheet/corner-spec.ts +++ b/packages/s2-core/__tests__/spreadsheet/corner-spec.ts @@ -49,6 +49,7 @@ describe('PivotSheet Corner Tests', () => { fields: { ...simpleDataConfig.fields, columns: [], + values: ['price'], }, }); s2.setOptions({ @@ -88,6 +89,13 @@ describe('PivotSheet Corner Tests', () => { }, }, }); + s2.setDataCfg({ + ...simpleDataConfig, + fields: { + ...simpleDataConfig.fields, + values: ['price'], + }, + }); s2.render(); const cornerNodes = s2.facet.getCornerNodes(); diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index e111a0cf4e..f7f3f6f1d3 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -197,8 +197,8 @@ describe('Pivot Table Core Data Process', () => { data: myData, meta, fields: { - rows: ['province', 'city'], - columns: ['type', 'sub_type'], + rows: ['province', 'city', 'type', 'sub_type'], + columns: [], values: ['number'], // valueInCols: false, // customValueOrder: 2, @@ -206,7 +206,7 @@ describe('Pivot Table Core Data Process', () => { totalData: [], }), assembleOptions({ - hierarchyType: 'tree', + // hierarchyType: 'tree', style: { colCfg: { hideMeasureColumn: true, @@ -214,25 +214,11 @@ describe('Pivot Table Core Data Process', () => { }, debug: false, width: 1024, - height: 2600, + height: 600, totals: { row: { - totalsDimensionsGroup: ['type'], - subTotalsDimensionsGroup: ['type', 'sub_type'], - calcTotals: { - aggregation: Aggregation.SUM, - }, - calcSubTotals: { - aggregation: Aggregation.SUM, - }, - showGrandTotals: true, - showSubTotals: true, - reverseLayout: true, - reverseSubLayout: true, - subTotalsDimensions: ['province'], - }, - col: { - totalsDimensionsGroup: ['sub_type'], + totalsDimensionsGroup: ['city', 'type'], + subTotalsDimensionsGroup: ['sub_type'], calcTotals: { aggregation: Aggregation.SUM, }, @@ -245,6 +231,21 @@ describe('Pivot Table Core Data Process', () => { reverseSubLayout: true, subTotalsDimensions: ['province'], }, + // col: { + // subTotalsDimensionsGroup: ['city'], + // totalsDimensionsGroup: ['sub_type'], + // calcTotals: { + // aggregation: Aggregation.SUM, + // }, + // calcSubTotals: { + // aggregation: Aggregation.SUM, + // }, + // showGrandTotals: true, + // showSubTotals: true, + // reverseLayout: true, + // reverseSubLayout: true, + // subTotalsDimensions: ['province'], + // }, }, }), ); From 4bdab0f6a13cca3b1bc1b403d2527131b654cef1 Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 1 Sep 2023 17:12:48 +0800 Subject: [PATCH 16/39] =?UTF-8?q?docs:=20=E5=9B=BE=E7=89=87=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/unit/data-process/new-total-spec.tsx | 9 ++------- packages/s2-core/src/sheet-type/spread-sheet.ts | 1 - packages/s2-core/src/utils/dataset/pivot-data-set.ts | 1 + s2-site/docs/manual/basic/totals.zh.md | 10 ++++------ 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx index f7f3f6f1d3..cc6ba1e1e6 100644 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx @@ -199,7 +199,7 @@ describe('Pivot Table Core Data Process', () => { fields: { rows: ['province', 'city', 'type', 'sub_type'], columns: [], - values: ['number'], + values: ['number', 'cost'], // valueInCols: false, // customValueOrder: 2, }, @@ -207,14 +207,9 @@ describe('Pivot Table Core Data Process', () => { }), assembleOptions({ // hierarchyType: 'tree', - style: { - colCfg: { - hideMeasureColumn: true, - }, - }, debug: false, width: 1024, - height: 600, + height: 2600, totals: { row: { totalsDimensionsGroup: ['city', 'type'], diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index 78c6b7e508..d523d4398a 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -413,7 +413,6 @@ export abstract class SpreadSheet extends EE { this.clearDrillDownData('', true); this.dataSet.setDataCfg(this.dataCfg); } - this.buildFacet(); if (reBuildHiddenColumnsDetail) { this.initHiddenColumnsDetail(); 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 e6b95a70aa..3d360dd983 100644 --- a/packages/s2-core/src/utils/dataset/pivot-data-set.ts +++ b/packages/s2-core/src/utils/dataset/pivot-data-set.ts @@ -188,6 +188,7 @@ export function getDataPath(params: DataPathParams) { } return path; }; + const rowPath = getPath(rowDimensionValues, true, rowPivotMeta, colPivotMeta); const colPath = getPath( colDimensionValues, diff --git a/s2-site/docs/manual/basic/totals.zh.md b/s2-site/docs/manual/basic/totals.zh.md index 3e6f3055d5..8f22dadf90 100644 --- a/s2-site/docs/manual/basic/totals.zh.md +++ b/s2-site/docs/manual/basic/totals.zh.md @@ -51,17 +51,15 @@ order: 5 按维度进行 小计/总计 的汇总计算,用于进行某一维度的数据对比分析等。 -#### 行总计小计 +#### 行总计小计分组 行总计按 “类别” 分组,行小计按 “类别”,“子类别” 分组: -图片1 +row -#### 列总计小计 +#### 列总计小计分组 -列总计按 “城市” 分组: - -图片2 +row ## 使用 From fd0151ab614ffe41914233e826f93085437b8692 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 11:41:49 +0800 Subject: [PATCH 17/39] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=20snap=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pivot-data-set-total-spec.ts.snap | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap diff --git a/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap new file mode 100644 index 0000000000..5892350ec7 --- /dev/null +++ b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap @@ -0,0 +1,241 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 1`] = ` +Array [ + Object { + "$$extra$$": "number", + "$$value$$": 7789, + "city": "杭州市", + "number": 7789, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2367, + "city": "绍兴市", + "number": 2367, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 3877, + "city": "宁波市", + "number": 3877, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 4342, + "city": "舟山市", + "number": 4342, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, +] +`; + +exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 2`] = `Array []`; + +exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 3`] = ` +Array [ + Object { + "$$extra$$": "number", + "$$value$$": 7789, + "city": "杭州市", + "number": 7789, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2367, + "city": "绍兴市", + "number": 2367, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 3877, + "city": "宁波市", + "number": 3877, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 4342, + "city": "舟山市", + "number": 4342, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1723, + "city": "成都市", + "number": 1723, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1822, + "city": "绵阳市", + "number": 1822, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1943, + "city": "南充市", + "number": 1943, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2330, + "city": "乐山市", + "number": 2330, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, +] +`; + +exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 1`] = ` +Array [ + Object { + "$$extra$$": "number", + "$$value$$": 7789, + "city": "杭州市", + "number": 7789, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2367, + "city": "绍兴市", + "number": 2367, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 3877, + "city": "宁波市", + "number": 3877, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 4342, + "city": "舟山市", + "number": 4342, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, +] +`; + +exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 2`] = `Array []`; + +exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 3`] = ` +Array [ + Object { + "$$extra$$": "number", + "$$value$$": 7789, + "city": "杭州市", + "number": 7789, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2367, + "city": "绍兴市", + "number": 2367, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 3877, + "city": "宁波市", + "number": 3877, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 4342, + "city": "舟山市", + "number": 4342, + "province": "浙江省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1723, + "city": "成都市", + "number": 1723, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1822, + "city": "绵阳市", + "number": 1822, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 1943, + "city": "南充市", + "number": 1943, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, + Object { + "$$extra$$": "number", + "$$value$$": 2330, + "city": "乐山市", + "number": 2330, + "province": "四川省", + "sub_type": "桌子", + "type": "家具", + }, +] +`; From 288c124a6b14f548d7f739362d5ff23c2d2495fe Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 14:06:23 +0800 Subject: [PATCH 18/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/s2-core/package.json b/packages/s2-core/package.json index f6f924d62d..6337125605 100644 --- a/packages/s2-core/package.json +++ b/packages/s2-core/package.json @@ -1,7 +1,7 @@ { "private": false, "name": "@antv/s2", - "version": "1.49.1", + "version": "1.50.0", "main": "lib/index.js", "unpkg": "dist/index.min.js", "module": "esm/index.js", From f733e64ac71863ca5bfaee3dd09e265b67f5cbef Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 14:25:09 +0800 Subject: [PATCH 19/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/CHANGELOG.md | 8 ++++++++ packages/s2-core/UTIL.ts | 5 ----- packages/s2-core/__tests__/unit/utils/facet-spec.ts | 2 -- packages/s2-core/src/data-set/pivot-data-set.ts | 1 - packages/s2-core/src/facet/pivot-facet.ts | 1 - 5 files changed, 8 insertions(+), 9 deletions(-) delete mode 100644 packages/s2-core/UTIL.ts diff --git a/packages/s2-core/CHANGELOG.md b/packages/s2-core/CHANGELOG.md index 0bcd4b632e..962ea6ba09 100644 --- a/packages/s2-core/CHANGELOG.md +++ b/packages/s2-core/CHANGELOG.md @@ -1,3 +1,11 @@ +# [@antv/s2-v1.50.0](https://github.com/antvis/S2/compare/@antv/s2-v1.49.2...@antv/s2-v1.50.0) (2023-09-04) + + +### Features + +* 增加 小计/总计 按维度汇总功能 ([8076481](https://github.com/antvis/S2/commit/807648180fe64f47e9f70df865890ab480b07603)) + + # [@antv/s2-v1.49.2](https://github.com/antvis/S2/compare/@antv/s2-v1.49.1...@antv/s2-v1.49.2) (2023-08-11) diff --git a/packages/s2-core/UTIL.ts b/packages/s2-core/UTIL.ts deleted file mode 100644 index 6e6d0c5af9..0000000000 --- a/packages/s2-core/UTIL.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { cloneDeep } from 'lodash'; -export const JUZELOG = (a, e?: any) => { - // eslint-disable-next-line no-console - console.log('**************\n', e || '', cloneDeep(a)); -}; diff --git a/packages/s2-core/__tests__/unit/utils/facet-spec.ts b/packages/s2-core/__tests__/unit/utils/facet-spec.ts index 6ca9b3cccc..5c9d1aa44a 100644 --- a/packages/s2-core/__tests__/unit/utils/facet-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/facet-spec.ts @@ -5,8 +5,6 @@ import { } from '@/utils/facet'; describe('Facet util test', () => { - // JUZEMARK 倍数Map - test('should get correct index range for given offsets', () => { const offsets = [0, 30, 60, 90, 120, 150, 160, 170, 190]; expect(getIndexRangeWithOffsets(offsets, 0, 31)).toStrictEqual({ 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 f52e4465d1..e8d10cb2ef 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -59,7 +59,6 @@ import { import { calcActionByType } from '../utils/number-calculate'; import { handleSortAction } from '../utils/sort-action'; import type { CellMeta } from '../common'; -import { JUZELOG } from '../../UTIL'; import { BaseDataSet } from './base-data-set'; import type { CellDataParams, diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index 7fc4c7fa8a..f549e4f7dd 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -28,7 +28,6 @@ import { getDataCellId, handleDataItem } from '../utils/cell/data-cell'; import { getActionIconConfig } from '../utils/cell/header-cell'; import { getIndexRangeWithOffsets } from '../utils/facet'; import { getCellWidth, safeJsonParse } from '../utils/text'; -import { JUZELOG } from '../../UTIL'; import { BaseFacet } from './base-facet'; import { buildHeaderHierarchy } from './layout/build-header-hierarchy'; import type { Hierarchy } from './layout/hierarchy'; From 72321d6c1dc48667edf1f34c136044435ece2c52 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 14:28:31 +0800 Subject: [PATCH 20/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 248 ------------------ 1 file changed, 248 deletions(-) delete mode 100644 packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx deleted file mode 100644 index cc6ba1e1e6..0000000000 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ /dev/null @@ -1,248 +0,0 @@ -/** - * 透视表核心数据流程(保证基本数据正确) - * */ -// eslint-disable-next-line import/no-extraneous-dependencies -import { Aggregation } from '@antv/s2'; -import { assembleDataCfg, assembleOptions } from '../../util'; -import { getContainer } from '../../util/helpers'; -import { PivotSheet } from '@/sheet-type'; - -const myData = [ - { - cost: 99099, - number: 99099, - city: '杭州市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - sub_type: '桌子', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - type: '家具', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 356, - number: 3877, - province: '浙江省', - city: '宁波市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 5734, - number: 5343, - province: '浙江省', - city: '杭州市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 957, - number: 7234, - province: '浙江省', - city: '宁波市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 486, - number: 945, - province: '浙江省', - city: '杭州市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 357, - number: 1145, - province: '浙江省', - city: '宁波市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 513, - number: 1343, - province: '浙江省', - city: '杭州市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 234, - number: 1523, - province: '浙江省', - city: '宁波市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 456, - number: 1822, - province: '四川省', - city: '绵阳市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 2654, - number: 1943, - province: '四川省', - city: '南充市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 578, - number: 2244, - province: '四川省', - city: '绵阳市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 687, - number: 2333, - province: '四川省', - city: '南充市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 345, - number: 245, - province: '四川省', - city: '绵阳市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 756, - number: 2457, - province: '四川省', - city: '南充市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 243, - number: 3077, - province: '四川省', - city: '绵阳市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 123, - number: 3551, - province: '四川省', - city: '南充市', - type: '办公用品', - sub_type: '纸张', - }, -]; -const meta = [ - { - field: 'number', - name: '数量', - description: '数量说明。。', - }, - { - field: 'province', - name: '省份', - description: '省份说明。。', - }, - { - field: 'city', - name: '城市', - description: '城市说明。。', - }, - { - field: 'type', - name: '类别', - description: '类别说明。。', - }, - { - field: 'sub_type', - name: '子类别', - description: '子类别说明。。', - }, - { - field: 'cost', - name: '价格', - description: 'Value2', - }, -]; -describe('Pivot Table Core Data Process', () => { - const s2 = new PivotSheet( - getContainer(), - assembleDataCfg({ - data: myData, - meta, - fields: { - rows: ['province', 'city', 'type', 'sub_type'], - columns: [], - values: ['number', 'cost'], - // valueInCols: false, - // customValueOrder: 2, - }, - totalData: [], - }), - assembleOptions({ - // hierarchyType: 'tree', - debug: false, - width: 1024, - height: 2600, - totals: { - row: { - totalsDimensionsGroup: ['city', 'type'], - subTotalsDimensionsGroup: ['sub_type'], - calcTotals: { - aggregation: Aggregation.SUM, - }, - calcSubTotals: { - aggregation: Aggregation.SUM, - }, - showGrandTotals: true, - showSubTotals: true, - reverseLayout: true, - reverseSubLayout: true, - subTotalsDimensions: ['province'], - }, - // col: { - // subTotalsDimensionsGroup: ['city'], - // totalsDimensionsGroup: ['sub_type'], - // calcTotals: { - // aggregation: Aggregation.SUM, - // }, - // calcSubTotals: { - // aggregation: Aggregation.SUM, - // }, - // showGrandTotals: true, - // showSubTotals: true, - // reverseLayout: true, - // reverseSubLayout: true, - // subTotalsDimensions: ['province'], - // }, - }, - }), - ); - s2.render(); -}); From ce70d0471fe92d91bdd2f422e5d4d46d5e3fbfd1 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 14:38:49 +0800 Subject: [PATCH 21/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/scripts/test-live.mjs | 2 +- packages/s2-react/scripts/test-live.mjs | 2 +- s2-site/examples/analysis/totals/demo/meta.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index 8f919b7092..59c461979b 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,7 +9,7 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/unit/data-process/new-total-spec.tsx'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; spinner.stop(); const selectedPath = await inquirer.prompt([ diff --git a/packages/s2-react/scripts/test-live.mjs b/packages/s2-react/scripts/test-live.mjs index 33f08d1de8..90727b050c 100644 --- a/packages/s2-react/scripts/test-live.mjs +++ b/packages/s2-react/scripts/test-live.mjs @@ -10,7 +10,7 @@ async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/unit/data-process/new-total-spec.tsx'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; spinner.stop(); const selectedPath = await inquirer.prompt([ diff --git a/s2-site/examples/analysis/totals/demo/meta.json b/s2-site/examples/analysis/totals/demo/meta.json index 14921a13b6..544eaf60d7 100644 --- a/s2-site/examples/analysis/totals/demo/meta.json +++ b/s2-site/examples/analysis/totals/demo/meta.json @@ -26,7 +26,7 @@ "zh": "分组汇总", "en": "Grouping Value Totals" }, - "screenshot": "" + "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1SDsRpTA_kQAAAAAAAAAAAAADmJ7AQ/original" }, { "filename": "tree.ts", From 16388888accebd445ba553ee5a9e7b036614e14d Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 15:10:47 +0800 Subject: [PATCH 22/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/scripts/test-live.mjs | 2 +- packages/s2-react/scripts/test-live.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index 59c461979b..692a2a8324 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,7 +9,7 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ diff --git a/packages/s2-react/scripts/test-live.mjs b/packages/s2-react/scripts/test-live.mjs index 90727b050c..6c92d162dc 100644 --- a/packages/s2-react/scripts/test-live.mjs +++ b/packages/s2-react/scripts/test-live.mjs @@ -10,7 +10,7 @@ async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ From 2ce87cd29162ace8d4b49e6c9bd4ba956c47e104 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 15:10:47 +0800 Subject: [PATCH 23/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/scripts/test-live.mjs | 2 +- packages/s2-react/scripts/test-live.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index 59c461979b..692a2a8324 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,7 +9,7 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ diff --git a/packages/s2-react/scripts/test-live.mjs b/packages/s2-react/scripts/test-live.mjs index 90727b050c..6c92d162dc 100644 --- a/packages/s2-react/scripts/test-live.mjs +++ b/packages/s2-react/scripts/test-live.mjs @@ -10,7 +10,7 @@ async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; spinner.stop(); const selectedPath = await inquirer.prompt([ From 72db41a40ceb1759435cd297219e471ac7fbaea6 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 15:17:18 +0800 Subject: [PATCH 24/39] =?UTF-8?q?chore:=20=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/scripts/test-live.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/s2-core/scripts/test-live.mjs b/packages/s2-core/scripts/test-live.mjs index 692a2a8324..1e49382250 100644 --- a/packages/s2-core/scripts/test-live.mjs +++ b/packages/s2-core/scripts/test-live.mjs @@ -9,7 +9,8 @@ inquirer.registerPrompt('autocomplete', autoCompletePrompt); async function main() { const spinner = ora('读取测试文件中...').start(); const paths = glob.sync(`!(node_modules)/**/*-spec.ts?(x)`); - const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.tsx'; + + const defaultPath = '__tests__/spreadsheet/spread-sheet-spec.ts'; spinner.stop(); const selectedPath = await inquirer.prompt([ From 482e1f4bfb767e394c0dcb86835725d780a4e513 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 15:46:43 +0800 Subject: [PATCH 25/39] Merge remote-tracking branch 'origin/Juze_TotalsDimGroup' into Juze_TotalsDimGroup --- packages/s2-core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/s2-core/CHANGELOG.md b/packages/s2-core/CHANGELOG.md index 962ea6ba09..06f2e7ee6c 100644 --- a/packages/s2-core/CHANGELOG.md +++ b/packages/s2-core/CHANGELOG.md @@ -3,7 +3,7 @@ ### Features -* 增加 小计/总计 按维度汇总功能 ([8076481](https://github.com/antvis/S2/commit/807648180fe64f47e9f70df865890ab480b07603)) +* 增加 小计/总计 按维度汇总功能 # [@antv/s2-v1.49.2](https://github.com/antvis/S2/compare/@antv/s2-v1.49.1...@antv/s2-v1.49.2) (2023-08-11) From e2f0ce12b56050e67ad42f190f4e2f3ca0f843d9 Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 4 Sep 2023 15:46:43 +0800 Subject: [PATCH 26/39] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=BF=AB?= =?UTF-8?q?=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/CHANGELOG.md | 15 --- .../pivot-data-set-total-spec.ts.snap | 120 ------------------ 2 files changed, 135 deletions(-) diff --git a/packages/s2-core/CHANGELOG.md b/packages/s2-core/CHANGELOG.md index 962ea6ba09..d8892d200b 100644 --- a/packages/s2-core/CHANGELOG.md +++ b/packages/s2-core/CHANGELOG.md @@ -1,18 +1,3 @@ -# [@antv/s2-v1.50.0](https://github.com/antvis/S2/compare/@antv/s2-v1.49.2...@antv/s2-v1.50.0) (2023-09-04) - - -### Features - -* 增加 小计/总计 按维度汇总功能 ([8076481](https://github.com/antvis/S2/commit/807648180fe64f47e9f70df865890ab480b07603)) - - -# [@antv/s2-v1.49.2](https://github.com/antvis/S2/compare/@antv/s2-v1.49.1...@antv/s2-v1.49.2) (2023-08-11) - - -### Bug Fixes - -* 修复复制整行时错位 ([#2278](https://github.com/antvis/S2/issues/2278)) ([8076481](https://github.com/antvis/S2/commit/807648180fe64f47e9f70df865890ab480b07603)) - # [@antv/s2-v1.49.1](https://github.com/antvis/S2/compare/@antv/s2-v1.49.0...@antv/s2-v1.49.1) (2023-07-24) diff --git a/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap index 5892350ec7..91b43b95ef 100644 --- a/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap +++ b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap @@ -1,125 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 1`] = ` -Array [ - Object { - "$$extra$$": "number", - "$$value$$": 7789, - "city": "杭州市", - "number": 7789, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 2367, - "city": "绍兴市", - "number": 2367, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 3877, - "city": "宁波市", - "number": 3877, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 4342, - "city": "舟山市", - "number": 4342, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, -] -`; - -exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 2`] = `Array []`; - -exports[`Pivot Dataset Total Test test for query data test for total with dimension group get correct MultiData when query need to be processed 3`] = ` -Array [ - Object { - "$$extra$$": "number", - "$$value$$": 7789, - "city": "杭州市", - "number": 7789, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 2367, - "city": "绍兴市", - "number": 2367, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 3877, - "city": "宁波市", - "number": 3877, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 4342, - "city": "舟山市", - "number": 4342, - "province": "浙江省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 1723, - "city": "成都市", - "number": 1723, - "province": "四川省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 1822, - "city": "绵阳市", - "number": 1822, - "province": "四川省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 1943, - "city": "南充市", - "number": 1943, - "province": "四川省", - "sub_type": "桌子", - "type": "家具", - }, - Object { - "$$extra$$": "number", - "$$value$$": 2330, - "city": "乐山市", - "number": 2330, - "province": "四川省", - "sub_type": "桌子", - "type": "家具", - }, -] -`; - exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 1`] = ` Array [ Object { From 5c11b4d9c32ee5d118cd429725d65fb9e266c3c6 Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 6 Sep 2023 17:21:38 +0800 Subject: [PATCH 27/39] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E6=B5=8B=E8=AF=95=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/data-process/new-total-spec.tsx | 251 ------------------ 1 file changed, 251 deletions(-) delete mode 100644 packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx diff --git a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx b/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx deleted file mode 100644 index cff5555dbe..0000000000 --- a/packages/s2-core/__tests__/unit/data-process/new-total-spec.tsx +++ /dev/null @@ -1,251 +0,0 @@ -/** - * 透视表核心数据流程(保证基本数据正确) - * */ -// eslint-disable-next-line import/no-extraneous-dependencies -import { Aggregation } from '@antv/s2'; -import { assembleDataCfg, assembleOptions } from '../../util'; -import { getContainer } from '../../util/helpers'; -import { PivotSheet } from '@/sheet-type'; - -const myData = [ - { - cost: 99099, - number: 99099, - city: '杭州市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - sub_type: '桌子', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - type: '家具', - }, - { - cost: 99099, - number: 99099, - province: '浙江省', - city: '杭州市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 356, - number: 3877, - province: '浙江省', - city: '宁波市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 5734, - number: 5343, - province: '浙江省', - city: '杭州市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 957, - number: 7234, - province: '浙江省', - city: '宁波市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 486, - number: 945, - province: '浙江省', - city: '杭州市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 357, - number: 1145, - province: '浙江省', - city: '宁波市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 513, - number: 1343, - province: '浙江省', - city: '杭州市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 234, - number: 1523, - province: '浙江省', - city: '宁波市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 456, - number: 1822, - province: '四川省', - city: '绵阳市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 2654, - number: 1943, - province: '四川省', - city: '南充市', - type: '家具', - sub_type: '桌子', - }, - { - cost: 578, - number: 2244, - province: '四川省', - city: '绵阳市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 687, - number: 2333, - province: '四川省', - city: '南充市', - type: '家具', - sub_type: '沙发', - }, - { - cost: 345, - number: 245, - province: '四川省', - city: '绵阳市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 756, - number: 2457, - province: '四川省', - city: '南充市', - type: '办公用品', - sub_type: '笔', - }, - { - cost: 243, - number: 3077, - province: '四川省', - city: '绵阳市', - type: '办公用品', - sub_type: '纸张', - }, - { - cost: 123, - number: 3551, - province: '四川省', - city: '南充市', - type: '办公用品', - sub_type: '纸张', - }, -]; -const meta = [ - { - field: 'number', - name: '数量', - description: '数量说明。。', - }, - { - field: 'province', - name: '省份', - description: '省份说明。。', - }, - { - field: 'city', - name: '城市', - description: '城市说明。。', - }, - { - field: 'type', - name: '类别', - description: '类别说明。。', - }, - { - field: 'sub_type', - name: '子类别', - description: '子类别说明。。', - }, - { - field: 'cost', - name: '价格', - description: 'Value2', - }, -]; -describe('Pivot Table Core Data Process', () => { - const s2 = new PivotSheet( - getContainer(), - assembleDataCfg({ - data: myData, - meta, - fields: { - rows: ['province', 'city', 'type', 'sub_type'], - columns: [], - values: ['number', 'cost'], - // valueInCols: false, - }, - totalData: [], - }), - assembleOptions({ - // hierarchyType: 'tree', - debug: false, - width: 1024, - height: 2600, - interaction: { - brushSelection: { row: true }, - enableCopy: true, - }, - totals: { - row: { - totalsDimensionsGroup: ['type'], - subTotalsDimensionsGroup: ['sub_type'], - calcTotals: { - aggregation: Aggregation.SUM, - }, - calcSubTotals: { - aggregation: Aggregation.SUM, - }, - showGrandTotals: true, - showSubTotals: true, - reverseLayout: true, - reverseSubLayout: true, - subTotalsDimensions: ['province'], - }, - // col: { - // subTotalsDimensionsGroup: ['city'], - // totalsDimensionsGroup: ['sub_type'], - // calcTotals: { - // aggregation: Aggregation.SUM, - // }, - // calcSubTotals: { - // aggregation: Aggregation.SUM, - // }, - // showGrandTotals: true, - // showSubTotals: true, - // reverseLayout: true, - // reverseSubLayout: true, - // subTotalsDimensions: ['province'], - // }, - }, - }), - ); - s2.render(); -}); From 8550e315ddc44097b260a1fa8dbfc80bfb7718d6 Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 6 Sep 2023 18:36:36 +0800 Subject: [PATCH 28/39] =?UTF-8?q?fix:=20=E6=B1=87=E6=80=BB=E6=8C=87?= =?UTF-8?q?=E6=A0=87=E8=8A=82=E7=82=B9=E4=B9=9F=E6=98=AF=E6=B1=87=E6=80=BB?= =?UTF-8?q?=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/utils/layout/generate-header-nodes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/s2-core/src/utils/layout/generate-header-nodes.ts b/packages/s2-core/src/utils/layout/generate-header-nodes.ts index c72e7b62fe..402eb59120 100644 --- a/packages/s2-core/src/utils/layout/generate-header-nodes.ts +++ b/packages/s2-core/src/utils/layout/generate-header-nodes.ts @@ -91,7 +91,7 @@ export const generateHeaderNodes = (params: HeaderNodesParams) => { level, field: adjustedField, parent: parentNode, - isTotals, + isTotals: isTotals || isTotalMeasure, isGrandTotals, isSubTotals, isTotalMeasure, From 3bf638d1cab88cec5dc0c4709b249649d122c25e Mon Sep 17 00:00:00 2001 From: JuZe Date: Wed, 6 Sep 2023 20:36:06 +0800 Subject: [PATCH 29/39] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../s2-core/src/data-set/README-adjustTotalNodesCoordinate.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/s2-core/src/data-set/README-adjustTotalNodesCoordinate.md diff --git a/packages/s2-core/src/data-set/README-adjustTotalNodesCoordinate.md b/packages/s2-core/src/data-set/README-adjustTotalNodesCoordinate.md deleted file mode 100644 index 70b786d12e..0000000000 --- a/packages/s2-core/src/data-set/README-adjustTotalNodesCoordinate.md +++ /dev/null @@ -1 +0,0 @@ -// TODO From 8c36de68e2be2a11d71dc22c74466743ff4dc502 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 7 Sep 2023 11:20:52 +0800 Subject: [PATCH 30/39] =?UTF-8?q?fix:=20isTotalRoot=20=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=20isTotals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/cell/header-cell.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/s2-core/src/cell/header-cell.ts b/packages/s2-core/src/cell/header-cell.ts index a8fb6eff73..05b5eac9d5 100644 --- a/packages/s2-core/src/cell/header-cell.ts +++ b/packages/s2-core/src/cell/header-cell.ts @@ -85,7 +85,7 @@ export abstract class HeaderCell extends BaseCell { } protected getFormattedFieldValue(): FormatResult { - const { label, isTotals, isGrandTotals } = this.meta; + const { label, isTotalRoot, isGrandTotals } = this.meta; const formatter = this.spreadsheet.dataSet.getFieldFormatter( this.meta.field, @@ -101,14 +101,13 @@ export abstract class HeaderCell extends BaseCell { } else if (this.spreadsheet.isHierarchyTreeType()) { shouldFormat = !isGrandTotals; } else { - shouldFormat = !isTotals; + shouldFormat = !isTotalRoot; } const formattedValue = shouldFormat && formatter ? formatter(label, undefined, this.meta) : label; - return { formattedValue, value: label, From ce4aa590a588c8c973d5c929373c208cc28cdbb1 Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 7 Sep 2023 15:20:23 +0800 Subject: [PATCH 31/39] =?UTF-8?q?fix:=20isTotalRoot=20=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=20isTotals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/__tests__/unit/cell/header-cell-spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts index 14b9f566ee..28c3082153 100644 --- a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts @@ -60,7 +60,7 @@ describe('header cell formatter test', () => { value: '总计', parent: root, label: '总计', - isTotals: true, + isTotalRoot: true, }); const rowNode = new Node({ id: `root[&]杭州[&]小计`, @@ -68,7 +68,7 @@ describe('header cell formatter test', () => { value: '小计', parent: root, label: '小计', - isTotals: true, + isTotalRoot: true, }); const formatter: Formatter = (value) => { From e51ab22ea6d8e2b982055473f7e66b1406e575fb Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 7 Sep 2023 15:49:45 +0800 Subject: [PATCH 32/39] =?UTF-8?q?fix:=20isTotalRoot=20=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=20isTotals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/data-set/pivot-data-set.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 37a50b5425..25c37d07b5 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -623,7 +623,7 @@ export class PivotDataSet extends BaseDataSet { } // 有中间维度汇总的分组场景,将有中间 undefined 值的 query 处理为一组合法 query 后查询数据再合并 - private getGroupTotalMultiData(totalRows, columns, query): DataType[] { + private getGroupTotalMultiData(totalRows, rows, columns, query): DataType[] { let result = []; const rowTotalGroupQueries = this.getTotalGroupQueries(totalRows, query); let totalGroupQueries = []; @@ -645,8 +645,8 @@ export class PivotDataSet extends BaseDataSet { colDimensionValues, careUndefined: true, isFirstCreate: true, - rowFields: rowDimensionValues, - colFields: colDimensionValues, + rowFields: rows, + colFields: columns, rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); @@ -674,7 +674,7 @@ export class PivotDataSet extends BaseDataSet { const existDimensionGroup = this.checkExistDimensionGroup(query); let result = []; if (existDimensionGroup) { - result = this.getGroupTotalMultiData(totalRows, columns, query); + result = this.getGroupTotalMultiData(totalRows, rows, columns, query); } else { const rowDimensionValues = getQueryDimValues(totalRows, query); const colDimensionValues = getQueryDimValues(columns as string[], query); @@ -683,8 +683,8 @@ export class PivotDataSet extends BaseDataSet { colDimensionValues, careUndefined: true, isFirstCreate: true, - rowFields: rowDimensionValues, - colFields: colDimensionValues, + rowFields: rows, + colFields: columns as string[], rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); From 4f44045ba9c087a3d2213fe24d72eb6df39642ae Mon Sep 17 00:00:00 2001 From: JuZe Date: Fri, 8 Sep 2023 10:21:48 +0800 Subject: [PATCH 33/39] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=20React=20?= =?UTF-8?q?=E5=8C=85=E5=BF=AB=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../build-table-hierarchy-spec.tsx.snap | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/s2-react/__tests__/unit/utils/__snapshots__/build-table-hierarchy-spec.tsx.snap b/packages/s2-react/__tests__/unit/utils/__snapshots__/build-table-hierarchy-spec.tsx.snap index fad5bec42a..36ce2b1f24 100644 --- a/packages/s2-react/__tests__/unit/utils/__snapshots__/build-table-hierarchy-spec.tsx.snap +++ b/packages/s2-react/__tests__/unit/utils/__snapshots__/build-table-hierarchy-spec.tsx.snap @@ -19,6 +19,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "$$series_number$$", "label": "序号", @@ -49,6 +50,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "province", "label": "省份", @@ -79,6 +81,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "city", "label": "城市", @@ -109,6 +112,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "type", "label": "类别", @@ -139,6 +143,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "sub_type", "label": "子类别", @@ -169,6 +174,7 @@ Object { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "number", "label": "数量", @@ -197,6 +203,7 @@ Object { "isPivotMode": undefined, "isSubTotals": undefined, "isTotalMeasure": undefined, + "isTotalRoot": undefined, "isTotals": undefined, "key": "", "label": "", @@ -230,6 +237,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "$$series_number$$", "label": "序号", @@ -260,6 +268,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "province", "label": "省份", @@ -290,6 +299,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "city", "label": "城市", @@ -320,6 +330,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "type", "label": "类别", @@ -350,6 +361,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "sub_type", "label": "子类别", @@ -380,6 +392,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "number", "label": "数量", @@ -413,6 +426,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "$$series_number$$", "label": "序号", @@ -443,6 +457,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "province", "label": "省份", @@ -473,6 +488,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "city", "label": "城市", @@ -503,6 +519,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "type", "label": "类别", @@ -533,6 +550,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "sub_type", "label": "子类别", @@ -563,6 +581,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "number", "label": "数量", @@ -595,6 +614,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "$$series_number$$", "label": "序号", @@ -626,6 +646,7 @@ Hierarchy { "isPivotMode": undefined, "isSubTotals": false, "isTotalMeasure": false, + "isTotalRoot": false, "isTotals": false, "key": "$$series_number$$", "label": "序号", From 245cec45d190bff884f8e395ca1d9a4263aff4ee Mon Sep 17 00:00:00 2001 From: JuZe Date: Thu, 14 Sep 2023 18:52:53 +0800 Subject: [PATCH 34/39] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=A0=91?= =?UTF-8?q?=E7=8A=B6=E6=A8=A1=E5=BC=8F=E4=B8=8B=E6=80=BB=E8=AE=A1=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E7=9A=84=E6=8C=87=E6=A0=87=E8=8A=82=E7=82=B9=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=A2=AB=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/cell/header-cell.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/s2-core/src/cell/header-cell.ts b/packages/s2-core/src/cell/header-cell.ts index 3d6c04ecce..0bfebe0b5f 100644 --- a/packages/s2-core/src/cell/header-cell.ts +++ b/packages/s2-core/src/cell/header-cell.ts @@ -99,7 +99,7 @@ export abstract class HeaderCell extends BaseCell { if (this.spreadsheet.isTableMode()) { shouldFormat = false; } else if (this.spreadsheet.isHierarchyTreeType()) { - shouldFormat = !isGrandTotals; + shouldFormat = !(isGrandTotals && isTotalRoot); } else { shouldFormat = !isTotalRoot; } From 4f651d8af7af6303e9447c3a8c728d232fe5a35c Mon Sep 17 00:00:00 2001 From: JuZe Date: Sat, 16 Sep 2023 22:15:17 +0800 Subject: [PATCH 35/39] =?UTF-8?q?refactor:=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC=E5=92=8C=E7=BC=96=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/utils/export/export-spec.ts | 8 +- .../s2-core/src/common/interface/basic.ts | 4 +- packages/s2-core/src/data-set/interface.ts | 9 + .../s2-core/src/data-set/pivot-data-set.ts | 113 ++++++------ .../src/facet/layout/build-gird-hierarchy.ts | 173 ++++++++++-------- .../facet/layout/build-row-tree-hierarchy.ts | 8 +- .../s2-core/src/facet/layout/interface.ts | 9 +- .../s2-core/src/facet/layout/total-class.ts | 20 +- packages/s2-core/src/facet/pivot-facet.ts | 12 +- .../s2-core/src/sheet-type/spread-sheet.ts | 4 +- .../src/utils/dataset/pivot-data-set.ts | 2 +- packages/s2-core/src/utils/export/copy.ts | 14 +- .../s2-core/src/utils/layout/add-totals.ts | 14 +- s2-site/docs/common/totals.en.md | 4 +- s2-site/docs/common/totals.zh.md | 4 +- s2-site/docs/manual/basic/totals.en.md | 8 +- s2-site/docs/manual/basic/totals.zh.md | 12 +- .../totals/demo/dimension-group-col.ts | 4 +- 18 files changed, 238 insertions(+), 184 deletions(-) diff --git a/packages/s2-core/__tests__/unit/utils/export/export-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts index 8e763350f2..d160c70afe 100644 --- a/packages/s2-core/__tests__/unit/utils/export/export-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts @@ -255,8 +255,8 @@ describe('PivotSheet Export Test', () => { subTotalsDimensions: ['province'], }, col: { - totalsDimensionsGroup: ['city', 'type'], - subTotalsDimensionsGroup: ['sub_type'], + totalsGroupDimensions: ['city', 'type'], + subTotalsGroupDimensions: ['sub_type'], showGrandTotals: true, showSubTotals: true, subTotalsDimensions: ['type'], @@ -291,8 +291,8 @@ describe('PivotSheet Export Test', () => { subTotalsDimensions: ['province'], }, col: { - totalsDimensionsGroup: ['city', 'sub_type', 'province'], - subTotalsDimensionsGroup: ['sub_type'], + totalsGroupDimensions: ['city', 'sub_type', 'province'], + subTotalsGroupDimensions: ['sub_type'], showGrandTotals: true, showSubTotals: true, subTotalsDimensions: ['type'], diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index 94b7b22767..cc63caae50 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -152,9 +152,9 @@ export interface Total { // sub label's display name, default = '小计' subLabel?: string; /** 总计分组维度 */ - totalsDimensionsGroup?: string[]; + totalsGroupDimensions?: string[]; /** 小计分组维度 */ - subTotalsDimensionsGroup?: string[]; + subTotalsGroupDimensions?: string[]; } /** diff --git a/packages/s2-core/src/data-set/interface.ts b/packages/s2-core/src/data-set/interface.ts index 3d250ecad5..40f54ce91a 100644 --- a/packages/s2-core/src/data-set/interface.ts +++ b/packages/s2-core/src/data-set/interface.ts @@ -51,6 +51,15 @@ export interface CellDataParams { totalStatus?: TotalStatus; } +export interface checkAccordQueryParams { + // item of sortedDimensionValues,es: "浙江省[&]杭州市[&]家具[&]桌子" + dimensionValues: string; + query: DataType; + // rows or columns + dimensions: string[]; + field: string; +} + export interface TotalStatus { isRowTotal: boolean; isRowSubTotal: boolean; 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 25c37d07b5..2aaf955e95 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -15,6 +15,7 @@ import { isNumber, isUndefined, keys, + some, uniq, unset, values, @@ -62,6 +63,7 @@ import type { CellMeta } from '../common'; import { BaseDataSet } from './base-data-set'; import type { CellDataParams, + checkAccordQueryParams, DataType, PivotMeta, SortedDimensionValues, @@ -320,26 +322,30 @@ export class PivotDataSet extends BaseDataSet { }; } - // rows :['province','city','type'] - // query: ['浙江省',undefined] => return: ['文具','家具'] - public getTotalDimensionValues(field: string, query?: DataType): string[] { + public getDimensionsByField(field: string): string[] { const { rows = [], columns = [] } = this.fields || {}; - let dimensions: string[] = []; if (includes(rows, field)) { - dimensions = rows; - } else if (includes(columns, field)) { - dimensions = columns as string[]; + return rows; + } + if (includes(columns, field)) { + return columns as string[]; } - let allCurrentFieldDimensionValues = - this.sortedDimensionValues[field] || []; - allCurrentFieldDimensionValues = allCurrentFieldDimensionValues.filter( - (dimValue) => - this.checkAccordQueryWithDimensionValue( - dimValue, - query, - dimensions, - field, - ), + return []; + } + + // rows :['province','city','type'] + // query: ['浙江省',undefined] => return: ['文具','家具'] + public getTotalDimensionValues(field: string, query?: DataType): string[] { + const dimensions = this.getDimensionsByField(field); + const allCurrentFieldDimensionValues = ( + this.sortedDimensionValues[field] || [] + ).filter((dimValue) => + this.checkAccordQueryWithDimensionValue({ + dimensionValues: dimValue, + query, + dimensions, + field, + }), ); return filterUndefined( uniq(getDimensionsWithoutPathPre([...allCurrentFieldDimensionValues])), @@ -396,12 +402,7 @@ export class PivotDataSet extends BaseDataSet { } getTotalValue(query: DataType, totalStatus?: TotalStatus) { - let effectiveStatus = false; - forEach(totalStatus, (bol) => { - if (bol) { - effectiveStatus = true; - } - }); + const effectiveStatus = some(totalStatus); const status = effectiveStatus ? totalStatus : this.getTotalStatus(query); const { aggregation, calcFunc } = getAggregationAndCalcFuncByQuery( @@ -520,7 +521,7 @@ export class PivotDataSet extends BaseDataSet { * [undefined , '杭州市' , undefined , 'number'] => true * ['浙江省' , '杭州市' , undefined , 'number'] => true */ - checkExistDimensionGroup(query: DataType): boolean { + private checkExistDimensionGroup(query: DataType): boolean { const { rows, columns } = this.fields; const check = (dimensions: string[]) => { let existDimensionValue = false; @@ -544,15 +545,13 @@ export class PivotDataSet extends BaseDataSet { * dimensions = ['province','city'] * query = [province: '杭州市', type: '文具'] * field = 'sub_type' - * 浙江省[&]杭州市[&]家具[&]桌子 => true - * 四川省[&]成都市[&]文具[&]笔 => false + * DimensionValue: 浙江省[&]杭州市[&]家具[&]桌子 => true + * DimensionValue: 四川省[&]成都市[&]文具[&]笔 => false */ - checkAccordQueryWithDimensionValue( - dimensionValues: string, - query, - dimensions: string[], - field: string, + private checkAccordQueryWithDimensionValue( + params: checkAccordQueryParams, ): boolean { + const { dimensionValues, query, dimensions, field } = params; for (const [index, dimension] of dimensions.entries()) { const queryValue = get(query, dimension); if (queryValue) { @@ -577,12 +576,12 @@ export class PivotDataSet extends BaseDataSet { * {'百事公司','可乐','undefined','price'}, * ] */ - getTotalGroupQueries(dimensions: string[], query) { - let queryArray = [query]; + private getTotalGroupQueries(dimensions: string[], originQuery: DataType) { + let queries = [originQuery]; let existDimensionGroupKey = null; for (let i = dimensions.length; i > 0; i--) { const key = dimensions[i - 1]; - if (keys(query).includes(key)) { + if (keys(originQuery).includes(key)) { if (key !== EXTRA_FIELD) { existDimensionGroupKey = key; } @@ -592,16 +591,16 @@ export class PivotDataSet extends BaseDataSet { let res = []; const arrayLength = allCurrentFieldDimensionValues[0].split(ID_SEPARATOR).length; - for (const queryItem of queryArray) { + for (const query of queries) { const resKeys = []; for (const dimValue of allCurrentFieldDimensionValues) { if ( - this.checkAccordQueryWithDimensionValue( - dimValue, - queryItem, + this.checkAccordQueryWithDimensionValue({ + dimensionValues: dimValue, + query, dimensions, - existDimensionGroupKey, - ) + field: existDimensionGroupKey, + }) ) { const arrTypeValue = dimValue.split(ID_SEPARATOR); const currentKey = arrTypeValue[arrayLength - 2]; @@ -611,42 +610,46 @@ export class PivotDataSet extends BaseDataSet { } } const queryList = uniq(resKeys).map((v) => { - return { ...queryItem, [key]: v }; + return { ...query, [key]: v }; }); res = concat(res, queryList); } - queryArray = res; + queries = res; existDimensionGroupKey = key; } } - return queryArray; + return queries; } // 有中间维度汇总的分组场景,将有中间 undefined 值的 query 处理为一组合法 query 后查询数据再合并 - private getGroupTotalMultiData(totalRows, rows, columns, query): DataType[] { + private getGroupTotalMultiData( + totalRows: string[], + originQuery: DataType, + ): DataType[] { + const { rows, columns } = this.fields; let result = []; - const rowTotalGroupQueries = this.getTotalGroupQueries(totalRows, query); + const rowTotalGroupQueries = this.getTotalGroupQueries( + totalRows, + originQuery, + ); let totalGroupQueries = []; - for (const queryItem of rowTotalGroupQueries) { + for (const query of rowTotalGroupQueries) { totalGroupQueries = concat( totalGroupQueries, - this.getTotalGroupQueries(columns as string[], queryItem), + this.getTotalGroupQueries(columns as string[], query), ); } - for (const queryItem of totalGroupQueries) { - const rowDimensionValues = getQueryDimValues(totalRows, queryItem); - const colDimensionValues = getQueryDimValues( - columns as string[], - queryItem, - ); + for (const query of totalGroupQueries) { + const rowDimensionValues = getQueryDimValues(totalRows, query); + const colDimensionValues = getQueryDimValues(columns as string[], query); const path = getDataPath({ rowDimensionValues, colDimensionValues, careUndefined: true, isFirstCreate: true, rowFields: rows, - colFields: columns, + colFields: columns as string[], rowPivotMeta: this.rowPivotMeta, colPivotMeta: this.colPivotMeta, }); @@ -674,7 +677,7 @@ export class PivotDataSet extends BaseDataSet { const existDimensionGroup = this.checkExistDimensionGroup(query); let result = []; if (existDimensionGroup) { - result = this.getGroupTotalMultiData(totalRows, rows, columns, query); + result = this.getGroupTotalMultiData(totalRows, rows); } else { const rowDimensionValues = getQueryDimValues(totalRows, query); const colDimensionValues = getQueryDimValues(columns as string[], query); diff --git a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts index 278385b561..eb8de392ec 100644 --- a/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts +++ b/packages/s2-core/src/facet/layout/build-gird-hierarchy.ts @@ -9,15 +9,9 @@ import { TotalMeasure } from '../layout/total-measure'; import { whetherLeafByLevel } from '../../utils/layout/whether-leaf-by-level'; import { TotalClass } from './total-class'; -/** - * Build grid hierarchy in rows or columns - * - * @param params - */ -export const buildGridHierarchy = (params: GridHeaderParams) => { +const buildTotalGridHierarchy = (params: GridHeaderParams) => { const { addTotalMeasureInTotal, - addMeasureInTotalQuery, parentNode, currentField, fields, @@ -32,88 +26,115 @@ export const buildGridHierarchy = (params: GridHeaderParams) => { const fieldName = dataSet.getFieldName(currentField); let query = {}; - if (parentNode.isTotals) { - const totalsConfig = spreadsheet.getTotalsConfig(currentField); - const dimensionGroup = parentNode.isGrandTotals - ? totalsConfig.totalsDimensionsGroup - : totalsConfig.subTotalsDimensionsGroup; - if (dimensionGroup?.includes(currentField)) { - query = getDimsCondition(parentNode); - const dimValues = dataSet.getTotalDimensionValues(currentField, query); - fieldValues.push( - ...(dimValues || []).map( - (value) => - new TotalClass( - value, - parentNode.isSubTotals, - parentNode.isGrandTotals, - false, - ), - ), - ); - if (isEmpty(fieldValues)) { - fieldValues.push(fieldName); - } - } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { - // add total measures - query = getDimsCondition(parentNode); - fieldValues.push(...values.map((v) => new TotalMeasure(v))); - } else if (whetherLeafByLevel({ facetCfg, level: index, fields })) { - // 如果最后一级没有分组维度,则将上一个结点设为叶子结点 - parentNode.isLeaf = true; - hierarchy.pushIndexNode(parentNode); - parentNode.rowIndex = hierarchy.getIndexNodes().length - 1; - return; - } else { - // 如果是空维度,则跳转到下一级 level - buildGridHierarchy({ ...params, currentField: fields[index + 1] }); - return; + const totalsConfig = spreadsheet.getTotalsConfig(currentField); + const dimensionGroup = parentNode.isGrandTotals + ? totalsConfig.totalsGroupDimensions + : totalsConfig.subTotalsGroupDimensions; + if (dimensionGroup?.includes(currentField)) { + query = getDimsCondition(parentNode); + const dimValues = dataSet.getTotalDimensionValues(currentField, query); + fieldValues.push( + ...(dimValues || []).map( + (value) => + new TotalClass({ + label: value, + isSubTotals: parentNode.isSubTotals, + isGrandTotals: parentNode.isGrandTotals, + isTotalRoot: false, + }), + ), + ); + if (isEmpty(fieldValues)) { + fieldValues.push(fieldName); } + } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { + // add total measures + query = getDimsCondition(parentNode); + fieldValues.push(...values.map((v) => new TotalMeasure(v))); + } else if (whetherLeafByLevel({ facetCfg, level: index, fields })) { + // 如果最后一级没有分组维度,则将上一个结点设为叶子结点 + parentNode.isLeaf = true; + hierarchy.pushIndexNode(parentNode); + parentNode.rowIndex = hierarchy.getIndexNodes().length - 1; + return; } else { - // field(dimension)'s all values - query = getDimsCondition(parentNode, true); + // 如果是空维度,则跳转到下一级 level + buildTotalGridHierarchy({ ...params, currentField: fields[index + 1] }); + return; + } + + const displayFieldValues = fieldValues.filter((value) => !isUndefined(value)); + generateHeaderNodes({ + ...params, + fieldValues: displayFieldValues, + level: index, + parentNode, + query, + }); +}; - const dimValues = dataSet.getDimensionValues(currentField, query); +const buildNormalGridHierarchy = (params: GridHeaderParams) => { + const { parentNode, currentField, fields, facetCfg } = params; - const arrangedValues = layoutArrange( - dimValues, - facetCfg, - parentNode, - currentField, - ); - fieldValues.push(...(arrangedValues || [])); + const index = fields.indexOf(currentField); - // add skeleton for empty data + const { dataSet, spreadsheet } = facetCfg; + const fieldValues: FieldValue[] = []; + const fieldName = dataSet.getFieldName(currentField); - if (isEmpty(fieldValues)) { - if (currentField === EXTRA_FIELD) { - fieldValues.push(...dataSet.fields?.values); - } else { - fieldValues.push(fieldName); - } - } + let query = {}; + + // field(dimension)'s all values + query = getDimsCondition(parentNode, true); + + const dimValues = dataSet.getDimensionValues(currentField, query); - // add totals if needed - addTotals({ - currentField, - lastField: fields[index - 1], - isFirstField: index === 0, - fieldValues, - spreadsheet, - }); + const arrangedValues = layoutArrange( + dimValues, + facetCfg, + parentNode, + currentField, + ); + fieldValues.push(...(arrangedValues || [])); + + // add skeleton for empty data + + if (isEmpty(fieldValues)) { + if (currentField === EXTRA_FIELD) { + fieldValues.push(...dataSet.fields?.values); + } else { + fieldValues.push(fieldName); + } } + // add totals if needed + addTotals({ + currentField, + lastField: fields[index - 1], + isFirstField: index === 0, + fieldValues, + spreadsheet, + }); + const displayFieldValues = fieldValues.filter((value) => !isUndefined(value)); generateHeaderNodes({ - currentField, - fields, + ...params, fieldValues: displayFieldValues, - facetCfg, - hierarchy, - parentNode, level: index, + parentNode, query, - addMeasureInTotalQuery, - addTotalMeasureInTotal, }); }; + +/** + * Build grid hierarchy in rows or columns + * + * @param params + */ +export const buildGridHierarchy = (params: GridHeaderParams) => { + if (params.parentNode.isTotals) { + buildTotalGridHierarchy(params); + } else { + buildNormalGridHierarchy(params); + } +}; 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 05afda5ffe..28697f9c11 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 @@ -20,7 +20,13 @@ const addTotals = ( // TODO valueInCol = false and one or more values if (totalsConfig.showGrandTotals) { const func = totalsConfig.reverseLayout ? 'unshift' : 'push'; - fieldValues[func](new TotalClass(totalsConfig.label, false, true)); + fieldValues[func]( + new TotalClass({ + label: totalsConfig.label, + isSubTotals: false, + isGrandTotals: true, + }), + ); } }; diff --git a/packages/s2-core/src/facet/layout/interface.ts b/packages/s2-core/src/facet/layout/interface.ts index 45cae6244e..3e15a02f5d 100644 --- a/packages/s2-core/src/facet/layout/interface.ts +++ b/packages/s2-core/src/facet/layout/interface.ts @@ -42,15 +42,8 @@ export interface TotalParams { spreadsheet: SpreadSheet; } -export interface HeaderNodesParams { - currentField: string; - fields: string[]; +export interface HeaderNodesParams extends GridHeaderParams { fieldValues: FieldValue[]; - addTotalMeasureInTotal: boolean; - addMeasureInTotalQuery: boolean; - facetCfg: SpreadSheetFacetCfg; - hierarchy: Hierarchy; - parentNode: Node; level: number; query: Record; } diff --git a/packages/s2-core/src/facet/layout/total-class.ts b/packages/s2-core/src/facet/layout/total-class.ts index 75f3e40ef2..36f47c995d 100644 --- a/packages/s2-core/src/facet/layout/total-class.ts +++ b/packages/s2-core/src/facet/layout/total-class.ts @@ -1,6 +1,16 @@ /** * Class to mark '小计' & '总计' */ + +export interface TotalClassConfig { + label: string; + // 是否属于小计汇总格 + isSubTotals: boolean; + // 是否属于总计汇总格 + isGrandTotals: boolean; + // 是否是”小计“、”总计“单元格本身 + isTotalRoot?: boolean; +} export class TotalClass { public label: string; @@ -8,15 +18,11 @@ export class TotalClass { public isGrandTotals: boolean; - // 是否为 小计 总计 根结点,即value = “小计”,单元格,此类结点不参与 query + // 是否为 小计/总计 根结点,即 value = “小计”,单元格,此类结点不参与 query public isTotalRoot: boolean; - public constructor( - label: string, - isSubTotals = false, - isGrandTotals = false, - isTotalRoot = false, - ) { + public constructor(params: TotalClassConfig) { + const { label, isSubTotals, isGrandTotals, isTotalRoot } = params; this.label = label; this.isSubTotals = isSubTotals; this.isGrandTotals = isGrandTotals; diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts index bfab95c974..3b432f44b5 100644 --- a/packages/s2-core/src/facet/pivot-facet.ts +++ b/packages/s2-core/src/facet/pivot-facet.ts @@ -28,7 +28,7 @@ import { getDataCellId, handleDataItem } from '../utils/cell/data-cell'; import { getActionIconConfig } from '../utils/cell/header-cell'; import { getIndexRangeWithOffsets } from '../utils/facet'; import { getCellWidth, safeJsonParse } from '../utils/text'; -import { getTotalStatusByRowCol } from '../utils/dataset/pivot-data-set'; +import { getHeaderTotalStatus } from '../utils/dataset/pivot-data-set'; import { BaseFacet } from './base-facet'; import { buildHeaderHierarchy } from './layout/build-header-hierarchy'; import type { Hierarchy } from './layout/hierarchy'; @@ -95,7 +95,7 @@ export class PivotFacet extends BaseFacet { } : {}; const dataQuery = merge({}, rowQuery, colQuery, measureInfo); - const totalStatus = getTotalStatusByRowCol(row, col); + const totalStatus = getHeaderTotalStatus(row, col); const data = dataSet.getCellData({ query: dataQuery, rowNode: row, @@ -323,7 +323,7 @@ export class PivotFacet extends BaseFacet { col.isTotalMeasure || rowNode.isTotals || rowNode.isTotalMeasure, - totalStatus: getTotalStatusByRowCol(rowNode, col), + totalStatus: getHeaderTotalStatus(rowNode, col), }); if (cellData) { @@ -551,8 +551,8 @@ export class PivotFacet extends BaseFacet { const fields = isRowHeader ? rows : columns; const totalConfig = isRowHeader ? totals.row : totals.col; const dimensionGroup = isSubTotal - ? totalConfig.subTotalsDimensionsGroup || [] - : totalConfig.totalsDimensionsGroup || []; + ? totalConfig.subTotalsGroupDimensions || [] + : totalConfig.totalsGroupDimensions || []; const multipleMap: number[] = Array.from({ length: maxLevel + 1 }, () => 1); for (let level = maxLevel; level > 0; level--) { const currentField = fields[level] as string; @@ -679,7 +679,7 @@ export class PivotFacet extends BaseFacet { col.isTotalMeasure || rowNode.isTotals || rowNode.isTotalMeasure, - totalStatus: getTotalStatusByRowCol(rowNode, col), + totalStatus: getHeaderTotalStatus(rowNode, col), }); const cellDataKeys = keys(cellData); diff --git a/packages/s2-core/src/sheet-type/spread-sheet.ts b/packages/s2-core/src/sheet-type/spread-sheet.ts index b5470a4fd6..f3d48faad9 100644 --- a/packages/s2-core/src/sheet-type/spread-sheet.ts +++ b/packages/s2-core/src/sheet-type/spread-sheet.ts @@ -618,8 +618,8 @@ export abstract class SpreadSheet extends EE { return { label: i18n('总计'), subLabel: i18n('小计'), - totalsDimensionsGroup: [], - subTotalsDimensionsGroup: [], + totalsGroupDimensions: [], + subTotalsGroupDimensions: [], ...totalConfig, showSubTotals, }; 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 553f74ae53..02bcc254f3 100644 --- a/packages/s2-core/src/utils/dataset/pivot-data-set.ts +++ b/packages/s2-core/src/utils/dataset/pivot-data-set.ts @@ -344,7 +344,7 @@ export function generateExtraFieldMeta( return extraFieldMeta; } -export function getTotalStatusByRowCol(row: Node, col: Node): TotalStatus { +export function getHeaderTotalStatus(row: Node, col: Node): TotalStatus { return { isRowTotal: row.isGrandTotals, isRowSubTotal: row.isSubTotals, diff --git a/packages/s2-core/src/utils/export/copy.ts b/packages/s2-core/src/utils/export/copy.ts index f78c7e3678..b2a11af36a 100644 --- a/packages/s2-core/src/utils/export/copy.ts +++ b/packages/s2-core/src/utils/export/copy.ts @@ -31,7 +31,7 @@ import type { SpreadSheet } from '../../sheet-type'; import { copyToClipboard } from '../../utils/export'; import { flattenDeep } from '../data-set-operate'; import { getEmptyPlaceholder } from '../text'; -import { getTotalStatusByRowCol } from '../dataset/pivot-data-set'; +import { getHeaderTotalStatus } from '../dataset/pivot-data-set'; export function keyEqualTo(key: string, compareKey: string) { if (!key || !compareKey) { @@ -115,7 +115,7 @@ const getValueFromMeta = ( rowNode.isTotalMeasure || colNode.isTotals || colNode.isTotalMeasure, - totalStatus: getTotalStatusByRowCol(rowNode, colNode), + totalStatus: getHeaderTotalStatus(rowNode, colNode), }); return cell?.[VALUE_FIELD] ?? ''; } @@ -395,7 +395,7 @@ const getDataMatrix = ( rowNode.isTotalMeasure || colNode.isTotals || colNode.isTotalMeasure, - totalStatus: getTotalStatusByRowCol(rowNode, colNode), + totalStatus: getHeaderTotalStatus(rowNode, colNode), }); return getFormat( colNode.colIndex, @@ -660,6 +660,11 @@ function getLastLevelCells( }); } +/** 处理有合并单元格的复制(小记总计格) + * 维度1 | 维度2 | 维度3 + * 总计 | 维度三 + * => 总计 总计 维度三 + */ function getTotalCellMatrixId(meta: Node, maxLevel: number) { let nextNode = meta; let lastNode = { level: maxLevel }; @@ -667,7 +672,7 @@ function getTotalCellMatrixId(meta: Node, maxLevel: number) { while (nextNode.level >= 0) { let repeatNumber = lastNode.level - nextNode.level; while (repeatNumber > 0) { - cellId = nextNode.label + ID_SEPARATOR + cellId; + cellId = `${nextNode.label}${ID_SEPARATOR}${cellId}`; repeatNumber--; } lastNode = nextNode; @@ -675,6 +680,7 @@ function getTotalCellMatrixId(meta: Node, maxLevel: number) { } return cellId; } + function getCellMatrix( lastLevelCells: Array, maxLevel: number, diff --git a/packages/s2-core/src/utils/layout/add-totals.ts b/packages/s2-core/src/utils/layout/add-totals.ts index ed87291a18..1f5e25481f 100644 --- a/packages/s2-core/src/utils/layout/add-totals.ts +++ b/packages/s2-core/src/utils/layout/add-totals.ts @@ -15,7 +15,12 @@ export const addTotals = (params: TotalParams) => { // check to see if grand total is added if (totalsConfig?.showGrandTotals) { action = totalsConfig.reverseLayout ? 'unshift' : 'push'; - totalValue = new TotalClass(totalsConfig.label, false, true, true); + totalValue = new TotalClass({ + label: totalsConfig.label, + isSubTotals: false, + isGrandTotals: true, + isTotalRoot: true, + }); } } else if ( /** @@ -29,7 +34,12 @@ export const addTotals = (params: TotalParams) => { currentField !== EXTRA_FIELD ) { action = totalsConfig.reverseSubLayout ? 'unshift' : 'push'; - totalValue = new TotalClass(totalsConfig.subLabel, true, false, true); + totalValue = new TotalClass({ + label: totalsConfig.label, + isSubTotals: false, + isGrandTotals: true, + isTotalRoot: true, + }); } fieldValues[action]?.(totalValue); diff --git a/s2-site/docs/common/totals.en.md b/s2-site/docs/common/totals.en.md index 56f167b9cf..d9b8df6b75 100644 --- a/s2-site/docs/common/totals.en.md +++ b/s2-site/docs/common/totals.en.md @@ -27,8 +27,8 @@ object is **required** , *default: null* Function description: subtotal total co | subLabel | subtotal alias | `string` | | | | calcTotals | Custom Calculated Totals | [CalcTotals](#calctotals) | | | | calcSubTotals | Custom Calculated Subtotals | [CalcTotals](#calctotals) | | | -| totalsDimensionsGroup | grouping dimension of the total |`string[]` | | | -| subTotalsDimensionsGroup | grouping dimension of the subtotal | `string[]` | | | +| totalsGroupDimensions | grouping dimension of the total |`string[]` | | | +| subTotalsGroupDimensions | grouping dimension of the subtotal | `string[]` | | | ## CalcTotals diff --git a/s2-site/docs/common/totals.zh.md b/s2-site/docs/common/totals.zh.md index 86ada706c4..6edacd116a 100644 --- a/s2-site/docs/common/totals.zh.md +++ b/s2-site/docs/common/totals.zh.md @@ -27,8 +27,8 @@ object **必选**,_default:null_ 功能描述: 小计总计配置 | subLabel | 小计别名 | `string` | | | | calcTotals | 自定义计算总计 | [CalcTotals](#calctotals) | | | | calcSubTotals | 自定义计算小计 | [CalcTotals](#calctotals) | | | -| totalsDimensionsGroup | 总计的分组维度 |`string[]` | | | -| subTotalsDimensionsGroup | 小计的分组维度 | `string[]` | | | +| totalsGroupDimensions | 总计的分组维度 |`string[]` | | | +| subTotalsGroupDimensions | 小计的分组维度 | `string[]` | | | ## CalcTotals diff --git a/s2-site/docs/manual/basic/totals.en.md b/s2-site/docs/manual/basic/totals.en.md index da12aa68d8..805319532b 100644 --- a/s2-site/docs/manual/basic/totals.en.md +++ b/s2-site/docs/manual/basic/totals.en.md @@ -25,8 +25,8 @@ object is **required** , *default: null* Function description: Subtotal calculat | subLabel | subtotal alias | `string` | | | | | calcTotals | calculate the total | `CalcTotals` | | | | | calcSubTotals | calculate subtotal | `CalcTotals` | | | | -| totalsDimensionsGroup | grouping dimension of the total |`string[]` | | | -| subTotalsDimensionsGroup | grouping dimension of the subtotal | `string[]` | | | +| totalsGroupDimensions | grouping dimension of the total |`string[]` | | | +| subTotalsGroupDimensions | grouping dimension of the subtotal | `string[]` | | | ```typescript const s2Options = { @@ -37,8 +37,8 @@ object is **required** , *default: null* Function description: Subtotal calculat reverseLayout: true, reverseSubLayout: true, subTotalsDimensions: [ 'province' ], - totalsDimensionsGroup: ['city'], - subTotalsDimensionsGroup: ['type', 'sub_type'], + totalsGroupDimensions: ['city'], + subTotalsGroupDimensions: ['type', 'sub_type'], }, col: { showGrandTotals: true, diff --git a/s2-site/docs/manual/basic/totals.zh.md b/s2-site/docs/manual/basic/totals.zh.md index 4101ba6852..cffaf101cb 100644 --- a/s2-site/docs/manual/basic/totals.zh.md +++ b/s2-site/docs/manual/basic/totals.zh.md @@ -51,7 +51,7 @@ order: 5 按维度进行 小计/总计 的汇总计算,用于进行某一维度的数据对比分析等。 - + #### 行总计小计分组 @@ -61,7 +61,7 @@ order: 5 #### 列总计小计分组 -row +col ## 使用 @@ -93,8 +93,8 @@ object **必选**,_default:null_ 功能描述: 小计总计算配置 | subLabel | 小计别名 | `string` | | | | calcTotals | 计算总计 | `CalcTotals` | | | | calcSubTotals | 计算小计 | `CalcTotals` | | | -| totalsDimensionsGroup | 总计的分组维度 |`string[]` | | | -| subTotalsDimensionsGroup | 小计的分组维度 | `string[]` | | | +| totalsGroupDimensions | 总计的分组维度 |`string[]` | | | +| subTotalsGroupDimensions | 小计的分组维度 | `string[]` | | | ```ts const s2Options = { @@ -105,8 +105,8 @@ const s2Options = { reverseLayout: true, reverseSubLayout: true, subTotalsDimensions: ['province'], - totalsDimensionsGroup: ['city'], - subTotalsDimensionsGroup: ['type', 'sub_type'], + totalsGroupDimensions: ['city'], + subTotalsGroupDimensions: ['type', 'sub_type'], }, col: { showGrandTotals: true, diff --git a/s2-site/examples/analysis/totals/demo/dimension-group-col.ts b/s2-site/examples/analysis/totals/demo/dimension-group-col.ts index 00322e085a..89bd78473a 100644 --- a/s2-site/examples/analysis/totals/demo/dimension-group-col.ts +++ b/s2-site/examples/analysis/totals/demo/dimension-group-col.ts @@ -56,9 +56,9 @@ fetch('https://gw.alipayobjects.com/os/bmw-prod/6eede6eb-8021-4da8-bb12-67891a57 aggregation: 'SUM', }, // 总计分组下,city 城市维度会出现分组 - totalsDimensionsGroup: ['city'], + totalsGroupDimensions: ['city'], // 小计维度下,type 类别维度下会出现分组 - subTotalsDimensionsGroup: ['type'], + subTotalsGroupDimensions: ['type'], }, }, }; From 68c76d1a501265ba7dd456380c9d79d782e59def Mon Sep 17 00:00:00 2001 From: JuZe Date: Sat, 16 Sep 2023 22:25:24 +0800 Subject: [PATCH 36/39] =?UTF-8?q?test:=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC=E5=92=8C=E7=BC=96=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/__tests__/unit/cell/header-cell-spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts index 28c3082153..870c3947db 100644 --- a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts +++ b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts @@ -92,6 +92,7 @@ describe('header cell formatter test', () => { label: '总计', isTotals: true, isGrandTotals: true, + isTotalRoot: true, }); const rowSubTotalNode = new Node({ From 495b606e332c167d300384db61b8ba33ceb681bd Mon Sep 17 00:00:00 2001 From: JuZe Date: Sat, 16 Sep 2023 22:26:57 +0800 Subject: [PATCH 37/39] =?UTF-8?q?test:=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC=E5=92=8C=E7=BC=96=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- s2-site/examples/analysis/totals/demo/dimension-group-row.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s2-site/examples/analysis/totals/demo/dimension-group-row.ts b/s2-site/examples/analysis/totals/demo/dimension-group-row.ts index 02cde55ef4..e12518827e 100644 --- a/s2-site/examples/analysis/totals/demo/dimension-group-row.ts +++ b/s2-site/examples/analysis/totals/demo/dimension-group-row.ts @@ -55,9 +55,9 @@ fetch('https://gw.alipayobjects.com/os/bmw-prod/6eede6eb-8021-4da8-bb12-67891a57 aggregation: 'SUM', }, // 总计分组下,city 城市维度会出现分组 - totalsDimensionsGroup: ['city'], + totalsGroupDimensions: ['city'], // 小计维度下,type 类别维度下会出现分组 - subTotalsDimensionsGroup: ['type'], + subTotalsGroupDimensions: ['type'], }, }, }; From 2bd6251ef3c9ef6adc923fbaf98a16a59a86cc0e Mon Sep 17 00:00:00 2001 From: JuZe Date: Sat, 16 Sep 2023 22:26:57 +0800 Subject: [PATCH 38/39] =?UTF-8?q?test:=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC=E5=92=8C=E7=BC=96=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 7 +-- .../data-set/pivot-data-set-total-spec.ts | 48 +++++++++---------- .../s2-core/src/data-set/pivot-data-set.ts | 10 ++-- .../s2-core/src/utils/layout/add-totals.ts | 6 +-- .../totals/demo/dimension-group-row.ts | 4 +- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 12166c9035..4adc644ca1 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "build:umd": "lerna run build:umd --include-dependencies --stream", "bundle:size": "lerna run bundle:size --stream", "release": "lerna exec --ignore @antv/s2-shared --concurrency 1 -- npx --no-install semantic-release", - "release:bump-latest":"node ./scripts/latest-bump-version.js", + "release:bump-latest": "node ./scripts/latest-bump-version.js", "release:preview": "yarn release --dry-run --no-ci", "prepublish:manual": "yarn build", "publish:manual": "lerna publish", @@ -174,5 +174,6 @@ "vite-plugin-imp": "^2.1.8", "vue-jest": "^5.0.0-alpha.10" }, - "license": "MIT" -} + "license": "MIT", + "repository": "https://github.com/NoobNotN/S2.git" +} \ No newline at end of file diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts index f87a27ff43..2a7ac2d86b 100644 --- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts +++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts @@ -835,50 +835,50 @@ describe('Pivot Dataset Total Test', () => { }); test('should get correct boolean of dimensionValue is a query condition', () => { expect( - dataSet.checkAccordQueryWithDimensionValue( - '浙江省[&]杭州市[&]家具[&]桌子', - { + dataSet.checkAccordQueryWithDimensionValue({ + dimensionValues: '浙江省[&]杭州市[&]家具[&]桌子', + query: { province: '浙江省', city: 'A', type: 'Abc', }, - dataCfg.fields.rows, - 'province', - ), + dimensions: dataCfg.fields.rows, + field: 'province', + }), ).toEqual(true); expect( - dataSet.checkAccordQueryWithDimensionValue( - '浙江省[&]杭州市[&]家具[&]桌子', - { + dataSet.checkAccordQueryWithDimensionValue({ + dimensionValues: '浙江省[&]杭州市[&]家具[&]桌子', + query: { province: '浙江省', city: '杭州市', type: '家具', }, - dataCfg.fields.rows, - 'sub_type', - ), + dimensions: dataCfg.fields.rows, + field: 'sub_type', + }), ).toEqual(true); expect( - dataSet.checkAccordQueryWithDimensionValue( - '浙江省[&]杭州市[&]家具[&]桌子', - { + dataSet.checkAccordQueryWithDimensionValue({ + dimensionValues: '浙江省[&]杭州市[&]家具[&]桌子', + query: { province: '浙江省', city: '不是杭州市', type: '家具', }, - dataCfg.fields.rows, - 'sub_type', - ), + dimensions: dataCfg.fields.rows, + field: 'sub_type', + }), ).toEqual(false); expect( - dataSet.checkAccordQueryWithDimensionValue( - '浙江省[&]杭州市[&]家具[&]桌子', - { + dataSet.checkAccordQueryWithDimensionValue({ + dimensionValues: '浙江省[&]杭州市[&]家具[&]桌子', + query: { province: '浙江省', }, - dataCfg.fields.rows, - 'sub_type', - ), + dimensions: dataCfg.fields.rows, + field: 'sub_type', + }), ).toEqual(true); }); test('get correct query list when query need to be processed', () => { 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 2aaf955e95..ee278c5b76 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -521,7 +521,7 @@ export class PivotDataSet extends BaseDataSet { * [undefined , '杭州市' , undefined , 'number'] => true * ['浙江省' , '杭州市' , undefined , 'number'] => true */ - private checkExistDimensionGroup(query: DataType): boolean { + checkExistDimensionGroup(query: DataType): boolean { const { rows, columns } = this.fields; const check = (dimensions: string[]) => { let existDimensionValue = false; @@ -548,9 +548,7 @@ export class PivotDataSet extends BaseDataSet { * DimensionValue: 浙江省[&]杭州市[&]家具[&]桌子 => true * DimensionValue: 四川省[&]成都市[&]文具[&]笔 => false */ - private checkAccordQueryWithDimensionValue( - params: checkAccordQueryParams, - ): boolean { + checkAccordQueryWithDimensionValue(params: checkAccordQueryParams): boolean { const { dimensionValues, query, dimensions, field } = params; for (const [index, dimension] of dimensions.entries()) { const queryValue = get(query, dimension); @@ -576,7 +574,7 @@ export class PivotDataSet extends BaseDataSet { * {'百事公司','可乐','undefined','price'}, * ] */ - private getTotalGroupQueries(dimensions: string[], originQuery: DataType) { + getTotalGroupQueries(dimensions: string[], originQuery: DataType) { let queries = [originQuery]; let existDimensionGroupKey = null; for (let i = dimensions.length; i > 0; i--) { @@ -677,7 +675,7 @@ export class PivotDataSet extends BaseDataSet { const existDimensionGroup = this.checkExistDimensionGroup(query); let result = []; if (existDimensionGroup) { - result = this.getGroupTotalMultiData(totalRows, rows); + result = this.getGroupTotalMultiData(totalRows, query); } else { const rowDimensionValues = getQueryDimValues(totalRows, query); const colDimensionValues = getQueryDimValues(columns as string[], query); diff --git a/packages/s2-core/src/utils/layout/add-totals.ts b/packages/s2-core/src/utils/layout/add-totals.ts index 1f5e25481f..9b29207ca1 100644 --- a/packages/s2-core/src/utils/layout/add-totals.ts +++ b/packages/s2-core/src/utils/layout/add-totals.ts @@ -35,9 +35,9 @@ export const addTotals = (params: TotalParams) => { ) { action = totalsConfig.reverseSubLayout ? 'unshift' : 'push'; totalValue = new TotalClass({ - label: totalsConfig.label, - isSubTotals: false, - isGrandTotals: true, + label: totalsConfig.subLabel, + isSubTotals: true, + isGrandTotals: false, isTotalRoot: true, }); } diff --git a/s2-site/examples/analysis/totals/demo/dimension-group-row.ts b/s2-site/examples/analysis/totals/demo/dimension-group-row.ts index 02cde55ef4..e12518827e 100644 --- a/s2-site/examples/analysis/totals/demo/dimension-group-row.ts +++ b/s2-site/examples/analysis/totals/demo/dimension-group-row.ts @@ -55,9 +55,9 @@ fetch('https://gw.alipayobjects.com/os/bmw-prod/6eede6eb-8021-4da8-bb12-67891a57 aggregation: 'SUM', }, // 总计分组下,city 城市维度会出现分组 - totalsDimensionsGroup: ['city'], + totalsGroupDimensions: ['city'], // 小计维度下,type 类别维度下会出现分组 - subTotalsDimensionsGroup: ['type'], + subTotalsGroupDimensions: ['type'], }, }, }; From a44b134bf7072aab05b4c08ed645bb65de708d9f Mon Sep 17 00:00:00 2001 From: JuZe Date: Mon, 18 Sep 2023 18:25:01 +0800 Subject: [PATCH 39/39] =?UTF-8?q?chore:=20=E6=9B=B4=E6=94=B9=20interface?= =?UTF-8?q?=20=E5=91=BD=E5=90=8D=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-core/src/data-set/interface.ts | 2 +- packages/s2-core/src/data-set/pivot-data-set.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/s2-core/src/data-set/interface.ts b/packages/s2-core/src/data-set/interface.ts index 40f54ce91a..672766c8ef 100644 --- a/packages/s2-core/src/data-set/interface.ts +++ b/packages/s2-core/src/data-set/interface.ts @@ -51,7 +51,7 @@ export interface CellDataParams { totalStatus?: TotalStatus; } -export interface checkAccordQueryParams { +export interface CheckAccordQueryParams { // item of sortedDimensionValues,es: "浙江省[&]杭州市[&]家具[&]桌子" dimensionValues: string; query: DataType; 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 ee278c5b76..545d9eebf8 100644 --- a/packages/s2-core/src/data-set/pivot-data-set.ts +++ b/packages/s2-core/src/data-set/pivot-data-set.ts @@ -63,7 +63,7 @@ import type { CellMeta } from '../common'; import { BaseDataSet } from './base-data-set'; import type { CellDataParams, - checkAccordQueryParams, + CheckAccordQueryParams, DataType, PivotMeta, SortedDimensionValues, @@ -548,7 +548,7 @@ export class PivotDataSet extends BaseDataSet { * DimensionValue: 浙江省[&]杭州市[&]家具[&]桌子 => true * DimensionValue: 四川省[&]成都市[&]文具[&]笔 => false */ - checkAccordQueryWithDimensionValue(params: checkAccordQueryParams): boolean { + checkAccordQueryWithDimensionValue(params: CheckAccordQueryParams): boolean { const { dimensionValues, query, dimensions, field } = params; for (const [index, dimension] of dimensions.entries()) { const queryValue = get(query, dimension);