import { AbstractTreeNode, ArtColumn, ArtColumnMergePath } from "../interfaces"; import { pathIndexMetaSymbol, protoMetaSymbol } from "./makeRecursiveMapper"; export const groupMetaSymbol = Symbol("groupMetaSymbol"); export const groupLevelMetaSymbol = Symbol("groupLevelMetaSymbol"); export const groupColumnNameMetaSymbol = Symbol("groupColumnNameMetaSymbol"); function groupBy(array: T[], key: string) { const newList: Array = []; const keyMap: Map = new Map([]); for (let index = 0; index < array.length; index++) { const itemData = array[index]; const value = itemData[key]; if (keyMap.has(value)) { const ind = keyMap.get(value); newList[ind].push(itemData); } else { const length = newList.length; keyMap.set(value, length); newList[length] = [itemData]; } } return newList; } const getValue = (value) => { if (typeof value === "string") { return value; } if (typeof value === "number") { return value.toString(); } if (typeof value === "boolean") { return value.toString(); } if (value === undefined) { return `${undefined}`; } if (value === null) { return `${null}`; } return value; }; /** 对树状结构的数据进行分组. * layeredGroup 是一个递归的过程, * */ export function layeredGroup( array: T[], oldGroup: ArtColumn[], primaryKey: string | ((row: any) => string), parentKey: string = "", level: number = 0, parentObj = {} ): T[] { const group = [...oldGroup]; // 每次取第一个进行分组,剩余的进行二次循环 const firstGroupItem = group.shift(); if (firstGroupItem) { const enumData = firstGroupItem.enumData; const newParentKey = parentKey ? parentKey + "_" + firstGroupItem.code : firstGroupItem.code; const groupData = groupBy(array, firstGroupItem.code); const lg = groupData.length; const newArray: T[] = []; for (let index = 0; index < lg; index++) { const itemList = groupData[index]; const groupItemList = (itemList || []).map((item: T) => { return { ...item }; }); const value = groupItemList[0][firstGroupItem.code]; let textValue = getValue(value); if (enumData[textValue]) { textValue = enumData[textValue]; } const rowKey = typeof primaryKey === "function" ? primaryKey(groupItemList[0]) : primaryKey; const valueKey = groupItemList[0][rowKey]; if (group.length) { const list = layeredGroup( groupItemList, group, primaryKey, newParentKey, level + 1, { ...parentObj, [firstGroupItem.code]: value } ); const newKeys = valueKey + "_" + textValue + "_" + newParentKey + "_" + level; newArray.push({ ...parentObj, children: list, groupTitle: textValue, [firstGroupItem.code]: value, [rowKey]: newKeys, [groupLevelMetaSymbol]: level, __groupLevelMetaSymbol: level, [groupMetaSymbol]: true, __groupMetaSymbol: true, [groupColumnNameMetaSymbol]: firstGroupItem.name, __groupColumnNameMetaSymbol: firstGroupItem.name, } as undefined as T); } else { const newKeys = valueKey + "_" + textValue + "_" + newParentKey + "_" + level; newArray.push({ ...parentObj, children: groupItemList, groupTitle: textValue, [firstGroupItem.code]: value, [rowKey]: newKeys, [groupLevelMetaSymbol]: level, __groupLevelMetaSymbol: level, [groupMetaSymbol]: true, __groupMetaSymbol: true, [groupColumnNameMetaSymbol]: firstGroupItem.name, __groupColumnNameMetaSymbol: firstGroupItem.name, } as undefined as T); } } return newArray; } return array; } /** 对树状结构的数据进行分组. * layeredGroup 是一个递归的过程, * */ export function layeredGroup2( array: T[], oldGroup: ArtColumn[], primaryKey: string | ((row: any) => string) ): T[] { const newListData = []; const loop = ( array: T[], oldGroup: ArtColumn[], primaryKey: string | ((row: any) => string), parentKey: string = "", level: number = 0, parentObj = {} ) => { const group = [...oldGroup]; // 每次取第一个进行分组,剩余的进行二次循环 const firstGroupItem = group.shift(); if (firstGroupItem) { const enumData = firstGroupItem.enumData; const newParentKey = parentKey ? parentKey + "_" + firstGroupItem.code : firstGroupItem.code; const groupData = groupBy(array, firstGroupItem.code); const lg = groupData.length; const newArray: T[] = []; for (let index = 0; index < lg; index++) { const itemList = groupData[index]; const groupItemList = (itemList || []).map((item: T) => { return { ...item }; }); const value = groupItemList[0][firstGroupItem.code]; let textValue = getValue(value); if (enumData[textValue]) { textValue = enumData[textValue]; } const rowKey = typeof primaryKey === "function" ? primaryKey(groupItemList[0]) : primaryKey; const valueKey = groupItemList[0][rowKey]; if (group.length) { const newKeys = valueKey + "_" + textValue + "_" + newParentKey + "_" + level; const newItem = { ...parentObj, groupTitle: textValue, [firstGroupItem.code]: value, [rowKey]: newKeys, __groupLevelMetaSymbol: level, __groupMetaSymbol: true, __groupColumnNameMetaSymbol: firstGroupItem.name, } as unknown as T; newListData.push(newItem); newArray.push(newItem); const list = loop( groupItemList, group, primaryKey, newParentKey, level + 1, { ...parentObj, [firstGroupItem.code]: value } ); newItem.children = list; } else { const newKeys = valueKey + "_" + textValue + "_" + newParentKey + "_" + level; const newItem = { ...parentObj, children: groupItemList, groupTitle: textValue, [firstGroupItem.code]: value, [rowKey]: newKeys, __groupLevelMetaSymbol: level, __groupMetaSymbol: true, __groupColumnNameMetaSymbol: firstGroupItem.name, } as undefined as T; newArray.push(newItem); newListData.push(newItem); newListData.push(...groupItemList); } } return newArray; } }; loop(array, oldGroup, primaryKey); return newListData; } export class GroupUtils { static groupMetaSymbol = groupMetaSymbol; static groupLevelMetaSymbol = groupLevelMetaSymbol; static protoMetaSymbol = protoMetaSymbol; static pathIndexMetaSymbol = pathIndexMetaSymbol; static groupColumnNameMetaSymbol = groupColumnNameMetaSymbol; /**分组数据(转换成二维数组)*/ static groupBy = groupBy; /**设置分组下标*/ static setGroupIndex = ( columns: T[] ): T[] => { return columns.map((ite, groupIndex) => { if (ite?.[protoMetaSymbol]) { ite[protoMetaSymbol].groupIndex = groupIndex; } return { ...ite, groupIndex }; }); }; /**移除分组下标*/ static removeGroupIndex = ( columns: T[] ): T[] => { return columns.map((ite) => { const { groupIndex, ...rest } = ite; if (ite?.[protoMetaSymbol]) { delete ite[protoMetaSymbol].groupIndex; } return { ...rest }; }) as T[]; }; /**一个数组中进行移动数据*/ static replaceColumns = ( columns: ArtColumnMergePath[], startPath: string, movePath: string ) => { /**移动的数据下标*/ /**需要移动的数据下标*/ const startColumn = columns.find( (column) => column[pathIndexMetaSymbol] === startPath ); const moveIndex = columns.findIndex( (column) => column[pathIndexMetaSymbol] === movePath ); const newColumns = columns.filter( (column) => column[pathIndexMetaSymbol] !== startPath ); if (moveIndex === 0) { newColumns.unshift(startColumn); } else if (moveIndex === columns.length - 1) { newColumns.push(startColumn); } else { newColumns.splice(moveIndex, 0, startColumn); } return [...newColumns]; }; /**两个个数组中进行移动数据*/ static replaceColumns2 = ( startColumns: ArtColumnMergePath[], moveColumns: ArtColumnMergePath[], startPath: string, movePath: string, isAdd1: boolean ) => { const startColumn = startColumns.find( (column) => column[pathIndexMetaSymbol] === startPath ); const moveIndex = moveColumns.findIndex( (column) => column[pathIndexMetaSymbol] === movePath ); const newStartColumns = startColumns.filter( (column) => column[pathIndexMetaSymbol] !== startPath ); const newMoveColumns = [...moveColumns]; if (isAdd1) { newMoveColumns.splice(moveIndex + 1, 0, startColumn); } else { newMoveColumns.splice(moveIndex, 0, startColumn); } return { moveColumns: [...newMoveColumns], startColumns: [...newStartColumns], }; }; }