diff --git a/.changeset/spotty-meals-jump.md b/.changeset/spotty-meals-jump.md new file mode 100644 index 000000000..0e5e5e4a8 --- /dev/null +++ b/.changeset/spotty-meals-jump.md @@ -0,0 +1,5 @@ +--- +"@hera/plugin-rental": patch +--- + +树形结构筛选 diff --git a/packages/core/actions/src/actions/list.ts b/packages/core/actions/src/actions/list.ts index 0f2054f61..498416e5d 100644 --- a/packages/core/actions/src/actions/list.ts +++ b/packages/core/actions/src/actions/list.ts @@ -2,6 +2,7 @@ import { assign } from '@nocobase/utils'; import { Context } from '..'; import { getRepositoryFromParams, pageArgsToLimitArgs } from '../utils'; import { DEFAULT_PAGE, DEFAULT_PER_PAGE } from '../constants'; +import { QueryTypes } from 'sequelize'; function totalPage(total, pageSize): number { return Math.ceil(total / pageSize); @@ -28,7 +29,8 @@ async function listWithPagination(ctx: Context) { const { page = DEFAULT_PAGE, pageSize = DEFAULT_PER_PAGE } = ctx.action.params; const repository = getRepositoryFromParams(ctx); - + const resourceName = ctx.action.resourceName; + const collection = ctx.db.getCollection(resourceName); const options = { context: ctx, ...findArgs(ctx), @@ -40,12 +42,89 @@ async function listWithPagination(ctx: Context) { delete options[key]; } }); + let filterTreeData = []; + if (ctx.action.params.tree) { + const foreignKey = collection.treeParentField?.foreignKey || 'parentId'; + const params = Object.values(options.filter).flat()[0] || {}; + let dataId: any; + if (Object.entries(params).length) { + const getParent = async (filter = {}) => { + const data = await repository.findOne({ + filter: filter, + }); + dataId = data.id; + }; + await getParent(params); + const filterTreeDatas = await ctx.db.sequelize.query( + ` + WITH RECURSIVE tree1 AS ( + SELECT * + FROM ${collection.name} + WHERE id = :dataId + UNION ALL + + SELECT p.* + FROM tree1 up + JOIN ${collection.name} p ON up."${foreignKey}" = p.id + ), + tree2 AS ( + SELECT * + FROM ${collection.name} + WHERE id = :dataId + + UNION ALL + + SELECT p.* + FROM tree2 down + JOIN ${collection.name} p ON down.id = p."${foreignKey}" + ) + SELECT DISTINCT * + FROM ( + SELECT * + FROM tree1 + UNION ALL + SELECT * + FROM tree2 + ) + `, + { + replacements: { + dataId, + }, + type: QueryTypes.SELECT, + }, + ); + const newRows: any[] = filterTreeDatas; + const father = newRows.filter((parent) => parent.parentId === null); + + const transTreeData = (father, allRows) => { + father.forEach((parent, index) => { + const children = allRows.filter((child) => child.parentId === parent.id); + const i = index.toString(); + parent.__index = parent.father || parent.father == '0' ? parent.father + '.children.' + i : i; + if (children?.length) { + const transChild = children.map((child) => { + return { + ...child, + father: parent.__index, + }; + }); + parent.children = transChild; + } + if (parent.children?.length) { + transTreeData(parent.children, allRows); + } + }); + }; + transTreeData(father, newRows); + filterTreeData = father; + } + } const [rows, count] = await repository.findAndCount(options); - ctx.body = { count, - rows, + rows: filterTreeData.length ? filterTreeData : rows, page: Number(page), pageSize: Number(pageSize), totalPage: totalPage(count, pageSize),