Uh oh!
There was an error while loading. Please reload this page.
fix(components): FilterBuilder 切换 field 时把算子归到新桶内 (#4768) - #4779
Merged
Conversation
算子桶按字段类型划分且互不包含(select 有 in/notIn,text 没有;between
只有日期桶有)。切换一行的 field 只写 { field },算子就留在了新桶没有的
位置——Radix 的 SelectValue 拿实际挂载的 SelectItem 匹配,于是 trigger
渲染成空白,用户看不见也点不到自己正在用的算子。
现在把「改字段」和「定算子、定 value 形状」合成一次编辑,与 #3958 /
PR #4762 在算子侧的机制同形:新桶仍提供的算子予以保留(value 一并不动),
新桶不提供的换成该桶首项并按新家族重整 value。归属判断走 spec 自己的
normalizeFilterOperator,所以存量视图读回的 not_in 会被认成下拉里列的
notIn,不会被无谓重置;该折叠在本组件的 22 个算子 id 上是单射的,测试
把这条性质一并钉住。
Co-authored-by: Claude <noreply@anthropic.com>The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
commented
Aug 16, 2026
CollaboratorAuthor
PM 验收(座位 核验记录(实物核验 + CI 亲读):
out-of-scope #4781(field 切换后 value 残留的三选项语义)已入决策箱 —— dev 对「这是产品语义不是契约机械」的判断被 PM 采纳,倾向 B 的论证在卡上待维护者拍板。 Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 16, 2026 06:10
Uh oh!
There was an error while loading. Please reload this page.
akarma-synetal pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 17, 2026
…bjectstack-ai#4781) (objectstack-ai#4876) * fix(components): FilterBuilder 切换 field 时按新列类型重整 value —— 可转则转,不可转清空 (objectstack-ai#4781) 切换一行的 field 时,PR objectstack-ai#4779 只在算子家族变化时重整 value 的形状;标量到 标量没有形状问题,值被原样带过去。但字段的**类型**也换了,而值输入框正是 按新类型重绘的:`<input type="number">` 对非数字 value 一律显示为空。于是 text 列的 `equals "acme"` 指到 number 列后,输入框空白,行却仍带着 `"acme"` —— `foldFilterGroupToSpecRules` 原样持久化,实时网格拿 `amount equals "acme"` 去查。与 objectstack-ai#4768 同一形状的「看不见的值」,只是发生在 value 而不是 operator 上。 按维护者 2026-08-16 裁定(方案 B:能转则转、不能转才清): - convertibility 一处定义(`convertScalarToFamily`),与 `reshapeFilterValue` 的 carry-if-possible 语义并列;判定为**干净、无歧义**的读数,比 `parseFloat` 严格 —— 后者会把 `"acme"` 读成 `0`,写出用户从未写过的筛选; - number:`"42"` → `42`,`"42abc"` / `"1,000"` / `Infinity` 清空; - boolean:只认 `"true"` / `"false"`(两端可往返),`1` / `"yes"` 是约定不是 读数,清空; - date/datetime/time:只收目标输入框本身能渲染的值,外加唯一一处不丢信息的 截断(无时区时间戳 → 其日期)。裸日期不会被补上午夜去凑 datetime 列: `equals 2024-03-05T00:00` 是一条看起来已填、实则几乎匹配不到东西的规则; - 新列装得下的值原样保留(两个 text 列之间、两个数值列之间),空行仍是空行。 `getInputType` 改为读同一张 family 表,使「值被转换成的类型」与「值被编辑的 输入框」不可能各说各话 —— 二者不一致正是本单的病灶。 Co-authored-by: Claude <noreply@anthropic.com> * refactor(components): family→input 表改为模块私有,不进包的公共 API (objectstack-ai#4781) `FILTER_INPUT_TYPE_BY_FAMILY` 上一版标了「@internal exported for tests」, 但测试并不导入它 —— 输入框类型是从渲染出来的 DOM 上钉的,那本来就是更硬的 钉法。`packages/components/src/custom/index.ts` 是 `export *`,于是它白白进了 包的公共 API(连 `dist/*.d.ts` 都带上了)。没有消费方要求的东西不进契约。 Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#4768
问题
FilterBuilder的算子桶是按字段类型分的,且互不包含:select桶有in/notIn,text桶没有;between只有日期桶有。切换一行的 field 时组件只写{ field },算子原样留在了新桶里根本没有的位置——比如 select 改 text 之后行上仍是in。Radix 的
SelectValue是拿实际挂载的SelectItem去匹配的,桶里没有该项,trigger 就渲染成空白:用户既看不见也点不到自己正在用的算子,只能删掉整行重来;行本身还在按那个算子过滤。改动
把「改字段」和「定算子、定 value 形状」合成一次编辑,与 #3958 / PR #4762 在算子侧确立的机制同形(那边是「改算子」和「重整 value 形状」合成一次编辑):
contains从一个文本列换到另一个文本列不该悄悄变成equals;reshapeFilterValue按新算子的家族重整 value:in下的列表塌成首项标量,between的区间保留下界,未填过的[]变回''。归属判断走 spec 自己的
normalizeFilterOperator——正是filterValueArity已经在用的那次折叠。存量视图读回来可能拼成not_in,而下拉里列的是别名notIn,两者是同一个算子,不能因为拼写不同就把作者的算子重置掉。折叠在本组件的算子词表上是单射的(defaultOperators的 22 个 id 折叠出 22 个互异的规范算子),这才使「按规范拼写比较」是安全的;测试把这条单射性钉住,将来加入的算子一旦破坏它就会红。renderers/form未触碰(#4014 在飞)。反向验证(先预判、后执行、不提交)
预判:只把接线退回
updateCondition(condition.id, { field: value })(helper 不动),前两个 describe 的 9 个 UI 驱动钉转红,「新桶仍提供则不重置」整个 describe 与全部纯函数钉保持绿——后者是防止修复过度(无条件重置会把它们弄红),不是「必须变化」的钉。实测与预判逐条一致:
红的正是预判的 9 条(4 条「切换后算子落回新桶」+ 4 条「value 按新家族重整」+ 1 条 #4762 家族衔接),PR #4762 自己那 24 条钉全绿。随后已还原修复。
验证
pnpm exec vitest run packages/components --maxWorkers=2→ 137 files / 1196 tests passedViewFilterRuleSchema整链(含 PR fix(components): FilterBuilder 为 in/not_in/between 渲染匹配形状的值输入,家族判定改读 spec 词表 (#3958) #4762 的viewFilterFold.builderSetOperators.test.tsx)→ 5 files / 59 tests passedturbo run type-check→ 81/81 successful;check:control-bytes、i18n 双闸、changeset 双闸、phantom-deps、spec-symbol、lint/type-check coverage 全绿.changeset/filter-builder-field-switch-resets-operator.md(patch)Generated by Claude Code