You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
长远合理性 —— 倾向「生效」。 那行原始比较是 bug 而不是刻意限制:同一段注释白纸黑字写着"gate the whole control while a declared dependsOn parent is still empty",意图从来就是通用的,只是字符串比较漏了带前缀的那一半。让它继续瘫痪,等于在 console 上长期维持一个"声明了却不兑现"的能力 —— 正是本仓反复在清的那种东西(#3232、#3236 都是同族)。而且 widget 侧本来就有自己的 useCascadingOptions,门控语义在 widget 内一直是生效的;渲染器这一侧不生效,反而是两侧不一致。
Activity
xuyushun441-sys commentedon Aug 3, 2026
认领:PM 循环第 2 轮
会话:
session_01NVPjPzmmAJ2Ngtvgg5MSRa(objectui 分片 PM,账号xuyushun441-sys,已在 objectstack#4604 登记)分支:
claude/issue-3231-empty-hint-single-sourceWorktree:
objectui-issue-3231决策裁定:走 A(PM 拍板,不上升维护者,可否决)
原单把 A/B 标为"需维护者定夺"。按 SKILL.md 的升级门槛,我判定不需要上升 —— 这是「declared ≠ delivered」的恢复不变量类,而且仓规已经把答案写死了。
A:widget 优先用宿主传来的
emptyHint,自有文案退化为兜底。按两条评估轴:
emptyHint已经被声明、被表单渲染器计算、被传输(form.tsx:1351),然后被四个 widget 解构后丢弃。B(把emptyHint从这条路径上撤掉、承认 widget 拥有文案)等于承认宿主无法影响提示,而form.tsx:1824的内建分支又确实在用它 —— 那会留下"内建分支宿主可覆盖、注册 widget 不可"的分裂语义,比现状更难解释。A 是一个生产者、一个消费者。TextAreaField读取的mobileFullscreenprop 全仓无人生产,注释却说"宿主表单传入" #3232 刚清掉的那种东西 —— 我不打算在同一天用另一单再造一份。A 之后,宿主传了就一定生效,没传才用兜底,行为可预测。两件必须一起做的事,否则本单白修
1. i18n 不是附带项。 原单点明四个 widget 的兜底文案是硬编码英文字面量(
'No options available'、`Select ${dependsOnFields.join(' / ')} first`),而useFieldTranslation()在同一个文件里已经可用。无论 A 还是 B,这条都得修 —— 兜底文案必须走翻译。只把emptyHint接上、兜底仍是硬编码英文,等于只修了一半。2. 必须有测试钉住。 原单说"任一方向都应有测试钉住,否则会再次静默漂移" —— 这条是硬要求。至少要覆盖:宿主传了
emptyHint时四个 widget 都显示它(不是自己的文案),没传时显示已翻译的兜底。四个 widget 都要覆盖,不能只测一个 —— 它们是四份独立的复制品,这正是它们能一起漂移的原因。复核记录
origin/main上确认:四个 widget(SelectField/MultiSelectField/RadioField/CheckboxesField)均为emptyHint: _emptyHint,形态解构后丢弃。解构本身是正当的(不解构会随...props铺到 DOM 上),问题只在解构之后没有使用 —— 修法是用它,不是别解构它。packages/fields。packages/components/src/renderers/form/form.tsx是emptyHint的生产者,读可以,改要有强理由并在报告里说明 —— 内建 select 分支(form.tsx:1824)是另一条独立活路径,不要顺手统一。Generated by Claude Code
xuyushun441-sys commentedon Aug 3, 2026
PM 验收:实现通过,但我没有合并 —— 需要维护者拍一个板
PR #3262 已从 draft 转为 ready for review,刻意没有入合并队列。这是本轮五单里唯一一个我不自行合并的。
代码质量核对(GitHub 实况):CI 14 绿 + 2 path-filter skipped,零失败;三处独立 mutation 验证(widget 忽略
emptyHint→ 20 红;stripRegisteredFieldProps停止转发 → 8 红;isOptionField退回原比较 → 5 红且恰好红在四个field:前缀用例上)。四个 widget 收敛到共享的OptionsEmptyState,十个语言包都补了fields.options.*,i18n 缺口修掉了。这些都对。为什么不合并:它顺带打开了一个此前从未生效的行为开关
开发 agent 诚实地把这条列进了"需要审查者看见"而不是埋掉 —— 我核对了源码,属实,而且比报告里说的更值得重视。
原单只说"四个 widget 把
emptyHint丢掉了"。实测这条链断了三处,而最靠前的一处不是丢弃,是根本没算:对象派生表单经
mapFieldTypeToFormType发出的是field:select这类带前缀的 id,一个都匹配不上 —— 也就是说在 console 的常规路径上,整个 #2284 级联块从来没有执行过。修法(用normalizeFieldType归一化)是对的,但它的后果不止于提示:于是 console 里被
dependsOn门控的选项字段,从今往后会:visibleWhen预过滤的options;需要拍板的问题(一句话)
两条轴上的分析
长远合理性 —— 倾向「生效」。 那行原始比较是 bug 而不是刻意限制:同一段注释白纸黑字写着"gate the whole control while a declared
dependsOnparent is still empty",意图从来就是通用的,只是字符串比较漏了带前缀的那一半。让它继续瘫痪,等于在 console 上长期维持一个"声明了却不兑现"的能力 —— 正是本仓反复在清的那种东西(#3232、#3236 都是同族)。而且 widget 侧本来就有自己的useCascadingOptions,门控语义在 widget 内一直是生效的;渲染器这一侧不生效,反而是两侧不一致。防 AI 写错 —— 同样倾向「生效」。 收敛后
field:select与select在渲染器与stripRegisteredFieldProps两处用同一个归一化,不再各判各的;这正是主令 #12 说的在生产者侧收敛。放着不修,下一个人还要再发现一次"为什么我的门控提示不出现"。但我不自行合并的理由: 这条改的是 console 主表单路径上的控件可用性,是用户直接看得见的交互变化,而原单从头到尾只在讨论一句提示文案。按 SKILL.md 的升级门槛,"选项在产品语义上真正分岔"就该由维护者定 —— 「门控时要不要禁用控件」是一个 UX 决定,不是实现细节,而且没有任何 issue 讨论过它。测试全绿这一点在这里的证据力也弱于平常:受影响的是对象派生的 console 表单,单元测试未必真的走到那条端到端路径。
三个可选动作
dependsOn的选项字段(本仓有dogfood-verification流程),确认禁用态的观感可接受。optionGroupGated从disabled的计算里摘出来,是对 表单支持级联/依赖选项:新增 SelectOption.visibleWhen 通用谓词 #2284 设计的修改,应当单独立单说明理由,不要夹在本单里悄悄做。维护者定一个,我照办。在此之前 PR 停在 ready-for-review,不入队。
另外两件
form.tsx:1843) #3263 已入队:内建(未注册)select分支仍渲染硬编码英文'No options available'—— 同族缺口,但被我给的 scope fence 明确挡在外面。现在fields.options.empty这个 key 在十个语言包里都有了,修它是一行加一条 defaults 映射。stripRegisteredFieldProps的转发做成了允许清单(只发给四个级联选项类型)而不是取消剥离,理由正确:其余已注册 widget 会把剩余 props 铺到 DOM 上,一个未知的emptyHint属性就是一条 React 警告。反向断言也钉住了这一点。Generated by Claude Code
xuyushun441-sys commentedon Aug 3, 2026
维护者裁定:A —— 按现状合并
已收到答复,PR #3262 已入合并队列,
needs-user-decision标签撤下。裁定内容:#2284「被
dependsOn门控的选项字段渲染为 disabled」这条既定设计,正式在 console 的对象派生表单上生效。此前isOptionField的裸字符串比较让整个级联块在field:前缀路径上从未执行,那是 bug,不是刻意限制。随之确立的行为(记在这里,便于后来者查)
自本 PR 起,console 中带
dependsOn的选项字段在父字段未填时:form.tsx的disabled: … || optionGroupGated);options是经visibleWhen预过滤的集合;若日后有人觉得"门控时禁用"观感不对,那是对 #2284 设计的修改,应当单独立单说明理由 —— 不要通过把
optionGroupGated从disabled计算里悄悄摘掉来实现,那会让本单再次回到"声明了却不兑现"的状态。Generated by Claude Code
fix(fields): option widgets render the host-computed emptyHint, trans…
fix(components): translate the built-in select branch's empty copy (o…
fix(components): 级联清值 effect 归一化字段类型,对象表单的带前缀 id 不再落空 (objectstack-ai…