v1.0.10 两件大事:
1. 界面中英双语(英文界面无中文残留)
- 新增 web/i18n.js(约 4200 条词条),零依赖零构建
- 后端下发中文数据走 bt4() 查表翻译;独立模块(upstream/netdetail/
realtime/update)纳入翻译并注册切语言重绘钩子
- 后端「状态/聚合」接口只回稳定枚举+原始数值,不下发中文文案
- 顺带修一个真实 XSS:顶层 const 不挂 window,独立脚本 esc 静默退化成零转义
2. 修掉「文字竖着排/错位」(多分辨率反复暴露)
- 单元格 min-content 只有 1 字宽 → word-break:keep-all + 表头 nowrap
- 依赖卡片正文被标签/按钮挤成 27px → .dep-body{flex:1 1 200px} + flex-wrap
- 裸 flex:1(下限为0)给正文 → 一律改 flex:1 1 <px>
- .dep-item 横向容器直接塞块级子项 → 退回块级
- 关键陷阱:auto-fill 布局屏越宽列数越多单卡越窄,窄屏反而测不出来,
真机审计推进到「逐视图点按钮 + 1920/2560 宽视口 + 中英双语」
- 守卫 t-layout.py 扩到 35 条,12 处反向验证全红
3. 修真缺陷:_link_since() 重启检测被误改成 if False:(注释还写着「已修」),
uptime 归零后相减得负数 → 恢复比对 boot_id
附带:新增 25 个检查器(t-*.py)、排版审计工具链(shot-*/ocr-*/live-*)、
版本号兜底值同步到 1.0.10、.gitignore 收纳 i18n/排版排查的一次性脚本。
41 lines
1.7 KiB
JavaScript
41 lines
1.7 KiB
JavaScript
(() => {
|
|
const v = document.querySelector('#view');
|
|
if (!v) return JSON.stringify({ err: 'no #view' });
|
|
const vRect = v.getBoundingClientRect();
|
|
const docSW = document.documentElement.scrollWidth;
|
|
const vOver = v.scrollWidth - v.clientWidth;
|
|
const isIntentional = (el) => {
|
|
// .tw / pre / 终端类 是**有意**的横向滚动容器,不算问题
|
|
for (let p = el; p; p = p.parentElement) {
|
|
const c = p.className;
|
|
if (typeof c === 'string' && /(^|\s)(tw|term-pre|term-screen|logline|ppline)(\s|$)/.test(c)) return true;
|
|
if (p.tagName === 'PRE') return true;
|
|
if (p === v) break;
|
|
}
|
|
return false;
|
|
};
|
|
const items = [];
|
|
if (vOver > 1) {
|
|
for (const el of v.querySelectorAll('*')) {
|
|
const r = el.getBoundingClientRect();
|
|
if (r.width < 1 && r.height < 1) continue;
|
|
if (isIntentional(el)) continue;
|
|
// 两类都要报:① 盒子本身越过内容区右边界;
|
|
// ② 盒子内**内容**溢出(nowrap 长文本,rect 看不出但 scrollWidth 能)。
|
|
const ownOver = el.clientWidth > 0 && el.scrollWidth > el.clientWidth + 1;
|
|
if (r.right <= vRect.right + 1 && !ownOver) continue;
|
|
items.push({
|
|
sel: el.tagName.toLowerCase() + (typeof el.className === 'string' && el.className
|
|
? '.' + el.className.trim().split(/\s+/).slice(0, 2).join('.') : ''),
|
|
right: Math.round(r.right), w: Math.round(r.width),
|
|
own: ownOver ? el.scrollWidth - el.clientWidth : 0,
|
|
txt: (el.textContent || '').replace(/\s+/g, ' ').trim().slice(0, 80),
|
|
});
|
|
}
|
|
}
|
|
return JSON.stringify({
|
|
vw: window.innerWidth, docSW, vOver,
|
|
n: items.length, items: items.slice(0, 10),
|
|
});
|
|
})()
|