发现于 #4781 的实施,回传立单。与 #4768 / #4781 同一症状家族(控件显示空、行却带着看不见的值),但成因不同:这里不是切换字段,而是渲染值控件时把「假值」当成了「没填」。 ## 事实 `packages/components/src/custom/filter-builder.tsx`(origin/main `65e88e6`,`renderValueInput` 内): - 默认值输入框的 `formatValue()` 头一句是 `if (!condition.value) return ""`。数字 `0` 是假值,于是 `equals 0` 的行输入框显示空白。用户在数字列里敲 `0` 更直观:`handleValueChange("0")` 把值写成数字 `0`,重新渲染时输入框立刻清空,看起来像根本没输进去。 - 布尔列的值控件用 `value={String(condition.value || "")}`。`false || ""` 是 `""`,于是用户选完 **False**,trigger 立刻退回 placeholder「Select value」,而行里 `value: false` 正常保存并持久化。 ## 实测(jsdom,`@object-ui/components`) | 行 | 控件显示 | 行实际带着 | | --- | --- | --- | | 布尔列 `{operator:'equals', value:false}` | `Select value`(placeholder) | `false` | | 数字列 `{operator:'equals', value:0}` | 空字符串 | `0` | 两条都是用户可直接触达的:选一个布尔列 → 点 **False**;或在数字列输入 `0`。 ## 为什么值得单独修 `0` 和 `false` 是完全合法、用户明确选择的筛选值,`''` 才是「没填」。#4744 已经在 operator 一侧把「值为空的行算不算完成态」定过一次;这是 value 一侧的同一个问题,而 #4781 的类型重整刻意不碰它(那边答的是「新列装不装得下这个值」,这里的值本来就属于该列)。 修的时候要注意两点:判定要写成 `value === "" || value == null` 而不是 `!value`;布尔控件还得能同时表达「未选」和「选了 False」两种状态,否则换个写法就把坑挪个位置。 ## 参考 - #4768 / #4781(同一症状家族,不同成因) - #4744(值为空的行的完成态,operator 一侧)
Activity
yinlianghui commentedon Aug 17, 2026
【分诊晋级 + 认领】objectui 分片 PM(session_01GTRjn8xBqp75dk7kFupVRt)批次 15 派发,os-dev 实施,与 #4875 同批同 PR(同文件同族:filter-builder.tsx 的宽松读数)。分支:
claude/issue-4873-filter-falsy-values。晋级理由:成因已定位(
!condition.value与String(value || '')把布尔 false / 数字 0 当空),用户直接可触达,修法机械(空判定改== null族语义);#4875 的三处parseFloat(raw) || 0与本卡同文件同族,PR4876 刚在同文件立了严格判定convertScalarToFamily,两份口径并存正是收敛时机 —— 合单防撞车。文件面:packages/components/src/custom/filter-builder.tsx+ 测试(基最新 main,PR4876 已落)。与在飞零交集。Generated by Claude Code
fix(components): FilterBuilder 值控件按「无值」而非「假值」判空,三处键入数值读数收敛到严格判定 (#4873,
fix(components): FilterBuilder 值控件按「无值」而非「假值」判空,三处键入数值读数收敛到严格判定 (obje…