全站文字截断体检 · 检测工具本身要先被证伪
入档:2026-07-26 来源:PB Arena(pb.tiaozhuxiansheng.com)后台下拉框显示不全的修复会话,1 个提交(
f510fe5)已部署上线并封版v2026.07.26状态:已上线并线上实测;四条 insight 均为本次首次发现 ⚠️;核心律「检测工具本身要先被证伪」已于 2026-07-27 跨项目二次验证(网络测速探针,见 ping通不等于路通_fake-ip假信号与节点带宽实测选型_v1),其余三条仍待验证 同项目前情:零作品的比赛_界面演完不等于链路存在_v1 · 赛事状态机到点不切换_写入方不等于推进方_v1
事实记录(不可修改区)
-
触发:用户截图后台轮次列表,「参与范围」下拉只显示「所有人可」,并要求「顺便查一下类似的问题一并修复」
-
做法:写脚本遍历全部页面 + 11 个后台面板 + 各弹窗,扫 320 / 375 / 900 / 1000 / 1100 / 1280 / 1440 七档宽度
-
判据换过三版,对同一个元素给出三种不同结论(以
#adminEventStatusFilter、宽 96px 为例):版本 判据 对该元素的结论 v1 canvas 量文字宽 + padding + border + 经验值箭头宽 22px 差 3px,判为截断 ❌ v2 克隆一个 width:auto的同款 select,问浏览器要多宽不截断 ✅ v3 逐项选中,读元素自身 scrollWidth > clientWidth不截断 ✅ -
v1 共报 14 条,其中 8 条是后台筛选下拉「差 3px」、1 条是房间人数下拉「差 9px」——全部是误报
-
我据 v1 的误报给房间人数下拉加过一行
flex: none;做 A/B 对照(加与不加各量一遍)后发现两种情况宽度都是 50px、都不截断,已撤回 -
v3 的信号有效性单独验证过:把该下拉故意压到 30px,
scrollWidth34 >clientWidth30,确认信号能反映真截断 -
最终确认的真缺陷 3 处,修复后七档宽度 + 各弹窗零命中;后端测试 9/9 通过
一句话总结
体检脚本吐出来的「缺陷清单」本身就是一个待验证的假设——先用已知正常和已知损坏的样本把工具两端标定过再信它;否则你会拿着一张很权威的清单,去改一堆没坏的代码。
四条可复用 insight
1. 含经验常数的判据 = 未验证的假设,但它输出的是权威清单 ⚠️首次
v1 判据里只有一个拍脑袋的数:下拉箭头占 22px。就这一个数,把 8 个完全正常的元素判成了缺陷。
危险的地方在于输出形态:它不像一句「我觉得应该能行」那样一眼可疑,它是一张带元素选择器、带「需要 98px / 实际 95px」的表格,看起来已经量过了。人天然倾向于相信「工具找到了问题」,而不是「工具算错了」。
正确做法:先拿一个已知正常的元素和一个已知损坏的元素各跑一遍,确认工具在两端都判对,再信它对中间地带的判断。 本次最后就是靠「把下拉故意压到 30px,看它报不报」这一步,才确认 v3 的信号真的有效。
假阳性比假阴性更贵:假阴性只是漏掉一个 bug;假阳性会让你去改没坏的代码,同时放大工作量和回归风险。
2. 能问浏览器就别自己算,而且要问对问题 ⚠️首次
三版判据的演进方向,是越来越少自己算:
- v1:自己量文字 + 自己估箭头 + 自己加 padding → 三个中间量,三个偏差源
- v2:克隆一个自由宽度的元素,问浏览器「你要多宽」 → 好很多,但仍高估约 10px
- v3:让元素处在真实状态(逐项选中),直接读它自己的
scrollWidth/clientWidth→ 对
判据:凡是「渲染结果对不对」的问题,答案应该由渲染引擎给出,不由你的模型给出。 你自己算的每一个中间量都是一个偏差源。
v2 已经在问浏览器了,为什么还不对?因为我问错了问题:「浏览器认为一个自由宽度的 select 该多宽」和「这个 select 现在有没有截断」是两个不同的问题——前者的答案里含浏览器留的富余量。从「自己算」升级到「问引擎」只是第一步,还得确认你问的正是你要判的那件事。
3. 误报会伪装成「顺手修一下」混进提交 ⚠️首次
那行 flex: none 只有一个属性,看起来完全无害,而且「防止 flex 子项被压缩」这个理由本身还挺像回事。要不是最后做了 A/B 对照,它会作为「顺带修复」留在提交里,变成一行为不存在的问题而存在、后人也不敢删的代码(因为没人知道它在防什么)。
判据:每一条「顺带修的」改动,都要能单独拿出「改之前确实坏、改之后确实好」的证据。拿不出来就撤回。 不要用「反正无害」当理由留着——无害的代码也是债,债在于它让后来者无法判断它的必要性。
4. 「同类问题」要按写法搜,不按页面搜 ⚠️首次
三处真缺陷的共同点不是「都在后台」,而是同一种 CSS 写法:固定像素列宽 + 一个会自适应的邻居。
| 位置 | 写法 | 后果 |
|---|---|---|
| 后台轮次列表(用户截图处) | 80px 145px minmax(180px,1fr) 三列却放了五个子元素 | 两个下拉掉进 80px 的标题列,最长选项要 181px |
| 后台新增轮次表单 | 两个下拉写死 160px | 最长选项要 182px / 170px |
| 前台赛事卡片轮次行 | 95px 1fr auto | 固定列 + auto 列把中间的题目挤成 15px(要 66–99px) |
第三处最严重,却在用户截图的那个宽度下完全正常,只在 1100px 附近才现形;而且它在前台,不在后台。
所以:按「再看看后台别的页面」去找会漏掉它;按「再看看 1440px 下还有没有」去找也会漏掉它。要按写法搜(grep 固定像素列宽)+ 按宽度扫,才能捞到同一个 bug 的另一个化身。
顺手教训
- 用户说「顺便查一下类似的问题」时,交付物里要包含排查覆盖面:查了哪些页面、哪些宽度、用什么判据、哪些报了但复核后判定不是问题。否则「我查过了」是不可核验的一句话。本次把「排查后确认不是问题(未改动)」单独写进了文档,和「已修复」并列。
- 带版本号的静态资源,改文件必须同步改版本号——这条在 赛事状态机到点不切换_写入方不等于推进方_v1 里已经记过一次,本次改
styles.css时主动改了?v=20260726,并在部署后单独核对线上 HTML 引用的确实是新版本号。记过的坑要在下一次主动触发,而不是等它再犯。 - 线上没有可复现的数据时,注入渲染器实际产出的那段结构来量线上 CSS:生产库里没有进行中的赛事,页面渲染不出轮次卡片。做法是把
renderRoundList实际产出的 HTML 注入线上页面 DOM 再量——量到的是部署后的样式,不是本地的,且全程只读、不写任何数据。
下次改进
- 写体检 / 扫描类脚本时,第一步不是跑全量,是造一个已知正常样本和一个已知损坏样本,确认工具两端都判对。
- 判 UI 渲染结果时,优先读元素自身在真实状态下的几何属性;要自己算之前先问一句「这个量浏览器是不是已经算好了」。
- 每条「顺带修的」改动都配一份 A/B 证据,拿不出来就撤回。
- 找「同类问题」时 grep 的是写法(这里是固定像素列宽),不是页面名。
关联文档
- ⭐ 交付前实测证伪律_v1 —— 直接同族的另一半:那条管「别把没验证过的方案当能行」,本篇管「别把没验证过的检测工具的输出当事实」;两条合起来才是完整的「不把未验证当已验证」
- ⚠️ 赛事状态机到点不切换_写入方不等于推进方_v1 —— 同项目,且是本篇的正对照:那篇的教训是「决定性的一步是量,不是猜」(量到胶囊文字实际 56px / 需要 86px);本篇补上后半句——量的方法本身也可能是错的,量之前先标定
- ⚠️ 零作品的比赛_界面演完不等于链路存在_v1 —— 同项目上一会话:那篇是「别用界面验收功能,要用数据」,本篇是「用来验收的工具也要先被验收」
- ⚠️ Claude预览环境不派发滚动事件_滚动类功能无法行为验证_v1 —— 同族「验证手段本身失效」:那篇是环境不派发事件导致压根测不了,本篇是判据算错导致测出一堆假的
- ⚠️ reduced-motion本机陷阱_动效降级纯淡入而非跳过_v1 —— 同族「本机测量骗了你」:那篇是本机偏好开关让自测毫无变化,本篇是自制判据让正常元素显示为缺陷
- ⚠️ 美工改稿全站落地_跨稿重复才是规范_v1 —— 同项目后续会话、同一纪律的第三次现形:本篇是自制判据把正常元素判成缺陷,那篇是拿规范文字当待办清单、把两处已经实现的功能误报成「还没做」;共同解法都是报缺陷前先回原地核实。另,本篇顺手教训里的版本号一条在那次被扩展成「版本号要覆盖会一起变的那一组文件」——
styles.css有?v=而app.js没有,只 bust 一半等于新样式配旧 DOM - ⭐ ping通不等于路通_fake-ip假信号与节点带宽实测选型_v1 —— 本篇核心律的跨项目二次验证(首次出圈:上次是浏览器 UI 体检脚本,这次是网络测速脚本):探针参数超限被 403,把 14 个正常节点判成「全挂」,形态是一列整齐的 0——和本篇「一张带数字的表格」同构,都是工具的输出形态很像事实;那篇补上操作层判据「
0同时意味着『测到 0』和『没测成』,探针必须输出http_code/size_download这类能区分二者的字段」 - ⭐ 构建产物的脏改动不是事故_复发是归因错了的信号_v1 —— 本篇核心律的第三次现形(2026-07-28),三条合起来覆盖了三个信息源:本篇管工具的输出要先证伪,ping通不等于路通_fake-ip假信号与节点带宽实测选型_v1 管诊断的信号要打在真实链路上,那篇管你自己写下的历史归因要先证伪——且那篇指出最后一种最危险:它不会被质疑(自己写的),还会主动加速下一次误判
- 复盘事实先行原则 —— 本篇顶部事实冻结区按它执行
- 09_平台工程索引 —— 平台工程区入口