Files
fe.ems.vue3/src/utils/parse-tree-utils.ts
2023-09-18 12:03:20 +08:00

224 lines
5.6 KiB
TypeScript

/**
* 解析数据层级转树结构
*
* @param data 数组数据
* @param fieldId 读取节点字段 默认 'id'
* @param fieldParentId 读取节点父节点字段 默认 'parentId'
* @param fieldChildren 设置子节点字段 默认 'children'
* @returns 层级数组
*/
export function parseDataToTree(
data: Record<string, any>[],
fieldId: string = 'id',
fieldParentId: string = 'parentId',
fieldChildren: string = 'children'
) {
// 节点分组
let map: Map<string, Record<string, any>[]> = new Map();
// 节点id
let treeIds: string[] = [];
// 树节点
let tree: Record<string, any>[] = [];
for (const item of data) {
let parentId = item[fieldParentId];
// 分组
let mapItem = map.get(parentId) ?? [];
mapItem.push(item);
map.set(parentId, mapItem);
// 记录节点id
treeIds.push(item[fieldId]);
}
for (const [key, value] of map) {
// 选择不是节点id的作为树节点
if (!treeIds.includes(key)) {
tree.push(...value);
}
}
for (const iterator of tree) {
componet(iterator);
}
/**闭包递归函数 */
function componet(iterator: Record<string, any>) {
let id = iterator[fieldId];
let item = map.get(id);
if (item) {
iterator[fieldChildren] = item;
}
if (iterator[fieldChildren]) {
for (let i of iterator[fieldChildren]) {
componet(i);
}
}
}
return tree;
}
/**
* 解析数据层级转树结构-排除节点
*
* @param data 数组数据
* @param excludeField 排除节点字段 默认 'type'
* @param excludeValue 排除节点值 默认 '0'
* @param fieldId 读取节点字段 默认 'id'
* @param fieldParentId 读取节点父节点字段 默认 'parentId'
* @param fieldChildren 设置子节点字段 默认 'children'
* @returns 层级数组
*/
export function parseDataToTreeExclude(
data: Record<string, any>[],
excludeField = 'type',
excludeValue = '0',
fieldId: string = 'id',
fieldParentId: string = 'parentId',
fieldChildren: string = 'children'
) {
// 节点分组
let map: Map<string, Record<string, any>[]> = new Map();
// 节点id
let treeIds: string[] = [];
// 树节点
let tree: Record<string, any>[] = [];
for (const item of data) {
// 排除值跳过
let exclude = item[excludeField];
if (exclude && exclude === excludeValue) {
continue;
}
let parentId = item[fieldParentId];
// 分组
let mapItem = map.get(parentId) ?? [];
mapItem.push(item);
map.set(parentId, mapItem);
// 记录节点id
treeIds.push(item[fieldId]);
}
for (const [key, value] of map) {
// 选择不是节点id的作为树节点
if (!treeIds.includes(key)) {
tree.push(...value);
}
}
for (const iterator of tree) {
componet(iterator);
}
/**闭包递归函数 */
function componet(iterator: Record<string, any>) {
let id = iterator[fieldId];
let item = map.get(id);
if (item) {
iterator[fieldChildren] = item;
}
if (iterator[fieldChildren]) {
for (let i of iterator[fieldChildren]) {
componet(i);
}
}
}
return tree;
}
/**
* 解析树结构数据转出一维id数组
*
* @param data 数组数据
* @param fieldId 读取节点字段 默认 'id'
* @param fieldChildren 读取子节点字段 默认 'children'
* @returns 层级数组
*/
export function parseTreeKeys(
data: Record<string, any>[],
fieldId: string = 'id',
fieldChildren: string = 'children'
) {
// 节点id
let treeIds: string[] | number[] = [];
componet(data);
/**闭包递归函数 */
function componet(data: Record<string, any>[]) {
if (data.length <= 0) return;
for (const iterator of data) {
let id = iterator[fieldId];
if (id) {
treeIds.push(id as never);
}
if (Array.isArray(iterator[fieldChildren])) {
componet(iterator[fieldChildren]);
}
}
}
return treeIds;
}
/**
* 解析树结构数据转出含子节点的一维id数组
*
* @param data 数组数据
* @param fieldId 读取节点字段 默认 'id'
* @param fieldChildren 读取子节点字段 默认 'children'
* @returns 层级数组
*/
export function parseTreeNodeKeys(
data: Record<string, any>[],
fieldId: string = 'id',
fieldChildren: string = 'children'
) {
// 节点id
let treeIds: string[] | number[] = [];
componet(data);
/**闭包递归函数 */
function componet(data: Record<string, any>[]) {
if (data.length <= 0) return;
for (const iterator of data) {
let nodes = iterator[fieldChildren];
if (Array.isArray(nodes) && nodes.length > 0) {
treeIds.push(iterator[fieldId] as never);
componet(iterator[fieldChildren]);
}
}
}
return treeIds;
}
/**
* 解析数据层级转级联options树结构
*
* @param data 数组数据
* @param fieldType 读取节点label字段 默认 'type'
* @param fieldLabel 读取节点label字段 默认 'name'
* @param fieldValue 读取节点value字段 默认 'value'
* @param fieldChildren 设置子节点字段 默认 'children'
* @returns 层级数组
*/
export function parseDataToOptions(
data: Record<string, any>[],
fieldType: string = 'type',
fieldLabel: string = 'label',
fieldValue: string = 'value',
fieldChildren: string = 'children'
) {
let options: Record<string, any>[] = [];
for (const v of data) {
let vType = v[fieldType];
let vLabel = v[fieldLabel];
let vValue = v[fieldValue];
const vData = { label: vLabel, value: vValue, ...v };
const item = options.find(i => i.value === vType);
if (item) {
item[fieldChildren].push(vData);
} else {
options.push({ label: vType, value: vType, [fieldChildren]: [vData] });
}
}
return options;
}