Label: ready-for-agent Category: frontend-execution
承接票37收口时维护者反馈第1、2条。
clockText 变化重渲染 + :view="panelViewOf(panelId)" 是模板方法调用 → 每帧重算出全新 block 对象;第三轮的 owner === toRaw(block) 身份比较在下一帧静默失效——浮层存的是标量所以还在,高亮却掉了,症状完全吻合。修复=联动键改 chartScope(index, block)=视图名|块序号|块类型|块标题的稳定标量串(数据刷新前后不变,仍区分并排同类图与块内不同行)。批量替换时漏掉 clearChartHover 6 处(前缀不含 set),mouseleave 仍传 block → 高亮清不掉,被 t43 P1 假红逮出修正;16 个调用点全部统一。Status: resolved Type: task Blocked by: Labels: ready-for-agent
小间隔=绘制缺陷(像素舍入),不是设计语义。 判定过程没有把视觉现象当设计:
components/PanelBlocks.vue 的堆叠段样式原先对 left 与 width 各自独立取整 —— left: Math.round(row.start*100)%、width: Math.round(row.ratio*100)%。相邻段之间露出的底色缝 = round(nextStart*100) − (round(start*100) + round(ratio*100)),该值可为 ±1 个百分点(取决于两段各自的小数部分)。[0,1,2,1,1,3,1,0](mocks/contractMocks.js:2419 alarmWorkOrderStates,total=9)逐段复算,「待验收→已结案」边界 left+width=55 而下一段 left=56,实测 1 个百分点缝,与维护者所见一致(预警效率/报警族两处堆叠条同一算法,同一缺陷)。.panel-stacked__seg 无 margin、条容器无 gap/分隔声明,分段色由 barTone 逐态给(八态八色相)——若真要表达语义边界,应当是显式的分隔样式,而不是随数据总数随机出现在某些边界上的缝。同一对类别是否露缝取决于计数(待派单/待接单边界 0→0 不露,待验收/已结案露 1),这正是舍入噪声的特征,不是语义设计的特征。domain/panelBlocks.js stackedBlock() 每行新增 startPct / widthPct:由同一个累加器取整接力(endPct = round(acc/total*100),下一段 startPct = 上一段 endPct),末段终点恒为 100。无缝不是运气舍入的结果,而是代码结构保证(每段起点定义上就是上一段终点)。components/PanelBlocks.vue 堆叠段样式改消费这两个整数百分比,删除段内的 Math.round(...) 独立取整。total / start / ratio 原样保留未取整的精确占比,只改绘制边界;后端统计字段与工单状态码一字未动。第一轮把 tabindex/hover 挂在可见细环带上(46/25、42/26),真实指针落在圆心孔/环带外全部不触发; 第二轮改整楔命中区后浮层触发修好了,但联动状态
chartHover = ref(...)被 Vue 深层代理,owner === block恒 false,.is-hovered从未生效——扇区放大/图例高亮全部落空(第三轮驳回)。 第三轮:shallowRef存联动状态(身份保持原始对象,整体替换即触发渲染);放大档加强到 scale 1.1 + brightness 1.35 + 白描边(原 1.05/1.06 在 64px 图上仅 ~1.5px 位移,不够"明显")。
hitPath):statusPie.js 的 hitWedge 与 panelBlocks.js 的 donutBlock 为每个扇区额外产出一条从圆心出发的整楔(内半径 0)路径。渲染层把它画在可见扇区之上(fill: transparent),悬停/聚焦/键盘全部挂命中楔——热区与视觉扇区同角度同边界,圆心孔不再是死区。chartHover = shallowRef):任一侧悬停/聚焦,可见扇区加 .is-hovered(放大+提亮+描边)、对应图例行加 .is-hovered(底色+文字提亮),同一个共享详情浮层(票 37 的 showChartTip)。按 owner=块 + key=行 记账:两块同类图并排不串亮;清除比对 owner+key 防闪烁。tabindex="0" + role="img" + 每片 aria-label(类别:数量);:focus-visible 画白色描边。外层 <svg> role="group"(img 会藏子树使名称不可达)。<title>(票 37 趋势点成例)。justify-content: space-between、环形计数去 margin-left: auto、标签 flex: 0 1 auto(只缩不涨——1 1 auto 会把数值顶回行尾)。环形中心读数 pointer-events: none 让位给命中楔。barTone 八态八色相,未新增含义不明的视觉元素。class 真带 is-hovered 且计算样式 transform/filter 变化、对应图例行同亮;浏览器正反证见「进度」与 Comments。total/start/ratio 保持精确值;闸门 S4 钉住这一点。闸门 t43(第三轮 22/22,全离线):S 组堆叠连续(接力构造、旧缺陷实证复现 + 新公式缝=0、宽度和=100、0 计数行保留、口径不变、渲染层消费接力值);P 组交互(P0 两图扇区带 hitPath、P1 命中楔承载 tabindex/aria-label/hover/focus、P1b 可见扇区被动化、P2 无原生 title、P3 svg role=group、P4 .is-hovered 放大档 + 命中楔焦点描边、P5 图例⇄扇区双向、P6 数值紧跟标签、P7 中心读数让位、P8 联动记账结构、P9 联动状态必须 shallowRef + P9c Vue 运行时身份探针(ref 深层代理会破坏 owner===block,shallowRef 不会));D 组 donutBlock 形状与可点接缝不回归。
变异测试累计 7 处打红:M1 独立取整→S 组红;M2 删 tabindex→P1 红;M3 恢复 <title>→P2 红;M4 图例删 setChartHover→P5 红;M5 恢复 margin-left:auto→P6 红;M6 标签改回生长(同时暴露 CSS 守卫必须先剥注释)→P6 红;M7 shallowRef 改回 ref→P9 红(本轮根因的反向锁定)。
回归(离线 11 组全绿):t43、t50 30/30、t42、t15、t23、t27、t16-stores、t16-alarm-order、t22、t19、t09。@vue/compiler-sfc 结构校验全过。
既有红闸门归因:t20-overview-panels 60/66 的 6 条红与票 42 记录的 HEAD 基线同 6 条,与本票 diff 零交集。
教训留档:① 归因实验禁用 git stash push -- <文件>(本工作树会写坏文件),用票 42 的 HEAD worktree 对照法;② 带孔/细环 SVG 图形的 hover 断言必须打在用户视角位置(圆心、环带外);③ 联动类交互的验收判据必须是"被联动元素的状态本身"(class/计算样式),不是旁证(浮层);④ 把对象存进深层 ref 再用 === 比身份,会被 Vue 代理拆穿——跨响应式边界比身份要用 shallowRef/toRaw 或稳定标量键。
a40aedc 推送 origin/master;第二/三/四轮 hunks(domain/panelBlocks.js、domain/statusPie.js、components/PanelBlocks.vue、verify/t43-*.mjs)经独立临时 index 的 plumbing 提交为 7f71992 并推送 origin/master。工作树混有并行票 38/47 在制品,故只摘本票 hunks(PanelBlocks.vue 13 处逐个复核归属,剔除票 38 的维度切换与 KPI wide 布局共 6 处),未碰他人暂存区与工作树。(第三轮最终) 双向联动的真正根因不在几何、不在 CSS,而在响应式身份比较:chartHover = ref(null) 存入 {owner: block} 后被 Vue 深层代理,读回的 owner 是代理对象,与模板 v-for 拿到的原始 block === 恒 false → .is-hovered 永不生效(扇区不放大、图例不亮),而浮层不依赖这个比较所以照常弹出——一个根因同时解释「只出详情」与「联动失败」。修复=shallowRef + 两侧 toRaw() 比较;放大档加到 scale(1.1)+brightness(1.35)+白描边(原 1.05/1.06 在 64–72px 图上仅 1.5–2px 位移,不够"明显")。验收判据本轮改为"被联动元素自身的状态"(class/视觉放大),不再以浮层出现代判:真实浏览器(real)悬停扇区→扇区放大+描边+图例亮、悬停图例→扇区放大+描边(双向成立)、环形图与键盘 focus 同法通过;变异 M7(shallowRef 改回 ref)被 P9 打红,P9c 在真 Vue 里钉住机制本身。t43 22/22、11 组回归全绿。第二/三轮 hunks 已于 2026-10-16 随第四轮一并提交(7f71992,plumbing 限定提交)并推送 origin/master。
诊断+实施完成(2026-10-15):① 间隔根因=绘制缺陷——堆叠段 left/width 各自独立取整露出底色缝(mock 报警向量 [0,1,2,1,1,3,1,0] 实测「待验收→已结案」边界 1 个百分点,反证非语义设计:CSS 无任何分隔声明、露缝与否随计数变化)。修复=domain 单累加器接力取整(startPct/widthPct),连续由构造保证;total/start/ratio 口径原样保留。② 饼/环交互补齐:扇区 tabindex=0 + 每片 aria-label(类别:数量)、focus/blur 接同一共享浮层、:focus-visible 与 :hover 同档放大+描边、外层 svg role=img→group(img 会藏子树使名称不可达)、删原生