UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

255 lines 11.3 kB
import { isEmpty, isNumber } from 'lodash'; import { EMPTY_FIELD_VALUE, EXTRA_FIELD } from '../../common/constant'; import { i18n } from '../../common/i18n'; import { filterOutDetail } from '../../utils/data-set-operate'; import { addTotals } from '../../utils/layout/add-totals'; import { generateId, resolveNillString } from '../../utils/layout/generate-id'; import { getDimsCondition } from '../../utils/layout/get-dims-condition-by-node'; import { whetherLeafByLevel } from '../../utils/layout/whether-leaf-by-level'; import { layoutArrange, layoutHierarchy } from '../layout/layout-hooks'; import { Node } from '../layout/node'; import { TotalClass } from '../layout/total-class'; import { TotalMeasure } from '../layout/total-measure'; /** * 计算节点是否折叠 * 注意:真正的叶子节点(没有子节点)不应该有折叠状态 */ const calculateCollapsedState = (options) => { var _a, _b, _c, _d, _e; const { spreadsheet, nodeId, currentField, level, isTotals, isTotalMeasure, isLeaf, } = options; // 真正的叶子节点没有子节点,不应有折叠状态 if (isLeaf) { return false; } const { collapseFields, collapseAll, expandDepth } = (_b = (_a = spreadsheet.options.style) === null || _a === void 0 ? void 0 : _a.rowCell) !== null && _b !== void 0 ? _b : {}; const isDefaultCollapsed = (_c = collapseFields === null || collapseFields === void 0 ? void 0 : collapseFields[nodeId]) !== null && _c !== void 0 ? _c : collapseFields === null || collapseFields === void 0 ? void 0 : collapseFields[currentField]; const isLevelCollapsed = isNumber(expandDepth) ? level >= expandDepth : null; return isTotals || isTotalMeasure ? false : (_e = (_d = isDefaultCollapsed !== null && isDefaultCollapsed !== void 0 ? isDefaultCollapsed : isLevelCollapsed) !== null && _d !== void 0 ? _d : collapseAll) !== null && _e !== void 0 ? _e : false; }; /** * 处理字段值,返回节点的值、查询条件和各种标志 */ const processFieldValue = (options) => { var _a; const { fieldValue, currentField, query, parentNode, spreadsheet, level, fields, addMeasureInTotalQuery, } = options; const isTotals = TotalClass.isTotalClassInstance(fieldValue); const isTotalMeasure = TotalMeasure.isTotalMeasureInstance(fieldValue); let value; let nodeQuery; let isLeaf = false; let isGrandTotals = false; let isSubTotals = false; let isTotalRoot = false; if (isTotals) { isGrandTotals = fieldValue.isGrandTotals; isSubTotals = fieldValue.isSubTotals; isTotalRoot = fieldValue.isTotalRoot; value = i18n(fieldValue.label); nodeQuery = isTotalRoot ? Object.assign({}, query) : Object.assign(Object.assign({}, query), { [currentField]: value }); if (addMeasureInTotalQuery) { nodeQuery[EXTRA_FIELD] = (_a = spreadsheet === null || spreadsheet === void 0 ? void 0 : spreadsheet.dataSet) === null || _a === void 0 ? void 0 : _a.fields.values[0]; } isLeaf = whetherLeafByLevel({ spreadsheet, level, fields }); } else if (isTotalMeasure) { value = i18n(fieldValue.label); nodeQuery = Object.assign(Object.assign({}, query), { [EXTRA_FIELD]: value }); isGrandTotals = parentNode.isGrandTotals; isSubTotals = parentNode.isSubTotals; isLeaf = whetherLeafByLevel({ spreadsheet, level, fields }); } else { value = fieldValue; nodeQuery = value === EMPTY_FIELD_VALUE ? Object.assign({}, query) : Object.assign(Object.assign({}, query), { [currentField]: value }); isLeaf = whetherLeafByLevel({ spreadsheet, level, fields }); } return { value, nodeQuery, isLeaf, isGrandTotals, isSubTotals, isTotalRoot, isTotals, isTotalMeasure, }; }; /** * 生成 grid-tree 模式的行头节点 * 与 generateHeaderNodes 类似,但支持折叠状态 */ const generateGridTreeHeaderNodes = (params) => { var _a; const { currentField, fields, fieldValues, hierarchy, parentNode, level, query, addMeasureInTotalQuery, addTotalMeasureInTotal, spreadsheet, handler, } = params; for (const originalFieldValue of fieldValues) { const fieldValue = resolveNillString(originalFieldValue); const adjustedField = currentField; const processed = processFieldValue({ fieldValue, currentField, query, parentNode, spreadsheet, level, fields, addMeasureInTotalQuery, }); const nodeId = generateId(parentNode.id, processed.value); if (nodeId) { const isCollapsed = calculateCollapsedState({ spreadsheet, nodeId, currentField, level, isTotals: processed.isTotals, isTotalMeasure: processed.isTotalMeasure, isLeaf: processed.isLeaf, }); const node = new Node({ id: nodeId, value: processed.value, level, field: adjustedField, parent: parentNode, isTotals: processed.isTotals || processed.isTotalMeasure, isGrandTotals: processed.isGrandTotals, isSubTotals: processed.isSubTotals, isTotalMeasure: processed.isTotalMeasure, isCollapsed, isTotalRoot: processed.isTotalRoot, hierarchy, query: processed.nodeQuery, spreadsheet, isLeaf: processed.isLeaf || isCollapsed, }); const expandCurrentNode = layoutHierarchy(spreadsheet, parentNode, node, hierarchy); const hiddenColumnsInfo = (_a = spreadsheet === null || spreadsheet === void 0 ? void 0 : spreadsheet.facet) === null || _a === void 0 ? void 0 : _a.getHiddenColumnsInfo(node); if (level > hierarchy.maxLevel && !processed.isGrandTotals && !parentNode.isGrandTotals && !parentNode.isSubTotals && !node.isSubTotals && !hiddenColumnsInfo) { hierarchy.sampleNodesForAllLevels.push(node); hierarchy.maxLevel = level; hierarchy.sampleNodeForLastLevel = node; } // grid-tree 模式下,折叠的节点也是叶子节点 const isLeafNode = processed.isLeaf || isCollapsed || !expandCurrentNode; if (isLeafNode) { node.isLeaf = true; hierarchy.pushIndexNode(node); node.rowIndex = hierarchy.getIndexNodes().length - 1; } else { handler === null || handler === void 0 ? void 0 : handler({ addTotalMeasureInTotal, addMeasureInTotalQuery, parentNode: node, currentField: fields[level + 1], fields, hierarchy, spreadsheet, }); } } } }; const buildNormalGridTreeHierarchy = (params) => { const { parentNode, currentField, fields, spreadsheet } = params; const dataSet = spreadsheet.dataSet; const { values = [] } = dataSet.fields; const index = fields.indexOf(currentField); const fieldValues = []; let query = {}; query = getDimsCondition(parentNode, true); const dimValues = dataSet.getDimensionValues(currentField, query); const arrangedValues = layoutArrange(spreadsheet, dimValues, parentNode, currentField); fieldValues.push(...(arrangedValues || [])); if (isEmpty(fieldValues) && currentField) { if (currentField === EXTRA_FIELD) { fieldValues.push(...values); } else { fieldValues.push(EMPTY_FIELD_VALUE); } } addTotals({ currentField, lastField: fields[index - 1], isFirstField: index === 0, fieldValues, spreadsheet, }); const displayFieldValues = filterOutDetail(fieldValues); generateGridTreeHeaderNodes(Object.assign(Object.assign({}, params), { fieldValues: displayFieldValues, level: index, parentNode, query, // eslint-disable-next-line @typescript-eslint/no-use-before-define handler: buildGridTreeHierarchy })); }; const buildTotalGridTreeHierarchy = (params) => { const { addTotalMeasureInTotal, parentNode, currentField, fields, hierarchy, spreadsheet, } = params; const index = fields.indexOf(currentField); const dataSet = spreadsheet.dataSet; const { values = [] } = dataSet.fields; const fieldValues = []; let query = {}; const totalsConfig = spreadsheet.getTotalsConfig(currentField); const defaultDimensionGroup = parentNode.isGrandTotals ? totalsConfig.grandTotalsGroupDimensions || [] : totalsConfig.subTotalsGroupDimensions || []; const dimensionGroup = !dataSet.isEmpty() ? defaultDimensionGroup : []; if (dimensionGroup === null || dimensionGroup === void 0 ? void 0 : dimensionGroup.includes(currentField)) { query = getDimsCondition(parentNode); const dimValues = dataSet.getDimensionValues(currentField, query); fieldValues.push(...(dimValues || []).map((value) => new TotalClass({ label: value, isSubTotals: parentNode.isSubTotals, isGrandTotals: parentNode.isGrandTotals, isTotalRoot: false, }))); if (isEmpty(fieldValues) && currentField) { fieldValues.push(EMPTY_FIELD_VALUE); } } else if (addTotalMeasureInTotal && currentField === EXTRA_FIELD) { query = getDimsCondition(parentNode); fieldValues.push(...values.map((v) => new TotalMeasure(v))); } else if (whetherLeafByLevel({ spreadsheet, level: index, fields })) { parentNode.isLeaf = true; hierarchy.pushIndexNode(parentNode); parentNode.rowIndex = hierarchy.getIndexNodes().length - 1; return; } else { // eslint-disable-next-line @typescript-eslint/no-use-before-define buildTotalGridTreeHierarchy(Object.assign(Object.assign({}, params), { currentField: fields[index + 1] })); return; } const displayFieldValues = filterOutDetail(fieldValues); generateGridTreeHeaderNodes(Object.assign(Object.assign({}, params), { fieldValues: displayFieldValues, level: index, parentNode, query, // eslint-disable-next-line @typescript-eslint/no-use-before-define handler: buildGridTreeHierarchy })); }; /** * 构建 grid-tree 模式的行头层级结构 * grid-tree 模式特点: * 1. 每个维度占据独立的列(与 grid 模式相同) * 2. 支持展开/折叠子节点(与 tree 模式相同) */ export function buildGridTreeHierarchy(params) { if (params.parentNode.isTotals) { buildTotalGridTreeHierarchy(params); } else { buildNormalGridTreeHierarchy(params); } } //# sourceMappingURL=build-grid-tree-hierarchy.js.map