From 436dd63f15d5cc5191b165b9d53ec7558872a6a8 Mon Sep 17 00:00:00 2001 From: Elegy233 <82034747+wan0ge@users.noreply.github.com> Date: Wed, 29 Jul 2026 22:38:48 +0800 Subject: [PATCH] =?UTF-8?q?perf(ui):=20=E4=BC=98=E5=8C=96=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=9F=A5=E7=9C=8B=E5=99=A8=E5=9C=A8=E5=A4=A7=E9=87=8F?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B8=8B=E7=9A=84=E6=B8=B2=E6=9F=93=E4=B8=8E?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E6=80=A7=E8=83=BD=20(#404)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 日志行加 content-visibility:auto,视口外日志跳过布局与绘制, 全量渲染 9000 行时布局成本从数百毫秒降到个位数毫秒 - 分类筛选由整段 innerHTML 销毁重建改为切换 CSS class 显隐, 不再重建日志 DOM - addLog 仅在日志视图可见时重建 DOM,避免非日志页面产生无谓的全量重建 - 切到日志视图仍每次从服务端加载最新日志,保留原有及时性逻辑 不影响 GET /api/logs 服务端接口;不限制渲染行数,日志完整保留 main.js 保持上游原版未改动 --- danmu_api/ui/css/components.css.js | 8 +++++ danmu_api/ui/js/logview.js | 55 ++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/danmu_api/ui/css/components.css.js b/danmu_api/ui/css/components.css.js index ef3efbc..94c94ef 100644 --- a/danmu_api/ui/css/components.css.js +++ b/danmu_api/ui/css/components.css.js @@ -252,6 +252,14 @@ export const componentsCssContent = /* css */ ` margin-bottom: 8px; padding: 5px; border-radius: 4px; + /* 视口外日志行跳过布局与绘制,使大日志量下的排版成本只与可见行数相关;占位高度取单行日志的实测高度,已渲染过的行由浏览器记忆实际尺寸 */ + content-visibility: auto; + contain-intrinsic-size: auto 31px; +} + +/* 与当前筛选分类不匹配的日志行隐藏,筛选切换复用已构建的 DOM */ +.log-entry.log-entry-hidden { + display: none; } .log-entry.info { color: #4fc3f7; } diff --git a/danmu_api/ui/js/logview.js b/danmu_api/ui/js/logview.js index a82836d..6520073 100644 --- a/danmu_api/ui/js/logview.js +++ b/danmu_api/ui/js/logview.js @@ -56,32 +56,36 @@ function getLogCategory(message) { } // 日志相关 +// 判断日志视图是否处于可见状态,用于避免在非日志页面产生无谓的全量 DOM 重建 +function isLogViewVisible() { + const section = document.getElementById('logs-section'); + return !!section && section.classList.contains('active'); +} + function addLog(message, type = 'info') { const timestamp = new Date().toLocaleTimeString(); logs.push({ timestamp, message, type, _category: getLogCategory(message) }); if (logs.length > 100) logs.shift(); - renderLogs(); + // 仅当日志视图可见时才重建 DOM;切到其他页面期间产生的日志仅追加到数组,回到日志视图并重新渲染时再统一呈现,避免每次切换区块都全量重建 + if (isLogViewVisible()) { + renderLogs(); + } } function renderLogs() { const container = document.getElementById('log-container'); const filterContainer = document.getElementById('log-filters') || createFilterContainer(); - let filteredLogs = logs; - if (currentLogFilter !== 'ALL') { - // 采用严格归属校验,同时支持续行上下文继承 - let lastCategory = 'system'; - filteredLogs = logs.filter(log => { - let category = log._category; - if (category === '_inherit_') { - } else { - lastCategory = category; - } - return category === currentLogFilter; - }); - } - - container.innerHTML = filteredLogs.map(log => { + // 全量日志一次性构建 DOM,归属分类解析后写入 data-category 供筛选显隐使用,续行继承上一行的分类,保证筛选时上下文完整 + let lastCategory = 'system'; + container.innerHTML = logs.map(log => { + let category = log._category; + if (category === '_inherit_') { + category = lastCategory; + } else { + lastCategory = category; + } + let highlightedMessage = log.message; // 行首连续标签高亮 (需双重转义) @@ -93,13 +97,24 @@ function renderLogs() { highlightedMessage = coloredPrefix + rest; } - return \`