From 172c49816e63f41753ae4fd1d82920104983d23f Mon Sep 17 00:00:00 2001 From: wc24 Date: Tue, 30 Jun 2026 16:01:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(filter):=20=E5=B5=8C=E5=A5=97=20filterable?= =?UTF-8?q?=20=E5=8F=B6=E5=AD=90=20=E2=86=92=20=E7=82=B9=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E8=BF=87=E6=BB=A4(object/tab)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit collectFilterablePaths 递归收集标了 filterable 的字段(object 子/tab 分支子)连同点路径; buildQuery 白名单从顶层字段扩成路径(点路径本就是 mongoose 嵌套查询,翻译逻辑不变)。 array 下钻、tab 判别值过滤留后续。 --- package-lock.json | 12 ++++++------ package.json | 4 ++-- src/Shrimp/ShrimpTableModule.ts | 17 ++++++++++++++++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index c052929..75b423f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,14 @@ { "name": "shrimp-server", - "version": "0.7.3", + "version": "0.7.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "shrimp-server", - "version": "0.7.3", + "version": "0.7.4", "dependencies": { - "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.3" + "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.4" }, "devDependencies": { "@types/bcrypt": "^5.0.0", @@ -3374,10 +3374,10 @@ } }, "node_modules/shrimp-server": { - "version": "0.7.3", - "resolved": "git+http://git.zeromvc.com/wc24/shrimp-server.git#24afc42de98f3fc5cebd178cd83707b7cde4da47", + "version": "0.7.4", + "resolved": "git+http://git.zeromvc.com/wc24/shrimp-server.git#a8cd07f8511487186732dfd884121f7acb77f5c0", "dependencies": { - "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.2" + "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.3" }, "peerDependencies": { "bcrypt": "^5 || ^6", diff --git a/package.json b/package.json index c1e9cf9..5b17b99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shrimp-server", - "version": "0.7.4", + "version": "0.7.5", "description": "Shrimp 框架后端 — 声明式字段驱动的 Node.js 管理后台框架(Express + Mongoose + JWT)", "main": "dist/main/index.js", "types": "dist/main/index.d.ts", @@ -57,6 +57,6 @@ "vitest": "^1.4.0" }, "dependencies": { - "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.3" + "shrimp-server": "git+http://git.zeromvc.com/wc24/shrimp-server.git#v0.7.4" } } diff --git a/src/Shrimp/ShrimpTableModule.ts b/src/Shrimp/ShrimpTableModule.ts index a8e8d6f..0f53dc9 100644 --- a/src/Shrimp/ShrimpTableModule.ts +++ b/src/Shrimp/ShrimpTableModule.ts @@ -297,6 +297,19 @@ export class ShrimpTableModule = ITableCrudProto return this.excludeKeys(item, ["__v", ...this.fields.filter(f => f.hidden).map(f => f.key)]) } + /** 递归收集标了 filterable 的字段 → 点路径(object 子 / tab 分支子)。array 暂不下钻(后续) */ + private collectFilterablePaths(fields: IFieldConfig[], base: string[], out: Map): void { + for (const f of fields) { + const path = [...base, f.key] + if (f.filterable) out.set(path.join("."), f) + if (f.type === ShrimpFieldTypes.Tab && Array.isArray(f.tabs)) { + for (const t of f.tabs) this.collectFilterablePaths(t.fields, path, out) + } else if (f.type === ShrimpFieldTypes.Object && Array.isArray(f.fields)) { + this.collectFilterablePaths(f.fields, path, out) + } + } + } + private buildQuery(query?: IPageQuery & any): IShrimpQuery { const { keyword, page, pageSize, sortBy, sortOrder, filter, ownerId } = query || {} const p = page || 1 @@ -307,7 +320,9 @@ export class ShrimpTableModule = ITableCrudProto } if (filter && typeof filter === 'object') { - const filterableFields = new Map(this.fields.filter(f => f.filterable).map(f => [f.key, f])) + // filterable 路径(含 object/tab 嵌套叶子,点路径如 condition.level)→ 白名单。点路径本就是 mongoose 嵌套查询,翻译逻辑不变 + const filterableFields = new Map() + this.collectFilterablePaths(this.fields, [], filterableFields) const stringLikeTypes = new Set(['string', 'textarea']) const where: Record = {} for (const [key, value] of Object.entries(filter)) {