From 2a05e60504d5c64717251cb4c3ad03b4934ff0e5 Mon Sep 17 00:00:00 2001 From: chenos Date: Sun, 16 Apr 2023 16:56:35 +0800 Subject: [PATCH] fix: data template filter --- .../DataTemplates/hooks/useCollectionState.ts | 4 +- .../server/src/middlewares/data-template.ts | 66 ++++++++++++++----- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts b/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts index aa7450c53..e189fa19b 100644 --- a/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts +++ b/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts @@ -76,13 +76,15 @@ export const useCollectionState = (currentCollectionName: string) => { tag: compile(field.uiSchema?.title) || field.name, }; const option = { + ...node, title: React.createElement(TreeNode, node), key: prefix ? `${prefix}.${field.name}` : field.name, }; // 多对多的只展示关系字段 if (['belongsTo', 'belongsToMany'].includes(field.type)) { + node['type'] = 'reference'; option['type'] = 'reference'; - option['label'] = React.createElement(TreeNode, { ...node, type: 'reference' }); + option['title'] = React.createElement(TreeNode, { ...node, type: 'reference' }); option['children'] = traverseAssociations(field.target, { depth: depth + 1, maxDepth, diff --git a/packages/core/server/src/middlewares/data-template.ts b/packages/core/server/src/middlewares/data-template.ts index 0c91c1a24..0a4652ce5 100644 --- a/packages/core/server/src/middlewares/data-template.ts +++ b/packages/core/server/src/middlewares/data-template.ts @@ -8,24 +8,34 @@ export const dateTemplate = async (ctx: Context, next) => { await next(); if (isTemplate && actionName === 'get' && fields.length > 0) { - ctx.body = traverseJSON(ctx.body?.toJSON(), ctx.db.getCollection(resourceName)); + ctx.body = traverseJSON(ctx.body?.toJSON(), { + collection: ctx.db.getCollection(resourceName), + include: fields, + }); } }; -const traverseHasMany = (arr: any[], collection: Collection, exclude = []) => { +type TraverseOptions = { + collection: Collection; + exclude?: string[]; + include?: string[]; + through?: string; +}; + +const traverseHasMany = (arr: any[], { collection, exclude = [], include = [] }: TraverseOptions) => { if (!arr) { return arr; } - return arr.map((item) => traverseJSON(item, collection, exclude)); + return arr.map((item) => traverseJSON(item, { collection, exclude, include })); }; -const traverseBelongsToMany = (arr: any[], collection: Collection, exclude = [], through) => { +const traverseBelongsToMany = (arr: any[], { collection, exclude = [], through }: TraverseOptions) => { if (!arr) { return arr; } const throughCollection = collection.db.getCollection(through); return arr.map((item) => { - const data = traverseJSON(item[through], throughCollection, exclude); + const data = traverseJSON(item[through], { collection: throughCollection, exclude }); if (Object.keys(data).length) { item[through] = data; } else { @@ -35,9 +45,28 @@ const traverseBelongsToMany = (arr: any[], collection: Collection, exclude = [], }); }; -const traverseJSON = (data, collection: Collection, exclude = []) => { +const parseInclude = (keys: string[]) => { + const map = {}; + for (const key of keys) { + const args = key.split('.'); + const field = args.shift(); + map[field] = map[field] || []; + if (args.length) { + map[field].push(args.join('.')); + } + } + return map; +}; + +const traverseJSON = (data, options: TraverseOptions) => { + const { collection, exclude = [], include = [] } = options; + const map = parseInclude(include); const result = {}; for (const key of Object.keys(data)) { + const subInclude = map[key]; + if (include.length > 0 && !subInclude) { + continue; + } if (exclude.includes(key)) { continue; } @@ -52,22 +81,29 @@ const traverseJSON = (data, collection: Collection, exclude = []) => { if (field.options.primaryKey) { continue; } - if (field.type === 'sort') { + if (['sort', 'password', 'sequence'].includes(field.type)) { continue; } if (field.type === 'hasOne') { - result[key] = traverseJSON(data[key], collection.db.getCollection(field.target), [field.foreignKey]); + result[key] = traverseJSON(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey], + include: subInclude, + }); } else if (field.type === 'hasMany') { - result[key] = traverseHasMany(data[key], collection.db.getCollection(field.target), [field.foreignKey]); + result[key] = traverseHasMany(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey], + include: subInclude, + }); } else if (field.type === 'belongsTo') { result[key] = data[key]; } else if (field.type === 'belongsToMany') { - result[key] = traverseBelongsToMany( - data[key], - collection.db.getCollection(field.target), - [field.foreignKey, field.otherKey], - field.through, - ); + result[key] = traverseBelongsToMany(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey, field.otherKey], + through: field.through, + }); } else { result[key] = data[key]; }