From e789f8a1f7ea313c372d182389176a4906a3cb06 Mon Sep 17 00:00:00 2001 From: wc24 Date: Tue, 30 Jun 2026 16:01:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(filter):=20filterableFields=20=E9=80=92?= =?UTF-8?q?=E5=BD=92=E6=94=B6=E9=9B=86=E5=B5=8C=E5=A5=97=20filterable?= =?UTF-8?q?=EF=BC=8Ckey=3D=E7=82=B9=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ShrimpTable 把 filterableFields 从'顶层 filter'改成'递归收集 object/tab 嵌套叶子', 生成 key=点路径的合成字段。抽屉/buildFilter/URL 同步全按 field.key 走即可,无需改。 版本与 shrimp-server 对齐 0.7.5。 --- package.json | 2 +- src/components/ShrimpTable.vue | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e95f43d..fa63551 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shrimp-admin", - "version": "0.7.1", + "version": "0.7.5", "private": true, "description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现", "main": "src/index.ts", diff --git a/src/components/ShrimpTable.vue b/src/components/ShrimpTable.vue index 3f896e1..ee77fec 100644 --- a/src/components/ShrimpTable.vue +++ b/src/components/ShrimpTable.vue @@ -212,9 +212,24 @@ const formFields = computed(() => { return list.filter(f => f.editable !== 'readonly') }) const searchableFields = computed(() => fields.value.filter(f => f.searchable)) +// 递归收集 filterable 字段(含 object/tab 嵌套叶子),生成 key=点路径的"合成字段"。 +// 这样筛选抽屉/buildFilter/URL 同步全按 field.key 走即可——key 就是 condition.level 这种路径。 +function collectFilterablePaths(list: IFieldConfig[], base: string[], out: any[]) { + for (const f of list) { + const path = [...base, f.key] + if (f.filterable) out.push({ ...f, key: path.join('.') }) + if (f.type === 'tab' && Array.isArray((f as any).tabs)) { + for (const t of (f as any).tabs) collectFilterablePaths(t.fields, path, out) + } else if (f.type === 'object' && Array.isArray((f as any).fields)) { + collectFilterablePaths((f as any).fields, path, out) + } + } +} const filterableFields = computed(() => { const lockedKeys = new Set(Object.keys(props.baseFilter || {})) - return fields.value.filter(f => f.filterable && !lockedKeys.has(f.key)) + const out: any[] = [] + collectFilterablePaths(fields.value, [], out) + return out.filter(f => !lockedKeys.has(f.key)) }) const formSlotNames = computed(() => Object.keys(slots).filter(name => name.startsWith('form-')))