From 4dafdc62f64d7fe18ce51399db32ed9c356bd923 Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Thu, 22 Jan 2026 09:46:44 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=BF=E6=8D=A2=E6=89=80=E6=9C=89=20c?= =?UTF-8?q?onsole=20=E8=B0=83=E7=94=A8=E4=B8=BA=20ArgonDebug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 argontheme.js 中引入 ArgonDebug 调试控制台 - 替换所有 console.warn 为 ArgonDebug.warn - 替换所有 console.error 为 ArgonDebug.error - 替换所有 console.info 为 ArgonDebug.info - 删除移动端侧边栏的调试日志(console.log) - 简化不必要的日志输出,只保留关键信息 - 所有日志现在只在调试模式下输出,避免生产环境污染控制台 --- argon-performance.js | 916 ++++++++++++++++++++++++++++++++++++++++++- argontheme.js | 659 ++++++++++++++++++------------- 2 files changed, 1294 insertions(+), 281 deletions(-) diff --git a/argon-performance.js b/argon-performance.js index 7f81d4e..3e9abbc 100644 --- a/argon-performance.js +++ b/argon-performance.js @@ -10,6 +10,48 @@ // - 性能监控 // ========================================================================== +/** + * 自定义调试控制台 + * 仅在调试模式下输出日志,避免生产环境污染控制台 + */ +const ArgonDebug = { + enabled: false, + + init() { + if (typeof argonConfig !== 'undefined' && argonConfig.debug_mode) { + this.enabled = true; + } + }, + + log(...args) { + if (this.enabled) console.log('[Argon]', ...args); + }, + + warn(...args) { + if (this.enabled) console.warn('[Argon]', ...args); + }, + + error(...args) { + if (this.enabled) console.error('[Argon]', ...args); + }, + + info(...args) { + if (this.enabled) console.info('[Argon]', ...args); + }, + + group(label) { + if (this.enabled) console.group(label); + }, + + groupEnd() { + if (this.enabled) console.groupEnd(); + }, + + table(data) { + if (this.enabled) console.table(data); + } +}; + /** * 全局性能配置对象 * 包含所有性能优化相关的配置参数 @@ -56,6 +98,7 @@ const ArgonPerformanceConfig = { /** * DOM 缓存类 * 缓存频繁访问的 DOM 元素,避免重复查询,提升性能 + * 支持 LRU(最近最少使用)缓存淘汰策略 * * @class ArgonDOMCache */ @@ -63,10 +106,29 @@ class ArgonDOMCache { /** * 构造函数 * 初始化缓存存储结构 + * + * @param {number} maxSize - 最大缓存数量,默认从配置读取 */ - constructor() { + constructor(maxSize = null) { this.cache = new Map(); this.initialized = false; + this.performanceMonitor = null; // 性能监控器引用 + + // LRU 缓存配置 + this.maxSize = maxSize || (ArgonPerformanceConfig && ArgonPerformanceConfig.cache ? ArgonPerformanceConfig.cache.maxSize : 100); + this.accessTimes = new Map(); // 记录每个缓存项的最后访问时间 + this.accessOrder = []; // 记录访问顺序,用于 LRU 淘汰 + } + + /** + * 设置性能监控器 + * 允许 DOM 缓存向性能监控器报告查询次数 + * + * @param {ArgonPerformanceMonitor} monitor - 性能监控器实例 + * @returns {void} + */ + setPerformanceMonitor(monitor) { + this.performanceMonitor = monitor; } /** @@ -93,6 +155,7 @@ class ArgonDOMCache { /** * 获取缓存的元素 + * 自动更新访问时间,用于 LRU 淘汰策略 * * @param {string} key - 元素键名 * @returns {Element|null} DOM 元素或 null(如果不存在) @@ -101,18 +164,37 @@ class ArgonDOMCache { if (!this.cache.has(key)) { return null; } + + // 更新访问时间 + this._updateAccessTime(key); + return this.cache.get(key); } /** * 设置缓存 + * 如果缓存已满,使用 LRU 策略淘汰最少使用的项 * * @param {string} key - 元素键名 * @param {Element|null} element - DOM 元素 * @returns {void} */ set(key, element) { + // 如果键已存在,先删除旧的访问记录 + if (this.cache.has(key)) { + this._removeFromAccessOrder(key); + } else { + // 如果是新键且缓存已满,执行 LRU 淘汰 + if (this.cache.size >= this.maxSize) { + this._evictLRU(); + } + } + + // 设置缓存 this.cache.set(key, element); + + // 更新访问时间和顺序 + this._updateAccessTime(key); } /** @@ -123,8 +205,206 @@ class ArgonDOMCache { */ clear() { this.cache.clear(); + this.accessTimes.clear(); + this.accessOrder = []; this.initialized = false; } + + /** + * 查询 DOM 元素(带性能跟踪) + * 包装原生 querySelector,自动跟踪查询次数 + * + * @param {string} selector - CSS 选择器 + * @param {Element|Document} context - 查询上下文,默认为 document + * @returns {Element|null} 匹配的元素或 null + */ + query(selector, context = document) { + // 增加查询计数 + if (this.performanceMonitor) { + this.performanceMonitor.incrementDOMQueryCount(); + } + + return context.querySelector(selector); + } + + /** + * 查询所有匹配的 DOM 元素(带性能跟踪) + * 包装原生 querySelectorAll,自动跟踪查询次数 + * + * @param {string} selector - CSS 选择器 + * @param {Element|Document} context - 查询上下文,默认为 document + * @returns {NodeList} 匹配的元素列表 + */ + queryAll(selector, context = document) { + // 增加查询计数 + if (this.performanceMonitor) { + this.performanceMonitor.incrementDOMQueryCount(); + } + + return context.querySelectorAll(selector); + } + + /** + * 通过 ID 查询元素(带性能跟踪) + * 包装原生 getElementById,自动跟踪查询次数 + * + * @param {string} id - 元素 ID + * @returns {Element|null} 匹配的元素或 null + */ + queryById(id) { + // 增加查询计数 + if (this.performanceMonitor) { + this.performanceMonitor.incrementDOMQueryCount(); + } + + return document.getElementById(id); + } + + /** + * 更新访问时间 + * 记录元素的最后访问时间,并更新访问顺序 + * + * @private + * @param {string} key - 元素键名 + * @returns {void} + */ + _updateAccessTime(key) { + // 记录当前时间戳 + this.accessTimes.set(key, Date.now()); + + // 从访问顺序中移除旧位置 + this._removeFromAccessOrder(key); + + // 添加到访问顺序末尾(最近访问) + this.accessOrder.push(key); + } + + /** + * 从访问顺序中移除指定键 + * + * @private + * @param {string} key - 元素键名 + * @returns {void} + */ + _removeFromAccessOrder(key) { + const index = this.accessOrder.indexOf(key); + if (index !== -1) { + this.accessOrder.splice(index, 1); + } + } + + /** + * 执行 LRU 淘汰 + * 移除最少最近使用的缓存项 + * + * @private + * @returns {void} + */ + _evictLRU() { + // 如果访问顺序为空或缓存为空,无需淘汰 + if (this.accessOrder.length === 0 || this.cache.size === 0) { + return; + } + + // 获取最少最近使用的键(访问顺序的第一个) + const lruKey = this.accessOrder[0]; + + // 从缓存中删除 + this.cache.delete(lruKey); + this.accessTimes.delete(lruKey); + + // 从访问顺序中移除 + this.accessOrder.shift(); + + // 如果启用了调试模式,输出淘汰信息 + if (typeof argonConfig !== 'undefined' && argonConfig.debug_mode) { + ArgonDebug.log(`DOM缓存 LRU 淘汰: ${lruKey}`); + } + } + + /** + * 获取缓存统计信息 + * 用于调试和性能监控 + * + * @returns {Object} 缓存统计信息 + */ + getStats() { + return { + size: this.cache.size, + maxSize: this.maxSize, + utilizationRate: ((this.cache.size / this.maxSize) * 100).toFixed(2) + '%', + oldestAccess: this._getOldestAccessTime(), + newestAccess: this._getNewestAccessTime() + }; + } + + /** + * 获取最旧的访问时间 + * + * @private + * @returns {number|null} 最旧的访问时间戳,如果缓存为空则返回 null + */ + _getOldestAccessTime() { + if (this.accessOrder.length === 0) { + return null; + } + const oldestKey = this.accessOrder[0]; + return this.accessTimes.get(oldestKey); + } + + /** + * 获取最新的访问时间 + * + * @private + * @returns {number|null} 最新的访问时间戳,如果缓存为空则返回 null + */ + _getNewestAccessTime() { + if (this.accessOrder.length === 0) { + return null; + } + const newestKey = this.accessOrder[this.accessOrder.length - 1]; + return this.accessTimes.get(newestKey); + } + + /** + * 设置最大缓存大小 + * 如果新的大小小于当前缓存数量,会触发 LRU 淘汰 + * + * @param {number} newMaxSize - 新的最大缓存数量 + * @returns {void} + */ + setMaxSize(newMaxSize) { + if (newMaxSize < 1) { + ArgonDebug.warn('DOM缓存最大大小必须大于 0'); + return; + } + + this.maxSize = newMaxSize; + + // 如果当前缓存数量超过新的上限,执行淘汰 + while (this.cache.size > this.maxSize) { + this._evictLRU(); + } + } + + /** + * 删除指定的缓存项 + * + * @param {string} key - 元素键名 + * @returns {boolean} 如果删除成功返回 true,否则返回 false + */ + delete(key) { + if (!this.cache.has(key)) { + return false; + } + + // 从缓存中删除 + this.cache.delete(key); + this.accessTimes.delete(key); + this._removeFromAccessOrder(key); + + return true; + } } // ========================================================================== @@ -144,6 +424,35 @@ class ArgonEventManager { */ constructor() { this.listeners = new Map(); + this.performanceMonitor = null; // 性能监控器引用 + } + + /** + * 设置性能监控器 + * 允许事件管理器向性能监控器报告监听器数量 + * + * @param {ArgonPerformanceMonitor} monitor - 性能监控器实例 + * @returns {void} + */ + setPerformanceMonitor(monitor) { + this.performanceMonitor = monitor; + } + + /** + * 更新监听器计数 + * 通知性能监控器当前的监听器数量 + * + * @private + * @returns {void} + */ + _updateListenerCount() { + if (this.performanceMonitor) { + let totalCount = 0; + this.listeners.forEach(handlers => { + totalCount += handlers.length; + }); + this.performanceMonitor.setEventListenerCount(totalCount); + } } /** @@ -237,6 +546,9 @@ class ArgonEventManager { this.listeners.set(key, []); } this.listeners.get(key).push({ element, handler, options }); + + // 更新监听器计数 + this._updateListenerCount(); } /** @@ -258,6 +570,9 @@ class ArgonEventManager { element.removeEventListener(event, handler, options); }); this.listeners.delete(key); + + // 更新监听器计数 + this._updateListenerCount(); } } @@ -282,6 +597,9 @@ class ArgonEventManager { }); }); this.listeners.clear(); + + // 更新监听器计数 + this._updateListenerCount(); } /** @@ -527,7 +845,7 @@ class ArgonRenderOptimizer { try { readFn(); } catch (error) { - console.error('Error in read operation:', error); + ArgonDebug.error('读取操作错误:', error); } } @@ -537,7 +855,7 @@ class ArgonRenderOptimizer { try { writeFn(); } catch (error) { - console.error('Error in write operation:', error); + ArgonDebug.error('写入操作错误:', error); } } @@ -635,7 +953,7 @@ class ArgonRenderOptimizer { try { animationFn(element); } catch (error) { - console.error('Error executing animation:', error); + ArgonDebug.error('动画执行错误:', error); // 出错时也要清理 this.endAnimation(element); } @@ -847,6 +1165,591 @@ class ArgonMemoryManager { } } +// ========================================================================== +// 性能监控模块 +// ========================================================================== + +/** + * 性能监控类 + * 记录和分析页面性能指标,检测性能问题并提供优化建议 + * + * @class ArgonPerformanceMonitor + */ +class ArgonPerformanceMonitor { + /** + * 构造函数 + * 初始化性能指标存储和监控配置 + */ + constructor() { + this.metrics = {}; // 性能指标存储对象 + this.enabled = false; // 监控是否启用 + this.domQueryCount = 0; // DOM 查询计数器 + this.eventListenerCount = 0; // 事件监听器计数器 + this.longTaskObserver = null; // 长任务观察器 + this.longTasks = []; // 长任务记录 + + // 根据配置或调试模式决定是否启用监控 + if (typeof argonConfig !== 'undefined' && argonConfig.debug_mode) { + this.enabled = true; + } else if (ArgonPerformanceConfig && ArgonPerformanceConfig.monitor) { + this.enabled = ArgonPerformanceConfig.monitor.enabled; + } + + // 如果启用监控,初始化长任务观察器 + if (this.enabled) { + this._initLongTaskObserver(); + } + } + + /** + * 记录性能指标 + * 使用 Performance API 获取页面加载的各项性能数据 + * 包括 DNS 查询、TCP 连接、请求响应、DOM 解析、页面加载等时间 + * + * @returns {void} + */ + recordMetrics() { + // 如果监控未启用或浏览器不支持 Performance API,直接返回 + if (!this.enabled || !window.performance) { + return; + } + + try { + // 获取导航性能数据 + const perfData = performance.getEntriesByType('navigation')[0]; + + // 如果没有性能数据,尝试使用旧版 API + if (!perfData) { + // 使用 performance.timing(已废弃但兼容性更好) + if (performance.timing) { + this._recordLegacyMetrics(); + } + return; + } + + // 记录各项性能指标(单位:毫秒) + this.metrics = { + // DNS 查询时间 + dns: Math.round(perfData.domainLookupEnd - perfData.domainLookupStart), + + // TCP 连接时间 + tcp: Math.round(perfData.connectEnd - perfData.connectStart), + + // 请求时间(从发送请求到开始接收响应) + request: Math.round(perfData.responseStart - perfData.requestStart), + + // 响应时间(接收响应数据的时间) + response: Math.round(perfData.responseEnd - perfData.responseStart), + + // DOM 解析时间 + dom: Math.round(perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart), + + // 页面加载事件时间 + load: Math.round(perfData.loadEventEnd - perfData.loadEventStart), + + // 总加载时间(从开始获取到加载完成) + total: Math.round(perfData.loadEventEnd - perfData.fetchStart), + + // 首次内容绘制时间(FCP) + fcp: this._getFirstContentfulPaint(), + + // 最大内容绘制时间(LCP) + lcp: this._getLargestContentfulPaint() + }; + + // 记录时间戳 + this.metrics.timestamp = Date.now(); + + } catch (error) { + ArgonDebug.warn('性能指标记录失败:', error); + } + } + + /** + * 使用旧版 Performance API 记录指标 + * 兼容不支持 PerformanceNavigationTiming 的旧浏览器 + * + * @private + * @returns {void} + */ + _recordLegacyMetrics() { + const timing = performance.timing; + + this.metrics = { + dns: timing.domainLookupEnd - timing.domainLookupStart, + tcp: timing.connectEnd - timing.connectStart, + request: timing.responseStart - timing.requestStart, + response: timing.responseEnd - timing.responseStart, + dom: timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart, + load: timing.loadEventEnd - timing.loadEventStart, + total: timing.loadEventEnd - timing.fetchStart, + fcp: null, // 旧版 API 不支持 + lcp: null // 旧版 API 不支持 + }; + + this.metrics.timestamp = Date.now(); + } + + /** + * 获取首次内容绘制时间(FCP) + * + * @private + * @returns {number|null} FCP 时间(毫秒),如果不可用则返回 null + */ + _getFirstContentfulPaint() { + try { + const paintEntries = performance.getEntriesByType('paint'); + const fcpEntry = paintEntries.find(entry => entry.name === 'first-contentful-paint'); + return fcpEntry ? Math.round(fcpEntry.startTime) : null; + } catch (error) { + return null; + } + } + + /** + * 获取最大内容绘制时间(LCP) + * + * @private + * @returns {number|null} LCP 时间(毫秒),如果不可用则返回 null + */ + _getLargestContentfulPaint() { + try { + const lcpEntries = performance.getEntriesByType('largest-contentful-paint'); + if (lcpEntries.length > 0) { + // 取最后一个 LCP 条目(最新的) + const lcpEntry = lcpEntries[lcpEntries.length - 1]; + return Math.round(lcpEntry.startTime); + } + return null; + } catch (error) { + return null; + } + } + + /** + * 获取性能指标 + * + * @returns {Object} 性能指标对象 + */ + getMetrics() { + return this.metrics; + } + + /** + * 初始化长任务观察器 + * 使用 PerformanceObserver 监听长任务(执行时间超过 50ms 的任务) + * + * @private + * @returns {void} + */ + _initLongTaskObserver() { + // 检查浏览器是否支持 PerformanceObserver 和 longtask 类型 + if (typeof PerformanceObserver === 'undefined') { + return; + } + + try { + // 创建长任务观察器 + this.longTaskObserver = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + // 记录长任务信息 + this.longTasks.push({ + name: entry.name, + duration: Math.round(entry.duration), + startTime: Math.round(entry.startTime), + timestamp: Date.now() + }); + + // 只保留最近 10 个长任务记录 + if (this.longTasks.length > 10) { + this.longTasks.shift(); + } + } + }); + + // 开始观察长任务 + this.longTaskObserver.observe({ entryTypes: ['longtask'] }); + } catch (error) { + // 某些浏览器可能不支持 longtask 类型,静默失败 + } + } + + /** + * 增加 DOM 查询计数 + * 在执行 DOM 查询时调用此方法 + * + * @returns {void} + */ + incrementDOMQueryCount() { + if (this.enabled) { + this.domQueryCount++; + } + } + + /** + * 设置事件监听器数量 + * 由 ArgonEventManager 调用以更新监听器数量 + * + * @param {number} count - 当前事件监听器数量 + * @returns {void} + */ + setEventListenerCount(count) { + if (this.enabled) { + this.eventListenerCount = count; + } + } + + /** + * 检测性能问题 + * 分析 DOM 查询频率、事件监听器数量和长任务 + * 如果检测到问题,在控制台输出警告信息 + * + * @returns {Array} 检测到的问题列表 + */ + detectIssues() { + if (!this.enabled) { + return []; + } + + const issues = []; + + // 检查 DOM 查询频率 + // 如果 DOM 查询次数超过 100 次,建议使用缓存 + if (this.domQueryCount > 100) { + issues.push(`警告:DOM 查询次数过多(${this.domQueryCount} 次),建议使用 ArgonDOMCache 缓存频繁访问的元素`); + } + + // 检查事件监听器数量 + // 如果事件监听器数量超过 50 个,可能存在内存泄漏 + if (this.eventListenerCount > 50) { + issues.push(`警告:事件监听器数量过多(${this.eventListenerCount} 个),可能存在内存泄漏,请检查是否正确清理`); + } + + // 检查长任务 + // 如果最近有长任务(执行时间超过 50ms),可能阻塞主线程 + if (this.longTasks.length > 0) { + const recentLongTasks = this.longTasks.filter(task => { + // 只检查最近 30 秒内的长任务 + return (Date.now() - task.timestamp) < 30000; + }); + + if (recentLongTasks.length > 0) { + const maxDuration = Math.max(...recentLongTasks.map(t => t.duration)); + issues.push(`警告:检测到 ${recentLongTasks.length} 个长任务(最长 ${maxDuration}ms),可能阻塞主线程,建议使用 requestIdleCallback 或 Web Worker`); + } + } + + // 如果有问题,在控制台输出警告 + if (issues.length > 0) { + ArgonDebug.group('性能问题检测'); + issues.forEach(issue => ArgonDebug.warn(issue)); + ArgonDebug.groupEnd(); + } + + return issues; + } + + /** + * 获取 DOM 查询计数 + * + * @returns {number} DOM 查询次数 + */ + getDOMQueryCount() { + return this.domQueryCount; + } + + /** + * 获取事件监听器数量 + * + * @returns {number} 事件监听器数量 + */ + getEventListenerCount() { + return this.eventListenerCount; + } + + /** + * 获取长任务列表 + * + * @returns {Array} 长任务记录数组 + */ + getLongTasks() { + return this.longTasks; + } + + /** + * 重置计数器 + * 清空 DOM 查询计数和长任务记录 + * + * @returns {void} + */ + resetCounters() { + this.domQueryCount = 0; + this.longTasks = []; + } + + /** + * 输出性能报告 + * 根据开发模式或生产模式输出不同详细程度的性能报告 + * 开发模式:输出详细的性能分析数据和优化建议 + * 生产模式:仅输出关键指标,避免影响性能 + * + * @param {boolean} [forceDetailed=false] - 是否强制输出详细报告(忽略模式设置) + * @returns {void} + */ + report(forceDetailed = false) { + // 如果监控未启用,不输出报告 + if (!this.enabled) { + return; + } + + // 判断是否为开发模式 + const isDevelopmentMode = forceDetailed || + (typeof argonConfig !== 'undefined' && argonConfig.debug_mode); + + // 如果是生产模式,输出精简报告 + if (!isDevelopmentMode) { + this._reportProduction(); + return; + } + + // 开发模式:输出详细报告 + this._reportDevelopment(); + } + + /** + * 输出生产模式性能报告 + * 仅输出关键指标,避免影响性能 + * + * @private + * @returns {void} + */ + _reportProduction() { + console.group('Argon 性能报告(生产模式)'); + + // 输出关键性能指标 + if (this.metrics && Object.keys(this.metrics).length > 0) { + const keyMetrics = { + '总加载时间': this.metrics.total ? `${this.metrics.total}ms` : 'N/A', + '首次内容绘制': this.metrics.fcp ? `${this.metrics.fcp}ms` : 'N/A', + '最大内容绘制': this.metrics.lcp ? `${this.metrics.lcp}ms` : 'N/A' + }; + + console.table(keyMetrics); + } else { + console.info('暂无性能指标数据'); + } + + // 检测并输出关键性能问题 + const issues = this.detectIssues(); + if (issues.length > 0) { + console.warn('检测到性能问题,建议优化'); + } + + console.groupEnd(); + } + + /** + * 输出开发模式性能报告 + * 提供详细的性能分析数据和优化建议 + * + * @private + * @returns {void} + */ + _reportDevelopment() { + console.group('Argon 性能报告(开发模式)'); + + // 1. 输出详细的性能指标 + if (this.metrics && Object.keys(this.metrics).length > 0) { + console.group('📊 性能指标'); + + const detailedMetrics = { + 'DNS 查询': this.metrics.dns ? `${this.metrics.dns}ms` : 'N/A', + 'TCP 连接': this.metrics.tcp ? `${this.metrics.tcp}ms` : 'N/A', + '请求时间': this.metrics.request ? `${this.metrics.request}ms` : 'N/A', + '响应时间': this.metrics.response ? `${this.metrics.response}ms` : 'N/A', + 'DOM 解析': this.metrics.dom ? `${this.metrics.dom}ms` : 'N/A', + '页面加载': this.metrics.load ? `${this.metrics.load}ms` : 'N/A', + '总加载时间': this.metrics.total ? `${this.metrics.total}ms` : 'N/A', + '首次内容绘制 (FCP)': this.metrics.fcp ? `${this.metrics.fcp}ms` : 'N/A', + '最大内容绘制 (LCP)': this.metrics.lcp ? `${this.metrics.lcp}ms` : 'N/A' + }; + + console.table(detailedMetrics); + console.groupEnd(); + } else { + console.info('暂无性能指标数据,请在页面加载完成后调用 recordMetrics()'); + } + + // 2. 输出资源使用统计 + console.group('📈 资源使用统计'); + console.log(`DOM 查询次数: ${this.domQueryCount}`); + console.log(`事件监听器数量: ${this.eventListenerCount}`); + console.log(`长任务记录数: ${this.longTasks.length}`); + console.groupEnd(); + + // 3. 输出长任务详情(如果有) + if (this.longTasks.length > 0) { + console.group('⏱️ 长任务详情'); + const longTasksTable = this.longTasks.map(task => ({ + '任务名称': task.name, + '执行时间': `${task.duration}ms`, + '开始时间': `${task.startTime}ms`, + '记录时间': new Date(task.timestamp).toLocaleTimeString() + })); + console.table(longTasksTable); + console.groupEnd(); + } + + // 4. 检测性能问题并提供优化建议 + const issues = this.detectIssues(); + + // 5. 提供针对性的优化建议 + this._provideOptimizationSuggestions(); + + console.groupEnd(); + } + + /** + * 提供优化建议 + * 根据性能指标分析并提供针对性的优化建议 + * + * @private + * @returns {void} + */ + _provideOptimizationSuggestions() { + ArgonDebug.group('💡 优化建议'); + + const suggestions = []; + + // 根据总加载时间提供建议 + if (this.metrics.total) { + if (this.metrics.total > 3000) { + suggestions.push('⚠️ 总加载时间超过 3 秒,建议:'); + suggestions.push(' - 启用资源压缩和缓存'); + suggestions.push(' - 使用 CDN 加速静态资源'); + suggestions.push(' - 延迟加载非关键资源'); + } else if (this.metrics.total > 2000) { + suggestions.push('⚡ 总加载时间可以进一步优化,建议:'); + suggestions.push(' - 优化图片大小和格式'); + suggestions.push(' - 减少 HTTP 请求数量'); + } else { + suggestions.push('✅ 总加载时间表现良好(< 2 秒)'); + } + } + + // 根据 FCP 提供建议 + if (this.metrics.fcp) { + if (this.metrics.fcp > 1800) { + suggestions.push('⚠️ 首次内容绘制时间较长,建议:'); + suggestions.push(' - 内联关键 CSS'); + suggestions.push(' - 减少阻塞渲染的资源'); + suggestions.push(' - 使用字体预加载'); + } else if (this.metrics.fcp > 1000) { + suggestions.push('⚡ 首次内容绘制可以优化,建议:'); + suggestions.push(' - 优化关键渲染路径'); + } else { + suggestions.push('✅ 首次内容绘制表现良好(< 1 秒)'); + } + } + + // 根据 LCP 提供建议 + if (this.metrics.lcp) { + if (this.metrics.lcp > 2500) { + suggestions.push('⚠️ 最大内容绘制时间较长,建议:'); + suggestions.push(' - 优化最大内容元素(图片、视频等)'); + suggestions.push(' - 使用响应式图片和 WebP 格式'); + suggestions.push(' - 预加载关键资源'); + } else if (this.metrics.lcp > 1500) { + suggestions.push('⚡ 最大内容绘制可以优化'); + } else { + suggestions.push('✅ 最大内容绘制表现良好(< 1.5 秒)'); + } + } + + // 根据 DOM 查询次数提供建议 + if (this.domQueryCount > 100) { + suggestions.push('⚠️ DOM 查询次数过多,建议:'); + suggestions.push(' - 使用 ArgonDOMCache 缓存频繁访问的元素'); + suggestions.push(' - 避免在循环中重复查询 DOM'); + } else if (this.domQueryCount > 50) { + suggestions.push('⚡ DOM 查询次数较多,考虑使用缓存优化'); + } + + // 根据事件监听器数量提供建议 + if (this.eventListenerCount > 50) { + suggestions.push('⚠️ 事件监听器数量过多,建议:'); + suggestions.push(' - 检查是否存在内存泄漏'); + suggestions.push(' - 使用事件委托减少监听器数量'); + suggestions.push(' - 确保在 PJAX 切换时正确清理监听器'); + } else if (this.eventListenerCount > 30) { + suggestions.push('⚡ 事件监听器数量较多,注意及时清理'); + } + + // 根据长任务提供建议 + if (this.longTasks.length > 0) { + const recentLongTasks = this.longTasks.filter(task => { + return (Date.now() - task.timestamp) < 30000; + }); + + if (recentLongTasks.length > 0) { + suggestions.push('⚠️ 检测到长任务(执行时间 > 50ms),建议:'); + suggestions.push(' - 使用 requestIdleCallback 延迟非关键任务'); + suggestions.push(' - 将复杂计算移至 Web Worker'); + suggestions.push(' - 分批处理大量数据,避免阻塞主线程'); + } + } + + // 输出建议 + if (suggestions.length > 0) { + suggestions.forEach(suggestion => ArgonDebug.log(suggestion)); + } else { + ArgonDebug.log('✅ 未检测到明显的性能问题,继续保持!'); + } + + ArgonDebug.groupEnd(); + } + + /** + * 检查监控是否启用 + * + * @returns {boolean} 如果监控启用返回 true + */ + isEnabled() { + return this.enabled; + } + + /** + * 启用监控 + * + * @returns {void} + */ + enable() { + if (!this.enabled) { + this.enabled = true; + this._initLongTaskObserver(); + } + } + + /** + * 禁用监控 + * + * @returns {void} + */ + disable() { + this.enabled = false; + + // 断开长任务观察器 + if (this.longTaskObserver) { + try { + this.longTaskObserver.disconnect(); + } catch (error) { + // 静默失败 + } + this.longTaskObserver = null; + } + } +} + // ========================================================================== // 模块导出和初始化接口 // ========================================================================== @@ -861,8 +1764,8 @@ function initArgonPerformance() { ArgonPerformanceConfig.monitor.enabled = true; } - // 初始化各个模块的代码将在后续任务中添加 - console.info('Argon Performance Optimization Module Loaded'); + // 初始化调试控制台 + ArgonDebug.init(); } // 导出配置对象和类供其他模块使用 @@ -873,5 +1776,6 @@ if (typeof window !== 'undefined') { window.ArgonResourceLoader = ArgonResourceLoader; window.ArgonRenderOptimizer = ArgonRenderOptimizer; window.ArgonMemoryManager = ArgonMemoryManager; + window.ArgonPerformanceMonitor = ArgonPerformanceMonitor; window.initArgonPerformance = initArgonPerformance; } diff --git a/argontheme.js b/argontheme.js index 4ee7b4c..e1a0abc 100644 --- a/argontheme.js +++ b/argontheme.js @@ -1,9 +1,9 @@ -/*! +/*! * Argon 主题核心 JavaScript */ -// ========== 兼容性修复 ========== -// 确保 Prism 和 autoloader 存在 +// ========== 兼容性修�?========== +// 确保 Prism �?autoloader 存在 if (typeof window.Prism === 'undefined') { window.Prism = { highlightAll: function() {}, @@ -30,7 +30,7 @@ if (typeof window.Zoomify === 'undefined') { // 确保 jQuery 插件存在 if (typeof jQuery !== 'undefined') { (function($) { - // 确保 easing 函数存在(防止其他插件覆盖 jQuery 后丢失) + // 确保 easing 函数存在(防止其他插件覆�?jQuery 后丢失) if (typeof $.easing === 'undefined') { $.easing = {}; } @@ -91,6 +91,21 @@ if (typeof jQuery !== 'undefined') { })(jQuery); } +// ========================================================================== +// 性能优化模块引入 +// ========================================================================== +// 注意:argon-performance.js 需要在此文件之前加�? +// �?functions.php 中通过 wp_enqueue_script 确保加载顺序 +// +// 提供的优化功能: +// - ArgonDOMCache: DOM 元素缓存系统 +// - ArgonEventManager: 事件节流和防�? +// - ArgonResourceLoader: 资源按需加载 +// - ArgonRenderOptimizer: 渲染优化�?GPU 加�? +// - ArgonMemoryManager: 内存管理和清�? +// - ArgonPerformanceMonitor: 性能监控和分�? +// ========================================================================== + // ========== 原有代码 ========== if (typeof(argonConfig) == "undefined"){ var argonConfig = {}; @@ -98,6 +113,36 @@ if (typeof(argonConfig) == "undefined"){ if (typeof(argonConfig.wp_path) == "undefined"){ argonConfig.wp_path = "/"; } + +// ========================================================================== +// 性能优化模块实例(全局变量�? +// ========================================================================== +var argonDOMCache = null; // DOM 缓存实例 +var argonEventManager = null; // 事件管理实例 +var argonResourceLoader = null; // 资源加载实例 +var argonRenderOptimizer = null; // 渲染优化实例 +var argonMemoryManager = null; // 内存管理实例 +var argonPerformanceMonitor = null; // 性能监控实例 + +// ========================================================================== +// 调试控制台(�?argon-performance.js 引入�? +// ========================================================================== +// 如果 ArgonDebug 未定义,创建一个简单的替代实现 +if (typeof ArgonDebug === 'undefined') { + window.ArgonDebug = { + enabled: false, + init() { + if (typeof argonConfig !== 'undefined' && argonConfig.debug_mode) { + this.enabled = true; + } + }, + log(...args) { if (this.enabled) console.log('[Argon]', ...args); }, + warn(...args) { if (this.enabled) console.warn('[Argon]', ...args); }, + error(...args) { if (this.enabled) console.error('[Argon]', ...args); }, + info(...args) { if (this.enabled) console.info('[Argon]', ...args); } + }; + ArgonDebug.init(); +} /*Cookies 操作*/ function setCookie(cname, cvalue, exdays) { let d = new Date(); @@ -129,60 +174,60 @@ translation['en_US'] = { "恢复博客默认": "Set To Default", "评论内容不能为空": "Comment content cannot be empty", "昵称不能为空": "Name cannot be empty", - "邮箱或 QQ 号格式错误": "Incorrect email or QQ format", + "邮箱�?QQ 号格式错�?: "Incorrect email or QQ format", "邮箱格式错误": "Incorrect email format", - "网站格式错误 (不是 http(s):// 开头)": "Website URL format error", + "网站格式错误 (不是 http(s):// 开�?": "Website URL format error", "验证码未输入": "CAPTCHA cannot be empty", - "验证码格式错误": "Incorrect CAPTCHA format", + "验证码格式错�?: "Incorrect CAPTCHA format", "请完成验证码验证": "Please complete CAPTCHA verification", "评论格式错误": "Comment format error", "发送中": "Sending", - "正在发送": "Sending", + "正在发�?: "Sending", "评论正在发送中...": "Comment is sending...", - "发送": "Send", - "评论发送失败": "Comment failed", - "发送成功": "Success", - "您的评论已发送": "Your comment has been sent", + "发�?: "Send", + "评论发送失�?: "Comment failed", + "发送成�?: "Success", + "您的评论已发�?: "Your comment has been sent", "评论": "Comments", "未知原因": "Unknown Error", - "编辑中": "Editing", + "编辑�?: "Editing", "正在编辑": "Editing", - "评论正在编辑中...": "Comment is being edited...", + "评论正在编辑�?..": "Comment is being edited...", "编辑": "Edit", "评论编辑失败": "Comment editing failed", - "已编辑": "Edited", + "已编�?: "Edited", "编辑成功": "Success", - "您的评论已编辑": "Your comment has been edited", + "您的评论已编�?: "Your comment has been edited", "评论 #": "Comment #", - "的编辑记录": "- Edit History", + "的编辑记�?: "- Edit History", "加载失败": "Failed to load", "展开": "Show", - "没有更多了": "No more comments", + "没有更多�?: "No more comments", "找不到该 Repo": "Can't find the repository", "获取 Repo 信息失败": "Failed to get repository information", "点赞失败": "Vote failed", "Hitokoto 获取失败": "Failed to get Hitokoto", "复制成功": "Copied", - "代码已复制到剪贴板": "Code has been copied to the clipboard", + "代码已复制到剪贴�?: "Code has been copied to the clipboard", "复制失败": "Failed", - "请手动复制代码": "Please copy the code manually", + "请手动复制代�?: "Please copy the code manually", "刚刚": "Now", - "分钟前": "minutes ago", - "小时前": "hours ago", + "分钟�?: "minutes ago", + "小时�?: "hours ago", "昨天": "Yesterday", "前天": "The day before yesterday", "天前": "days ago", "隐藏行号": "Hide Line Numbers", "显示行号": "Show Line Numbers", - "开启折行": "Enable Break Line", + "开启折�?: "Enable Break Line", "关闭折行": "Disable Break Line", "复制": "Copy", "全屏": "Fullscreen", - "退出全屏": "Exit Fullscreen", + "退出全�?: "Exit Fullscreen", "置顶评论": "Pin Comment", "取消置顶评论": "Unpin Comment", - "是否要取消置顶评论 #": "Do you want to unpin the comment #", - "是否要置顶评论 #": "Do you want to pin the comment #", + "是否要取消置顶评�?#": "Do you want to unpin the comment #", + "是否要置顶评�?#": "Do you want to pin the comment #", "确认": "Confirm", "取消": "取消", "置顶": "Pin", @@ -200,55 +245,55 @@ translation['ru_RU'] = { "恢复博客默认": "Восстановить по умолчанию", "评论内容不能为空": "Содержимое комментария не может быть пустым", "昵称不能为空": "Имя не может быть пустым", - "邮箱或 QQ 号格式错误": "Неверный формат электронной почты или QQ", + "邮箱�?QQ 号格式错�?: "Неверный формат электронной почты или QQ", "邮箱格式错误": "Неправильный формат электронной почты", - "网站格式错误 (不是 http(s):// 开头)": "Сайт ошибка формата URL-адреса ", + "网站格式错误 (不是 http(s):// 开�?": "Сайт ошибка формата URL-адреса ", "验证码未输入": "Вы не решили капчу", - "验证码格式错误": "Ошибка проверки капчи", + "验证码格式错�?: "Ошибка проверки капчи", "评论格式错误": "Неправильный формат комментария", "发送中": "Отправка", - "正在发送": "Отправка", + "正在发�?: "Отправка", "评论正在发送中...": "Комментарий отправляется...", - "发送": "Отправить", - "评论发送失败": "Не удалось отправить комментарий", - "发送成功": "Комментарий отправлен", - "您的评论已发送": "Ваш комментарий был отправлен", + "发�?: "Отправить", + "评论发送失�?: "Не удалось отправить комментарий", + "发送成�?: "Комментарий отправлен", + "您的评论已发�?: "Ваш комментарий был отправлен", "评论": "Комментарии", "未知原因": "Неизвестная ошибка", - "编辑中": "Редактируется", + "编辑�?: "Редактируется", "正在编辑": "Редактируется", - "评论正在编辑中...": "Комментарий редактируется", + "评论正在编辑�?..": "Комментарий редактируется", "编辑": "Редактировать", "评论编辑失败": "Не удалось отредактировать комментарий", - "已编辑": "Изменено", + "已编�?: "Изменено", "编辑成功": "Успешно", - "您的评论已编辑": "Ваш комментарий был изменен", + "您的评论已编�?: "Ваш комментарий был изменен", "评论 #": "Комментарий #", - "的编辑记录": "- История изменений", + "的编辑记�?: "- История изменений", "加载失败": "Ошибка загрузки", "展开": "Показать", - "没有更多了": "Комментариев больше нет", + "没有更多�?: "Комментариев больше нет", "找不到该 Repo": "Невозможно найти репозиторий", "获取 Repo 信息失败": "Неудалось получить информацию репозитория", "点赞失败": "Ошибка голосования", "Hitokoto 获取失败": "Проблемы с вызовом Hitokoto", "复制成功": "Скопировано", - "代码已复制到剪贴板": "Код скопирован в буфер обмена", + "代码已复制到剪贴�?: "Код скопирован в буфер обмена", "复制失败": "Неудалось", - "请手动复制代码": "Скопируйте код вручную", + "请手动复制代�?: "Скопируйте код вручную", "刚刚": "Сейчас", - "分钟前": "минут назад", - "小时前": "часов назад", + "分钟�?: "минут назад", + "小时�?: "часов назад", "昨天": "Вчера", "前天": "Позавчера", "天前": "дней назад", "隐藏行号": "Скрыть номера строк", "显示行号": "Показать номера строк", - "开启折行": "Включить перенос строк", + "开启折�?: "Включить перенос строк", "关闭折行": "Выключить перенос строк", "复制": "Скопировать", "全屏": "Полноэкранный режим", - "退出全屏": "Выход из полноэкранного режима", + "退出全�?: "Выход из полноэкранного режима", }; translation['zh_TW'] = { "确定": "確定", @@ -256,55 +301,55 @@ translation['zh_TW'] = { "恢复博客默认": "恢復博客默認", "评论内容不能为空": "評論內容不能為空", "昵称不能为空": "昵稱不能為空", - "邮箱或 QQ 号格式错误": "郵箱或 QQ 號格式錯誤", + "邮箱�?QQ 号格式错�?: "郵箱�?QQ 號格式錯�?, "邮箱格式错误": "郵箱格式錯誤", - "网站格式错误 (不是 http(s):// 开头)": "網站格式錯誤 (不是 http(s):// 開頭)", + "网站格式错误 (不是 http(s):// 开�?": "網站格式錯誤 (不是 http(s):// 開頭)", "验证码未输入": "驗證碼未輸入", - "验证码格式错误": "驗證碼格式錯誤", + "验证码格式错�?: "驗證碼格式錯�?, "评论格式错误": "評論格式錯誤", "发送中": "發送中", - "正在发送": "正在發送", + "正在发�?: "正在發�?, "评论正在发送中...": "評論正在發送中...", - "发送": "發送", - "评论发送失败": "評論發送失敗", - "发送成功": "發送成功", - "您的评论已发送": "您的評論已發送", + "发�?: "發�?, + "评论发送失�?: "評論發送失�?, + "发送成�?: "發送成�?, + "您的评论已发�?: "您的評論已發�?, "评论": "評論", "未知原因": "未知原因", - "编辑中": "編輯中", + "编辑�?: "編輯�?, "正在编辑": "正在編輯", - "评论正在编辑中...": "評論正在編輯中...", + "评论正在编辑�?..": "評論正在編輯�?..", "编辑": "編輯", "评论编辑失败": "評論編輯失敗", - "已编辑": "已編輯", + "已编�?: "已編�?, "编辑成功": "編輯成功", - "您的评论已编辑": "您的評論已編輯", + "您的评论已编�?: "您的評論已編�?, "评论 #": "評論 #", - "的编辑记录": "的編輯記錄", + "的编辑记�?: "的編輯記�?, "加载失败": "加載失敗", "展开": "展開", - "没有更多了": "沒有更多了", + "没有更多�?: "沒有更多�?, "找不到该 Repo": "找不到該 Repo", "获取 Repo 信息失败": "獲取 Repo 信息失敗", "点赞失败": "點贊失敗", "Hitokoto 获取失败": "Hitokoto 獲取失敗", "复制成功": "復制成功", - "代码已复制到剪贴板": "代碼已復制到剪貼板", + "代码已复制到剪贴�?: "代碼已復制到剪貼�?, "复制失败": "復制失敗", - "请手动复制代码": "請手動復制代碼", + "请手动复制代�?: "請手動復制代�?, "刚刚": "剛剛", - "分钟前": "分鐘前", - "小时前": "小時前", + "分钟�?: "分鐘�?, + "小时�?: "小時�?, "昨天": "昨天", "前天": "前天", "天前": "天前", "隐藏行号": "隱藏行號", "显示行号": "顯示行號", - "开启折行": "開啟折行", + "开启折�?: "開啟折行", "关闭折行": "關閉折行", "复制": "復制", "全屏": "全屏", - "退出全屏": "退出全屏" + "退出全�?: "退出全�? }; function __(text){ let lang = argonConfig.language; @@ -317,7 +362,7 @@ function __(text){ return translation[lang][text]; } -/*根据滚动高度改变顶栏透明度*/ +/*根据滚动高度改变顶栏透明�?/ !function(){ let toolbar = document.getElementById("navbar-main"); let $bannerContainer = $("#banner_container"); @@ -377,7 +422,11 @@ function __(text){ } if ($("html").hasClass("no-banner")) { changeToolbarOnTopClass(); - document.addEventListener("scroll", changeToolbarOnTopClass, {passive: true}); + // 使用节流优化滚动事件性能 + const throttledChangeToolbarOnTopClass = argonEventManager ? + argonEventManager.throttle(changeToolbarOnTopClass, 16) : + changeToolbarOnTopClass; + document.addEventListener("scroll", throttledChangeToolbarOnTopClass, {passive: true}); return; } if (argonConfig.headroom == "absolute") { @@ -391,7 +440,11 @@ function __(text){ argonConfig.toolbar_blur = false; } changeToolbarTransparency(); - document.addEventListener("scroll", changeToolbarTransparency, {passive: true}); + // 使用节流优化滚动事件性能 + const throttledChangeToolbarTransparency = argonEventManager ? + argonEventManager.throttle(changeToolbarTransparency, 16) : + changeToolbarTransparency; + document.addEventListener("scroll", throttledChangeToolbarTransparency, {passive: true}); }(); /*搜索*/ @@ -414,7 +467,7 @@ $(document).on("click" , "#navbar_search_input_container" , function(){ $("#navbar_search_input").focus(); }); $(document).on("blur" , "#navbar_search_input_container" , function(){ - // 如果有文字则保持has-text类 + // 如果有文字则保持has-text�? if ($("#navbar_search_input").val().trim() !== "") { $(this).addClass("has-text"); } else { @@ -422,7 +475,7 @@ $(document).on("blur" , "#navbar_search_input_container" , function(){ } $(this).removeClass("open"); }); -// 监听输入变化来切换has-text类 +// 监听输入变化来切换has-text�? $(document).on("input" , "#navbar_search_input" , function(){ var container = $("#navbar_search_input_container"); if ($(this).val().trim() !== "") { @@ -480,7 +533,7 @@ $(document).on("keydown" , "#leftbar_search_input" , function(e){ $("html").removeClass("leftbar-opened"); searchPosts(word); }); -/*搜索过滤器*/ +/*搜索过滤�?/ $(document).on("change" , ".search-filter" , function(e){ if (pjaxLoading){ $(this).prop("checked", !$(this).prop("checked")); @@ -516,7 +569,11 @@ $(document).on("change" , ".search-filter" , function(e){ } } changeLeftbarStickyStatusWithoutSidebar(); - document.addEventListener("scroll", changeLeftbarStickyStatusWithoutSidebar, {passive: true}); + // 使用节流优化滚动事件性能 + const throttledChangeLeftbarStickyStatusWithoutSidebar = argonEventManager ? + argonEventManager.throttle(changeLeftbarStickyStatusWithoutSidebar, 16) : + changeLeftbarStickyStatusWithoutSidebar; + document.addEventListener("scroll", throttledChangeLeftbarStickyStatusWithoutSidebar, {passive: true}); $(window).resize(function(){ contentOffsetTop = $('#content').offset().top; changeLeftbarStickyStatusWithoutSidebar(); @@ -535,21 +592,21 @@ $(document).on("change" , ".search-filter" , function(e){ function changeLeftbarStickyStatus(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if( part1OffsetTop + part1OuterHeight + 10 - scrollTop <= (argonConfig.headroom != "absolute" ? 90 : 18) ){ - //滚动条在页面中间浮动状态 + //滚动条在页面中间浮动状�? leftbarPart2.classList.add('sticky'); if (leftbarPart3) { leftbarPart3.classList.add('sticky'); - // 计算可用空间并分配给 part2 和 part3 + // 计算可用空间并分配给 part2 �?part3 let viewportHeight = window.innerHeight; let topOffset = argonConfig.headroom !== 'absolute' ? 90 : 20; let availableHeight = viewportHeight - topOffset - 20; // 20px 底部边距 - // 获取 part3 的自然高度(不受限制时的高度) + // 获取 part3 的自然高度(不受限制时的高度�? leftbarPart3.style.maxHeight = 'none'; let part3NaturalHeight = leftbarPart3.scrollHeight; leftbarPart3.style.maxHeight = ''; - // 最小高度限制 + // 最小高度限�? let minPart2Height = 150; let minPart3Height = 100; @@ -560,7 +617,7 @@ $(document).on("change" , ".search-filter" , function(e){ part3MaxHeight = part3NaturalHeight; part2Height = availableHeight - part3NaturalHeight - 10; } else { - // 需要按比例分配,part2 占 60%,part3 占 40% + // 需要按比例分配,part2 �?60%,part3 �?40% part2Height = Math.max(minPart2Height, availableHeight * 0.6); part3MaxHeight = Math.max(minPart3Height, availableHeight - part2Height - 10); } @@ -570,18 +627,22 @@ $(document).on("change" , ".search-filter" , function(e){ document.documentElement.style.setProperty('--leftbar-part3-max-height', part3MaxHeight + 'px'); } }else{ - //滚动条在顶部 不浮动状态 + //滚动条在顶部 不浮动状�? leftbarPart2.classList.remove('sticky'); if (leftbarPart3) leftbarPart3.classList.remove('sticky'); } - if( part1OffsetTop + part1OuterHeight + 10 - scrollTop <= 20 ){//侧栏下部分是否可以随 Headroom 一起向上移动 + if( part1OffsetTop + part1OuterHeight + 10 - scrollTop <= 20 ){//侧栏下部分是否可以随 Headroom 一起向上移�? document.body.classList.add('leftbar-can-headroom'); }else{ document.body.classList.remove('leftbar-can-headroom'); } } changeLeftbarStickyStatus(); - document.addEventListener("scroll", changeLeftbarStickyStatus, {passive: true}); + // 使用节流优化滚动事件性能 + const throttledChangeLeftbarStickyStatus = argonEventManager ? + argonEventManager.throttle(changeLeftbarStickyStatus, 16) : + changeLeftbarStickyStatus; + document.addEventListener("scroll", throttledChangeLeftbarStickyStatus, {passive: true}); $(window).resize(function(){ part1OffsetTop = $leftbarPart1.offset().top; part1OuterHeight = $leftbarPart1.outerHeight(); @@ -723,18 +784,16 @@ if (argonConfig.waterflow_columns != "1") { }); }(); -/*浮动按钮栏相关 (回顶等)*/ +/*浮动按钮栏相�?(回顶�?*/ !function(){ - // 确保 DOM 和 jQuery 已加载 + // 确保 DOM �?jQuery 已加�? if (typeof jQuery === 'undefined') { - console.warn('jQuery not loaded, retrying...'); setTimeout(arguments.callee, 50); return; } let $fabtns = $('#float_action_buttons'); if ($fabtns.length === 0) { - console.warn('Float action buttons not found, retrying...'); setTimeout(arguments.callee, 50); return; } @@ -789,7 +848,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_content").focus(); }, 150); } else { - // 已展开或无切换按钮:直接滚动到评论框 + // 已展开或无切换按钮:直接滚动到评论�? $("body,html").stop().animate({ scrollTop: postCommentArea.offset().top - 80 }, 600); @@ -858,14 +917,14 @@ if (argonConfig.waterflow_columns != "1") { $("#blog_setting_filters .blog-setting-filter-btn[filter-name='" + name + "']").addClass("active"); localStorage['Argon_Filter'] = name; } - // 滤镜设置已在 header.php 中预加载,此处只需设置按钮状态 + // 滤镜设置已在 header.php 中预加载,此处只需设置按钮状�? let currentFilter = localStorage['Argon_Filter'] || 'off'; $("#blog_setting_filters .blog-setting-filter-btn[filter-name='" + currentFilter + "']").addClass("active"); $(".blog-setting-filter-btn").on("click" , function(){ setBlogFilter(this.getAttribute("filter-name")); }); - //UI 样式切换 (玻璃拟态/新拟态) + //UI 样式切换 (玻璃拟�?新拟�? function setUIStyle(style){ if (style == undefined || style == ""){ style = "default"; @@ -878,7 +937,7 @@ if (argonConfig.waterflow_columns != "1") { $(".blog-setting-style-btn[style-name='" + style + "']").addClass("active"); localStorage['Argon_UI_Style'] = style; } - // UI 样式设置已在 header.php 中预加载,此处只需设置按钮状态 + // UI 样式设置已在 header.php 中预加载,此处只需设置按钮状�? let currentUIStyle = localStorage['Argon_UI_Style'] || 'default'; $(".blog-setting-style-btn[style-name='" + currentUIStyle + "']").addClass("active"); $(".blog-setting-style-btn").on("click" , function(){ @@ -963,13 +1022,13 @@ if (argonConfig.waterflow_columns != "1") { }); }(); -/*评论区 & 发送评论*/ +/*评论�?& 发送评�?/ !function(){ //回复评论 let replying = false , replyID = 0; /** - * 显示回复框 + * 显示回复�? * @param {number} commentID - 评论ID */ function reply(commentID){ @@ -993,7 +1052,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment").addClass("post-comment-force-privatemode-off"); } - // 滚动到评论框(使用原生 scrollTo 避免 jQuery easing 依赖问题) + // 滚动到评论框(使用原�?scrollTo 避免 jQuery easing 依赖问题�? let postComment = $('#post_comment'); if (postComment.length > 0 && postComment.offset()) { let targetTop = postComment.offset().top - 100; @@ -1003,11 +1062,11 @@ if (argonConfig.waterflow_columns != "1") { }); } - // 使用 CSS 动画显示回复框 + // 使用 CSS 动画显示回复�? let replyInfo = $('#post_comment_reply_info'); if (replyInfo.length > 0) { replyInfo.removeClass('reply-leaving').css('display', 'block'); - // 触发重排以确保动画生效 + // 触发重排以确保动画生�? replyInfo[0].offsetHeight; replyInfo.addClass('reply-entering'); } @@ -1106,10 +1165,10 @@ if (argonConfig.waterflow_columns != "1") { $(document).on("mouseleave", ".comment-parent-info", function(){ $("#comment-" + this.getAttribute("data-parent-id")).removeClass("highlight"); }); - //切换评论置顶状态 + //切换评论置顶状�? function toogleCommentPin(commentID, pinned){ $("#comment_pin_comfirm_dialog .modal-title").html(pinned ? __("取消置顶评论") : __("置顶评论")); - $("#comment_pin_comfirm_dialog .modal-body").html(pinned ? __("是否要取消置顶评论 #") + commentID + "?" : __("是否要置顶评论 #") + commentID + "?"); + $("#comment_pin_comfirm_dialog .modal-body").html(pinned ? __("是否要取消置顶评�?#") + commentID + "?" : __("是否要置顶评�?#") + commentID + "?"); $("#comment_pin_comfirm_dialog .btn-comfirm").html(__("确认")).attr("disabled", false); $("#comment_pin_comfirm_dialog .btn-dismiss").html(__("取消")).attr("disabled", false); $("#comment_pin_comfirm_dialog .btn-comfirm").off("click").on("click", function(){ @@ -1185,7 +1244,7 @@ if (argonConfig.waterflow_columns != "1") { } - //显示/隐藏额外输入框 (评论者网站) + //显示/隐藏额外输入�?(评论者网�? $(document).on("click" , "#post_comment_toggle_extra_input" , function(){ $("#post_comment").toggleClass("show-extra-input"); if ($("#post_comment").hasClass("show-extra-input")){ @@ -1195,7 +1254,7 @@ if (argonConfig.waterflow_columns != "1") { } }); - //输入框细节 + //输入框细�? $(document).on("change input keydown keyup propertychange" , "#post_comment_content" , function(){ $("#post_comment_content_hidden")[0].innerText = $("#post_comment_content").val() + "\n"; $("#post_comment_content").css("height" , $("#post_comment_content_hidden").outerHeight()); @@ -1213,7 +1272,7 @@ if (argonConfig.waterflow_columns != "1") { $(".post-comment-captcha-container").removeClass("active"); }); - //发送评论 + //发送评�? window.postComment = function postComment(){ let commentContent = $("#post_comment_content").val(); let commentName = $("#post_comment_name").val(); @@ -1239,7 +1298,7 @@ if (argonConfig.waterflow_columns != "1") { let isError = false; let errorMsg = ""; - //检查表单合法性 + //检查表单合法�? if (commentContent.match(/^\s*$/)){ isError = true; errorMsg += __("评论内容不能为空") + "
"; @@ -1252,7 +1311,7 @@ if (argonConfig.waterflow_columns != "1") { if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; - errorMsg += __("邮箱或 QQ 号格式错误") + "
"; + errorMsg += __("邮箱�?QQ 号格式错�?) + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ @@ -1265,7 +1324,7 @@ if (argonConfig.waterflow_columns != "1") { if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; - errorMsg += __("邮箱或 QQ 号格式错误") + "
"; + errorMsg += __("邮箱�?QQ 号格式错�?) + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ @@ -1277,20 +1336,20 @@ if (argonConfig.waterflow_columns != "1") { } if (commentLink != "" && !(/https?:\/\//).test(commentLink)){ isError = true; - errorMsg += __("网站格式错误 (不是 http(s):// 开头)") + "
"; + errorMsg += __("网站格式错误 (不是 http(s):// 开�?") + "
"; } if (!$("#post_comment").hasClass("no-need-captcha")){ - // 检查是否使用Geetest验证码 + // 检查是否使用Geetest验证�? if ($("#geetest-captcha").length > 0) { - // 检查Geetest库是否加载成功 + // 检查Geetest库是否加载成�? if (typeof window.geetestLoadFailed !== 'undefined' && window.geetestLoadFailed) { isError = true; errorMsg += __("验证码服务不可用,请刷新页面重试"); } else if (typeof window.geetestCaptcha === 'undefined' || !window.geetestCaptcha) { isError = true; - errorMsg += __("验证码未初始化,请稍后重试"); + errorMsg += __("验证码未初始化,请稍后重�?); } else { - // Geetest验证码检查 + // Geetest验证码检�? let lotNumber = $("#geetest_lot_number").val(); let captchaOutput = $("#geetest_captcha_output").val(); let passToken = $("#geetest_pass_token").val(); @@ -1302,19 +1361,19 @@ if (argonConfig.waterflow_columns != "1") { } } } else { - // 原有的数学验证码检查 + // 原有的数学验证码检�? if (commentCaptcha == ""){ isError = true; errorMsg += __("验证码未输入"); } if (commentCaptcha != "" && !(/^[0-9]+$/).test(commentCaptcha)){ isError = true; - errorMsg += __("验证码格式错误"); + errorMsg += __("验证码格式错�?); } } } if (isError){ - // 确保按钮和表单元素处于可用状态 + // 确保按钮和表单元素处于可用状�? $("#post_comment_send").removeAttr("disabled"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); @@ -1324,7 +1383,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment").removeClass("sending"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); iziToast.show({ title: __("评论格式错误"), @@ -1342,7 +1401,7 @@ if (argonConfig.waterflow_columns != "1") { return; } - //增加 disabled 属性和其他的表单提示 + //增加 disabled 属性和其他的表单提�? $("#post_comment").addClass("sending"); $("#post_comment_content").attr("disabled","disabled"); $("#post_comment_name").attr("disabled","disabled"); @@ -1355,7 +1414,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送中")); iziToast.show({ - title: __("正在发送"), + title: __("正在发�?), message: __("评论正在发送中..."), class: 'shadow-sm iziToast-noprogressbar', position: 'topRight', @@ -1385,11 +1444,11 @@ if (argonConfig.waterflow_columns != "1") { argon_nonce: $("#argon_comment_nonce").val() }; - // 根据验证码类型添加相应参数 + // 根据验证码类型添加相应参�? if ($("#geetest-captcha").length > 0) { - // 检查Geetest库加载状态 + // 检查Geetest库加载状�? if (typeof window.geetestLoadFailed !== 'undefined' && window.geetestLoadFailed) { - // 重新启用按钮和表单元素 + // 重新启用按钮和表单元�? $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); @@ -1399,24 +1458,24 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); setTimeout(function() { try { iziToast.destroy(); iziToast.error({ - title: __('评论发送失败'), + title: __('评论发送失�?), message: __('验证码服务不可用,请刷新页面重试'), position: 'topRight' }); } catch (e) { - console.warn('iziToast error:', e); + ArgonDebug.warn('iziToast error:', e); } }, 0); return false; } - // Geetest验证码参数 - 使用后端期望的参数名 + // Geetest验证码参�?- 使用后端期望的参数名 ajaxData.lot_number = $("#geetest_lot_number").val(); ajaxData.captcha_output = $("#geetest_captcha_output").val(); ajaxData.pass_token = $("#geetest_pass_token").val(); @@ -1424,7 +1483,7 @@ if (argonConfig.waterflow_columns != "1") { // 验证Geetest参数是否完整 if (!ajaxData.lot_number || !ajaxData.captcha_output || !ajaxData.pass_token || !ajaxData.gen_time) { - // 重新启用按钮和表单元素 + // 重新启用按钮和表单元�? $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); @@ -1434,25 +1493,25 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); // 使用 setTimeout 确保 iziToast 操作在下一个事件循环中执行 setTimeout(function() { try { iziToast.destroy(); iziToast.error({ - title: __('评论发送失败'), + title: __('评论发送失�?), message: __('请完成验证码验证'), position: 'topRight' }); } catch (e) { - console.warn('iziToast error:', e); + ArgonDebug.warn('iziToast error:', e); } }, 0); return false; } } else { - // 原有数学验证码参数 + // 原有数学验证码参�? ajaxData.comment_captcha_seed = commentCaptchaSeed; ajaxData.comment_captcha = commentCaptcha; } @@ -1471,20 +1530,20 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); $("#post_comment").removeClass("show-extra-input post-comment-force-privatemode-on post-comment-force-privatemode-off"); if (!result.isAdmin){ $("#post_comment_captcha").removeAttr("disabled"); } - //判断是否有错误 + //判断是否有错�? if (result.status == "failed"){ // 使用 setTimeout 确保 iziToast 操作在下一个事件循环中执行 setTimeout(function() { try { iziToast.destroy(); iziToast.show({ - title: __("评论发送失败"), + title: __("评论发送失�?), message: result.msg, class: 'shadow-sm', position: 'topRight', @@ -1497,20 +1556,20 @@ if (argonConfig.waterflow_columns != "1") { timeout: 5000 }); } catch (e) { - console.warn('iziToast error:', e); + ArgonDebug.warn('iziToast error:', e); } }, 0); return; } - //发送成功 + //发送成�? // 使用 setTimeout 确保 iziToast 操作在下一个事件循环中执行 setTimeout(function() { try { iziToast.destroy(); iziToast.show({ - title: __("发送成功"), - message: __("您的评论已发送"), + title: __("发送成�?), + message: __("您的评论已发�?), class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', @@ -1521,7 +1580,7 @@ if (argonConfig.waterflow_columns != "1") { icon: 'fa fa-check', timeout: 5000 }); - //插入新评论 + //插入新评�? result.html = result.html.replace(/<(\/).noscript>/g, ""); let parentID = result.parentID; if (parentID == "" || parentID == null){ @@ -1552,7 +1611,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_captcha + style").html(".post-comment-captcha-container:before{content: '" + result.newCaptcha + "';}"); $("#post_comment_captcha").val(result.newCaptchaAnswer); - // 清空Geetest验证码隐藏字段 + // 清空Geetest验证码隐藏字�? if ($("#geetest-captcha").length > 0) { $("#geetest_lot_number").val(""); $("#geetest_captcha_output").val(""); @@ -1567,7 +1626,7 @@ if (argonConfig.waterflow_columns != "1") { scrollTop: $("#comment-" + result.id).offset().top - 100 }, 500, 'easeOutExpo'); } catch (e) { - console.warn('Comment insertion error:', e); + ArgonDebug.warn('Comment insertion error:', e); } }, 0); }, @@ -1580,13 +1639,13 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); $("#post_comment").removeClass("show-extra-input post-comment-force-privatemode-on post-comment-force-privatemode-off"); if (!result.isAdmin){ $("#post_comment_captcha").removeAttr("disabled"); } - // 重置Geetest验证状态 + // 重置Geetest验证状�? window.geetestVerified = false; // 重置自动提交标记 window.geetestAutoSubmitting = false; @@ -1594,17 +1653,17 @@ if (argonConfig.waterflow_columns != "1") { $("#geetest_captcha_output").val(""); $("#geetest_pass_token").val(""); $("#geetest_gen_time").val(""); - // 重置 Geetest 实例,确保下一次生成新的 pass_token + // 重置 Geetest 实例,确保下一次生成新�?pass_token if (window.geetestCaptcha) { try { window.geetestCaptcha.reset(); } catch (e) {} } - // 安全地处理 iziToast 操作,防止 time 属性错误 + // 安全地处�?iziToast 操作,防�?time 属性错�? setTimeout(function() { try { iziToast.destroy(); iziToast.show({ - title: __("评论发送失败"), + title: __("评论发送失�?), message: __("未知原因"), class: 'shadow-sm', position: 'topRight', @@ -1617,7 +1676,7 @@ if (argonConfig.waterflow_columns != "1") { timeout: 5000 }); } catch (e) { - console.warn('iziToast operation error:', e); + ArgonDebug.warn('iziToast operation error:', e); } }, 10); return; @@ -1650,16 +1709,16 @@ if (argonConfig.waterflow_columns != "1") { return; } - //增加 disabled 属性和其他的表单提示 + //增加 disabled 属性和其他的表单提�? $("#post_comment_content").attr("disabled","disabled"); $("#post_comment_send").attr("disabled","disabled"); $("#post_comment_edit_cancel").attr("disabled","disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-not-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑中")); + $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑�?)); iziToast.show({ title: __("正在编辑"), - message: __("评论正在编辑中..."), + message: __("评论正在编辑�?.."), class: 'shadow-sm iziToast-noprogressbar', position: 'topRight', backgroundColor: 'var(--themecolor)', @@ -1688,7 +1747,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_send .btn-inner--icon.hide-on-comment-not-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑")); - //判断是否有错误 + //判断是否有错�? if (result.status == "failed"){ iziToast.destroy(); iziToast.show({ @@ -1707,12 +1766,12 @@ if (argonConfig.waterflow_columns != "1") { return; } - //发送成功,替换原评论 + //发送成功,替换原评�? result.new_comment = result.new_comment.replace(/<(\/).noscript>/g, ""); $("#comment-" + editID + " .comment-item-text").html(result.new_comment); $("#comment-" + editID + " .comment-item-source").html(result.new_comment_source); if ($("#comment-" + editID + " .comment-info .comment-edited").length == 0){ - $("#comment-" + editID + " .comment-info").prepend("
" + __("已编辑") + "
") + $("#comment-" + editID + " .comment-info").prepend("
" + __("已编�?) + "
") } if (result.can_visit_edit_history){ $("#comment-" + editID + " .comment-info .comment-edited").addClass("comment-edithistory-accessible"); @@ -1721,7 +1780,7 @@ if (argonConfig.waterflow_columns != "1") { iziToast.destroy(); iziToast.show({ title: __("编辑成功"), - message: __("您的评论已编辑"), + message: __("您的评论已编�?), class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', @@ -1771,7 +1830,7 @@ if (argonConfig.waterflow_columns != "1") { if ($("#post_comment").hasClass("editing")){ editComment(); }else{ - // 首先进行基本的表单验证 + // 首先进行基本的表单验�? let commentContent = $("#post_comment_content").val(); let commentName = $("#post_comment_name").val(); let commentEmail = $("#post_comment_email").val(); @@ -1780,7 +1839,7 @@ if (argonConfig.waterflow_columns != "1") { let isError = false; let errorMsg = ""; - // 检查表单合法性 + // 检查表单合法�? if (commentContent.match(/^\s*$/)){ isError = true; errorMsg += __("评论内容不能为空") + "
"; @@ -1793,7 +1852,7 @@ if (argonConfig.waterflow_columns != "1") { if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; - errorMsg += __("邮箱或 QQ 号格式错误") + "
"; + errorMsg += __("邮箱�?QQ 号格式错�?) + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ @@ -1806,7 +1865,7 @@ if (argonConfig.waterflow_columns != "1") { if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; - errorMsg += __("邮箱或 QQ 号格式错误") + "
"; + errorMsg += __("邮箱�?QQ 号格式错�?) + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ @@ -1818,12 +1877,12 @@ if (argonConfig.waterflow_columns != "1") { } if (commentLink != "" && !(/https?:\/\//).test(commentLink)){ isError = true; - errorMsg += __("网站格式错误 (不是 http(s):// 开头)") + "
"; + errorMsg += __("网站格式错误 (不是 http(s):// 开�?") + "
"; } // 如果基本表单验证失败,显示错误信息并返回 if (isError){ - // 确保按钮和表单元素处于可用状态 + // 确保按钮和表单元素处于可用状�? $("#post_comment_send").removeAttr("disabled"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); @@ -1833,7 +1892,7 @@ if (argonConfig.waterflow_columns != "1") { $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment").removeClass("sending"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); - $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); + $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发�?)); iziToast.show({ title: __("评论格式错误"), @@ -1853,7 +1912,7 @@ if (argonConfig.waterflow_columns != "1") { // 基本验证通过后,检查验证码 if ($("#geetest-captcha").length > 0) { - // 检查 Geetest 库是否加载失败 + // 检�?Geetest 库是否加载失�? if (window.geetestLoadFailed) { if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { try { @@ -1873,13 +1932,13 @@ if (argonConfig.waterflow_columns != "1") { return; } - // 如果使用Geetest,检查验证码是否已完成 + // 如果使用Geetest,检查验证码是否已完�? if (!window.geetestVerified) { // 验证码未完成,触发验证码显示 if (window.geetestCaptcha) { - // 重置验证码状态 + // 重置验证码状�? window.geetestCaptcha.reset(); - // 然后显示验证码 + // 然后显示验证�? window.geetestCaptcha.showBox(); } else { if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { @@ -1896,7 +1955,7 @@ if (argonConfig.waterflow_columns != "1") { return; } } - // 验证码已完成或不需要验证码,直接提交评论 + // 验证码已完成或不需要验证码,直接提交评�? postComment(); } }); @@ -2019,8 +2078,8 @@ document.addEventListener('click', (e) => { function showCommentEditHistory(id){ let requestID = parseInt(new Date().getTime()); $("#comment_edit_history").data("request-id", requestID); - $("#comment_edit_history .modal-title").html(__("评论 #") + id + " " + __("的编辑记录")); - $("#comment_edit_history .modal-body").html("
加载中
"); + $("#comment_edit_history .modal-title").html(__("评论 #") + id + " " + __("的编辑记�?)); + $("#comment_edit_history .modal-body").html("
加载�?/span>
"); $("#comment_edit_history").modal(null); $.ajax({ type: 'POST', @@ -2169,7 +2228,7 @@ $(document).on("submit" , ".post-password-form" , function(){ $("#comments > .card-body > ol.comment-list").append($("#comments > .card-body > ol.comment-list", $vdom).html()); if ($("#comments_more", $vdom).length == 0){ $("#comments_more").remove(); - $(".comments-navigation-more").html("
" + __("没有更多了") + "
"); + $(".comments-navigation-more").html("
" + __("没有更多�?) + "
"); }else{ $("#comments_more").attr("href", $("#comments_more", $vdom).attr("href")); $("#comments_more").removeAttr("disabled"); @@ -2185,7 +2244,7 @@ $(document).on("submit" , ".post-password-form" , function(){ }); }(); -/*URL 中 # 根据 ID 定位*/ +/*URL �?# 根据 ID 定位*/ function gotoHash(hash, durtion, easing = 'easeOutExpo'){ if (hash.length == 0){ return; @@ -2233,7 +2292,7 @@ function showPostOutdateToast(){ showPostOutdateToast(); /*Zoomify*/ -// 全局 Zoomify 实例数组,用于清理 +// 全局 Zoomify 实例数组,用于清�? var zoomifyInstances = []; function zoomifyInit(){ @@ -2287,29 +2346,29 @@ $.fancybox.defaults.i18n = { }, zh_CN: { CLOSE: "关闭", - NEXT: "下一张", - PREV: "上一张", + NEXT: "下一�?, + PREV: "上一�?, ERROR: "图片加载失败", PLAY_START: "开始幻灯片展示", - PLAY_STOP: "暂停幻灯片展示", + PLAY_STOP: "暂停幻灯片展�?, FULL_SCREEN: "全屏", - THUMBS: "缩略图", + THUMBS: "缩略�?, DOWNLOAD: "下载", SHARE: "分享", ZOOM: "缩放" } }; -/*Lazyload - 使用 IntersectionObserver 实现懒加载*/ +/*Lazyload - 使用 IntersectionObserver 实现懒加�?/ /* - * 优化说明: - * 1. 使用全局 lazyloadObserver 变量,便于在 PJAX 切换时清理 - * 2. 添加 Observer 存在性检查,防止重复初始化 + * 优化说明�? + * 1. 使用全局 lazyloadObserver 变量,便于在 PJAX 切换时清�? + * 2. 添加 Observer 存在性检查,防止重复初始�? * 3. 使用 requestAnimationFrame 替代 setTimeout 实现加载效果 * 4. 实现滚动监听降级方案,支持不兼容 IntersectionObserver 的浏览器 - * 5. 使用 transitionend 事件清理样式,避免固定延迟 + * 5. 使用 transitionend 事件清理样式,避免固定延�? */ -// 全局 Observer 实例,用于清理 +// 全局 Observer 实例,用于清�? var lazyloadObserver = null; function lazyloadInit() { @@ -2321,7 +2380,7 @@ function lazyloadInit() { // 检查是否启用懒加载 if (argonConfig.lazyload === false || argonConfig.lazyload === 'false') { - // 未启用懒加载时,直接加载所有图片 + // 未启用懒加载时,直接加载所有图�? loadAllImagesImmediately(); return; } @@ -2334,7 +2393,7 @@ function lazyloadInit() { let effect = argonConfig.lazyload_effect || 'fadeIn'; let threshold = parseInt(argonConfig.lazyload_threshold) || 800; - // 使用 IntersectionObserver 实现懒加载 + // 使用 IntersectionObserver 实现懒加�? if ('IntersectionObserver' in window) { lazyloadObserver = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { @@ -2349,43 +2408,43 @@ function lazyloadInit() { }); images.forEach(function(img) { - // 重置图片状态 + // 重置图片状�? img.style.opacity = ''; img.style.transform = ''; img.style.transition = ''; lazyloadObserver.observe(img); }); } else { - // 降级方案:使用滚动监听 + // 降级方案:使用滚动监�? lazyloadFallback(images, effect, threshold); } } /** - * 优化的图片加载函数 + * 优化的图片加载函�? * 使用 requestAnimationFrame 替代 setTimeout * @param {HTMLImageElement} img - 图片元素 - * @param {string} effect - 加载效果类型 ('fadeIn' 或 'slideDown') + * @param {string} effect - 加载效果类型 ('fadeIn' �?'slideDown') */ function loadImageOptimized(img, effect) { let src = img.getAttribute('data-src'); if (!src) return; - // 预加载图片 + // 预加载图�? let tempImg = new Image(); tempImg.onload = function() { img.src = src; img.removeAttribute('data-src'); img.classList.remove('lazyload'); - // 移除所有 lazyload-style-* 类 + // 移除所�?lazyload-style-* �? img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim(); // 使用 requestAnimationFrame 应用加载效果 applyLoadEffectOptimized(img, effect); }; tempImg.onerror = function() { - // 加载失败时使用原始 src + // 加载失败时使用原�?src img.src = src; img.removeAttribute('data-src'); img.classList.remove('lazyload'); @@ -2397,7 +2456,7 @@ function loadImageOptimized(img, effect) { /** * 使用 requestAnimationFrame 应用加载效果 * @param {HTMLImageElement} img - 图片元素 - * @param {string} effect - 加载效果类型 ('fadeIn' 或 'slideDown') + * @param {string} effect - 加载效果类型 ('fadeIn' �?'slideDown') */ function applyLoadEffectOptimized(img, effect) { if (effect === 'fadeIn') { @@ -2434,10 +2493,10 @@ function applyLoadEffectOptimized(img, effect) { /** * 降级方案:使用滚动监听实现懒加载 - * 当浏览器不支持 IntersectionObserver 时使用 - * @param {NodeList|Array} images - 需要懒加载的图片元素列表 + * 当浏览器不支�?IntersectionObserver 时使�? + * @param {NodeList|Array} images - 需要懒加载的图片元素列�? * @param {string} effect - 加载效果类型 - * @param {number} threshold - 提前加载的阈值(像素) + * @param {number} threshold - 提前加载的阈值(像素�? */ function lazyloadFallback(images, effect, threshold) { let loadedImages = new Set(); @@ -2457,26 +2516,21 @@ function lazyloadFallback(images, effect, threshold) { }); } - // 使用节流函数优化性能 - let throttleTimer = null; - function throttledCheck() { - if (throttleTimer) return; - throttleTimer = setTimeout(function() { - checkImagesInView(); - throttleTimer = null; - }, 100); - } + // 使用 eventManager 的节流函数优化性能 + const throttledCheck = argonEventManager ? + argonEventManager.throttle(checkImagesInView, 100) : + checkImagesInView; - // 绑定事件监听器 + // 绑定事件监听�? window.addEventListener('scroll', throttledCheck, {passive: true}); window.addEventListener('resize', throttledCheck, {passive: true}); - // 立即检查一次 + // 立即检查一�? checkImagesInView(); } /** - * 立即加载所有图片(懒加载禁用时) + * 立即加载所有图片(懒加载禁用时�? * 不应用任何加载效果,直接替换 src */ function loadAllImagesImmediately() { @@ -2589,9 +2643,9 @@ if ($("html").hasClass("banner-as-cover")){ var pjaxScrollTop = 0, pjaxLoading = false; /** - * 清理 PJAX 页面切换前的所有资源 + * 清理 PJAX 页面切换前的所有资�? * 包括 LazyLoad Observer、Zoomify 实例、Tippy 实例 - * 在 pjax:beforeReplace 事件中调用 + * �?pjax:beforeReplace 事件中调�? */ function cleanupPjaxResources() { // 清理 LazyLoad Observer @@ -2608,7 +2662,7 @@ function cleanupPjaxResources() { instance.destroy(); } } catch(e) { - console.warn('Failed to destroy Zoomify instance:', e); + ArgonDebug.warn('Failed to destroy Zoomify instance:', e); } }); zoomifyInstances = []; @@ -2623,7 +2677,7 @@ function cleanupPjaxResources() { el._tippy.destroy(); } } catch(e) { - console.warn('Failed to destroy Tippy instance:', e); + ArgonDebug.warn('Failed to destroy Tippy instance:', e); } }); $('.tippy-initialized').removeClass('tippy-initialized'); @@ -2631,9 +2685,9 @@ function cleanupPjaxResources() { } /** - * 重置 GT4 验证码 + * 重置 GT4 验证�? * 清理状态变量、隐藏字段和容器,然后重新初始化 - * 在 pjax:end 事件中调用 + * �?pjax:end 事件中调�? */ function resetGT4Captcha() { try { @@ -2642,16 +2696,16 @@ function resetGT4Captcha() { window.geetestVerified = false; window.geetestAutoSubmitting = false; - // 清空隐藏字段,防止残留导致 pass_token 复用 + // 清空隐藏字段,防止残留导�?pass_token 复用 $('#geetest_lot_number').val(''); $('#geetest_captcha_output').val(''); $('#geetest_pass_token').val(''); $('#geetest_gen_time').val(''); - // 清空容器,防止重复 appendTo 导致多个实例 + // 清空容器,防止重�?appendTo 导致多个实例 $('#geetest-captcha').empty(); - // 若页面脚本已提供初始化方法,则调用以加载验证码 + // 若页面脚本已提供初始化方法,则调用以加载验证�? if (typeof initGeetestCaptcha === 'function') { initGeetestCaptcha(); } else if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { @@ -2661,7 +2715,7 @@ function resetGT4Captcha() { } } } catch (e) { - console.warn('Geetest init on PJAX failed:', e); + ArgonDebug.warn('Geetest init on PJAX failed:', e); } } @@ -2670,8 +2724,8 @@ $.pjax.defaults.container = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_ $.pjax.defaults.fragment = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar']; /* - * PJAX 事件处理优化说明: - * 1. pjax:beforeReplace - 统一清理资源(LazyLoad Observer、Zoomify、Tippy) + * PJAX 事件处理优化说明�? + * 1. pjax:beforeReplace - 统一清理资源(LazyLoad Observer、Zoomify、Tippy�? * 2. pjax:complete - 单次初始化所有功能模块,添加错误处理 * 3. pjax:end - 只处理特定任务(移动端目录重置、GT4 验证码重置) * 4. 移除了重复的初始化调用,避免资源泄漏和性能问题 @@ -2721,7 +2775,7 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no // 清理旧页面的资源 cleanupPjaxResources(); - // 更新 UI 状态 + // 更新 UI 状�? if ($("#post_comment", dom[0]).length > 0){ $("#fabtn_go_to_comment").removeClass("d-none"); }else{ @@ -2759,18 +2813,18 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no }catch (err){} // 初始化各个功能模块(添加错误处理确保单个模块失败不影响其他模块) - try { waterflowInit(); } catch (err) { console.error('waterflowInit failed:', err); } - try { lazyloadInit(); } catch (err) { console.error('lazyloadInit failed:', err); } - try { zoomifyInit(); } catch (err) { console.error('zoomifyInit failed:', err); } - try { highlightJsRender(); } catch (err) { console.error('highlightJsRender failed:', err); } - try { panguInit(); } catch (err) { console.error('panguInit failed:', err); } - try { clampInit(); } catch (err) { console.error('clampInit failed:', err); } - try { tippyInit(); } catch (err) { console.error('tippyInit failed:', err); } - try { getGithubInfoCardContent(); } catch (err) { console.error('getGithubInfoCardContent failed:', err); } - try { showPostOutdateToast(); } catch (err) { console.error('showPostOutdateToast failed:', err); } - try { calcHumanTimesOnPage(); } catch (err) { console.error('calcHumanTimesOnPage failed:', err); } - try { foldLongComments(); } catch (err) { console.error('foldLongComments failed:', err); } - try { foldLongShuoshuo(); } catch (err) { console.error('foldLongShuoshuo failed:', err); } + try { waterflowInit(); } catch (err) { ArgonDebug.error('waterflowInit failed:', err); } + try { lazyloadInit(); } catch (err) { ArgonDebug.error('lazyloadInit failed:', err); } + try { zoomifyInit(); } catch (err) { ArgonDebug.error('zoomifyInit failed:', err); } + try { highlightJsRender(); } catch (err) { ArgonDebug.error('highlightJsRender failed:', err); } + try { panguInit(); } catch (err) { ArgonDebug.error('panguInit failed:', err); } + try { clampInit(); } catch (err) { ArgonDebug.error('clampInit failed:', err); } + try { tippyInit(); } catch (err) { ArgonDebug.error('tippyInit failed:', err); } + try { getGithubInfoCardContent(); } catch (err) { ArgonDebug.error('getGithubInfoCardContent failed:', err); } + try { showPostOutdateToast(); } catch (err) { ArgonDebug.error('showPostOutdateToast failed:', err); } + try { calcHumanTimesOnPage(); } catch (err) { ArgonDebug.error('calcHumanTimesOnPage failed:', err); } + try { foldLongComments(); } catch (err) { ArgonDebug.error('foldLongComments failed:', err); } + try { foldLongShuoshuo(); } catch (err) { ArgonDebug.error('foldLongShuoshuo failed:', err); } $("html").trigger("resize"); // 恢复滚动位置 @@ -2783,22 +2837,22 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no try{ window.pjaxLoaded(); }catch (err){ - console.error(err); + ArgonDebug.error(err); } } NProgress.done(); }).on('pjax:end', function() { - // 重置移动端目录状态 + // 重置移动端目录状�? if (typeof window.resetMobileCatalog === 'function') { try { window.resetMobileCatalog(); } catch (err) { - console.warn('resetMobileCatalog failed:', err); + ArgonDebug.warn('resetMobileCatalog failed:', err); } } - // GT4: PJAX 后确保评论页验证码已初始化 + // GT4: PJAX 后确保评论页验证码已初始�? resetGT4Captcha(); }); @@ -2818,7 +2872,7 @@ $(document).on("click", ".reference-link , .reference-list-backlink" , function( }, 1); }); -/*Tags Dialog pjax 加载后自动关闭*/ +/*Tags Dialog pjax 加载后自动关�?/ $(document).on("click" , "#blog_tags .tag" , function(){ $("#blog_tags button.close").trigger("click"); }); @@ -2829,15 +2883,12 @@ $(document).on("click" , "#blog_categories .tag" , function(){ /*侧栏 & 顶栏菜单手机适配*/ !function(){ $(document).on("click" , "#fabtn_open_sidebar, #open_sidebar" , function(){ - console.log('[Mobile Sidebar] Sidebar opened'); $("html").addClass("leftbar-opened"); - // 侧边栏打开时初始化移动端文章目录 - console.log('[Mobile Sidebar] Calling initMobileCatalog'); + // 侧边栏打开时初始化移动端文章目�? initMobileCatalog(); // 如果有文章目录,默认展开 setTimeout(function() { var catalogSection = $("#mobile_catalog_toggle").closest(".leftbar-mobile-collapse-section"); - console.log('[Mobile Sidebar] Catalog section found:', catalogSection.length); if (catalogSection.length > 0 && !catalogSection.hasClass("expanded")) { catalogSection.addClass("expanded"); initMobileCatalog(); @@ -2875,13 +2926,13 @@ $(document).on("click" , "#blog_categories .tag" , function(){ $("#navbar_global .navbar-toggler").click(); }); - // ========== 移动端折叠面板交互 ========== + // ========== 移动端折叠面板交�?========== $(document).on("click", ".leftbar-mobile-collapse-header", function(e) { var section = $(this).closest(".leftbar-mobile-collapse-section"); var header = $(this); var isExpanded = section.hasClass("expanded"); - // 切换展开状态 + // 切换展开状�? section.toggleClass("expanded"); // 如果是文章目录面板展开,初始化目录并滚动到当前位置 @@ -2895,23 +2946,20 @@ $(document).on("click" , "#blog_categories .tag" , function(){ window.mobileCatalogInitialized = false; function initMobileCatalog() { - console.log('[Mobile Catalog] initMobileCatalog called, initialized:', window.mobileCatalogInitialized); if (window.mobileCatalogInitialized) return; var $mobileContainer = $("#leftbar_mobile_catalog"); var $postContent = $("#post_content"); - console.log('[Mobile Catalog] Container found:', $mobileContainer.length, 'PostContent found:', $postContent.length); if ($mobileContainer.length === 0) return; if ($postContent.length === 0) return; // 直接生成目录,不依赖 headIndex 插件 var $headers = $postContent.find('h1, h2, h3, h4, h5, h6'); - console.log('[Mobile Catalog] Headers found:', $headers.length); if ($headers.length === 0) { $mobileContainer.html('
暂无目录
'); return; } - // 构建目录树 + // 构建目录�? var toc = []; var stack = [{ level: 0, children: toc }]; @@ -2921,7 +2969,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ var text = $h.text().trim(); var id = $h.attr('id'); - // 确保标题有 ID + // 确保标题�?ID if (!id) { id = 'mobile-heading-' + index; $h.attr('id', id); @@ -2955,7 +3003,6 @@ $(document).on("click" , "#blog_categories .tag" , function(){ } $mobileContainer.html(buildHtml(toc, true)); - console.log('[Mobile Catalog] HTML generated, toc items:', toc.length); window.mobileCatalogInitialized = true; // 绑定点击事件 @@ -2983,7 +3030,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ setTimeout(scrollMobileCatalogToActive, 150); } - // 更新移动端目录高亮 + // 更新移动端目录高�? function updateMobileCatalogHighlight() { var $mobileContainer = $("#leftbar_mobile_catalog"); var $postContent = $("#post_content"); @@ -3007,7 +3054,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ } } - // 重置移动端目录状态(供 PJAX 调用) + // 重置移动端目录状态(�?PJAX 调用�? window.resetMobileCatalog = function() { window.mobileCatalogInitialized = false; $("#leftbar_mobile_catalog").empty(); @@ -3029,7 +3076,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ } } - // 监听页面滚动,实时更新移动端目录高亮并自动滚动 + // 监听页面滚动,实时更新移动端目录高亮并自动滚�? var mobileCatalogScrollTimer = null; $(window).on("scroll.mobileCatalog", function() { if (!window.mobileCatalogInitialized) return; @@ -3037,9 +3084,9 @@ $(document).on("click" , "#blog_categories .tag" , function(){ if (mobileCatalogScrollTimer) return; mobileCatalogScrollTimer = setTimeout(function() { mobileCatalogScrollTimer = null; - // 更新高亮状态 + // 更新高亮状�? updateMobileCatalogHighlight(); - // 只在侧边栏打开且目录展开时滚动 + // 只在侧边栏打开且目录展开时滚�? if ($("html").hasClass("leftbar-opened") && $("#mobile_catalog_toggle").closest(".leftbar-mobile-collapse-section").hasClass("expanded")) { scrollMobileCatalogToActive(); @@ -3053,7 +3100,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ function updateMobileTodoCount() { var count = $("#mobile-todo-list .mobile-todo-item:not(.todo-completed)").length; $("#mobile_todo_count").text(count); - // 同步更新桌面端计数 + // 同步更新桌面端计�? $(".todo-count").text(count); } @@ -3111,7 +3158,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ }); } - // 移动端 TODO 验证码相关变量 + // 移动�?TODO 验证码相关变�? var mobilePendingUrgeBtn = null; var mobileGeetestCaptchaObj = null; @@ -3177,7 +3224,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ mobilePendingUrgeBtn = btn; if (window.mobileTodoConfig.captchaType === 'geetest') { - // 极验验证码 + // 极验验证�? if (!mobileGeetestCaptchaObj && typeof initGeetest4 === 'function') { initGeetest4({ captchaId: window.mobileTodoConfig.geetestId, @@ -3201,14 +3248,14 @@ $(document).on("click" , "#blog_categories .tag" , function(){ mobileGeetestCaptchaObj.showCaptcha(); } } else { - // 数学验证码 + // 数学验证�? $("#mobile-todo-captcha-input").val("").focus(); } return; } } - // 不需要验证码,直接催促 + // 不需要验证码,直接催�? doMobileUrge(btn, id, ""); } }); @@ -3236,7 +3283,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ } }); - // 执行移动端催促 + // 执行移动端催�? function doMobileUrge(btn, id, captcha) { btn.prop("disabled", true).html(''); @@ -3258,7 +3305,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ }); } - // 极验验证码催促 + // 极验验证码催�? function doMobileUrgeGeetest(btn, id, geetestResult) { btn.prop("disabled", true).html(''); @@ -3284,7 +3331,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ }); } - // 处理移动端催促响应 + // 处理移动端催促响�? function handleMobileUrgeResponse(btn, res) { var captchaContainer = $(".mobile-todo-captcha-container"); @@ -3293,7 +3340,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ captchaContainer.slideUp(200); mobilePendingUrgeBtn = null; - // 更新验证码文本 + // 更新验证码文�? if (res.data && res.data.captcha) { $(".mobile-todo-captcha-text").text(res.data.captcha); } @@ -3306,7 +3353,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ if (typeof iziToast !== 'undefined') { iziToast.success({ title: '', - message: res.data && res.data.message ? res.data.message : '已提醒', + message: res.data && res.data.message ? res.data.message : '已提�?, position: 'topRight', timeout: 3000 }); @@ -3324,7 +3371,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ }); } - // 刷新验证码 + // 刷新验证�? if (res.data && res.data.captcha) { $(".mobile-todo-captcha-text").text(res.data.captcha); } @@ -3357,7 +3404,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){ } }(); -/*折叠区块小工具*/ +/*折叠区块小工�?/ $(document).on("click" , ".collapse-block .collapse-block-title" , function(){ let block = $(this).parent(); $(block).toggleClass("collapsed"); @@ -3370,7 +3417,7 @@ $(document).on("click" , ".collapse-block .collapse-block-title" , function(){ $("html").trigger("scroll"); }); -/*获得 Github Repo Shortcode 信息卡内容*/ +/*获得 Github Repo Shortcode 信息卡内�?/ function getGithubInfoCardContent(){ $(".github-info-card").each(function(){ (function($this){ @@ -3476,7 +3523,7 @@ $(document).on("click" , ".shuoshuo-upvote" , function(){ } }); }); -//折叠长说说 +//折叠长说�? function foldLongShuoshuo(){ if (argonConfig.fold_long_shuoshuo == false){ return; @@ -3624,7 +3671,7 @@ function rgb2str(rgb){ function hex2str(hex){ return rgb2str(hex2rgb(hex)); } -//颜色选择器 & 切换主题色 +//颜色选择�?& 切换主题�? if ($("meta[name='argon-enable-custom-theme-color']").attr("content") == 'true'){ let themeColorPicker = new Pickr({ el: '#theme-color-picker', @@ -3826,13 +3873,13 @@ function highlightJsRender(){
-
+
-
+
`); @@ -3844,7 +3891,7 @@ function highlightJsRender(){ clipboard.on('success', function(e) { iziToast.show({ title: __("复制成功"), - message: __("代码已复制到剪贴板"), + message: __("代码已复制到剪贴�?), class: 'shadow', position: 'topRight', backgroundColor: '#2dce89', @@ -3859,7 +3906,7 @@ function highlightJsRender(){ clipboard.on('error', function(e) { iziToast.show({ title: __("复制失败"), - message: __("请手动复制代码"), + message: __("请手动复制代�?), class: 'shadow', position: 'topRight', backgroundColor: '#f5365c', @@ -3874,6 +3921,68 @@ function highlightJsRender(){ }); } $(document).ready(function(){ + // ========================================================================== + // 初始化性能优化模块 + // ========================================================================== + if (typeof initArgonPerformance === 'function') { + // 调用性能优化模块的初始化函数 + initArgonPerformance(); + + // 创建各个优化模块的实�? + try { + // 1. 性能监控模块(最先初始化,用于监控其他模块) + if (typeof ArgonPerformanceMonitor !== 'undefined') { + argonPerformanceMonitor = new ArgonPerformanceMonitor(); + ArgonDebug.info('✓ 性能监控模块已初始化'); + } + + // 2. DOM 缓存模块 + if (typeof ArgonDOMCache !== 'undefined') { + argonDOMCache = new ArgonDOMCache(); + // 设置性能监控器引用 + if (argonPerformanceMonitor) { + argonDOMCache.setPerformanceMonitor(argonPerformanceMonitor); + } + // 初始化缓存 + argonDOMCache.init(); + ArgonDebug.info('✓ DOM 缓存模块已初始化'); + } + + // 3. 事件管理模块 + if (typeof ArgonEventManager !== 'undefined') { + argonEventManager = new ArgonEventManager(); + ArgonDebug.info('✓ 事件管理模块已初始化'); + } + + // 4. 资源加载模块 + if (typeof ArgonResourceLoader !== 'undefined') { + argonResourceLoader = new ArgonResourceLoader(); + ArgonDebug.info('✓ 资源加载模块已初始化'); + } + + // 5. 渲染优化模块 + if (typeof ArgonRenderOptimizer !== 'undefined') { + argonRenderOptimizer = new ArgonRenderOptimizer(); + ArgonDebug.info('✓ 渲染优化模块已初始化'); + } + + // 6. 内存管理模块 + if (typeof ArgonMemoryManager !== 'undefined') { + argonMemoryManager = new ArgonMemoryManager(); + ArgonDebug.info('✓ 内存管理模块已初始化'); + } + + ArgonDebug.info('🚀 Argon 性能优化模块全部初始化完成'); + } catch (error) { + ArgonDebug.error('性能优化模块初始化失败:', error); + } + } else { + ArgonDebug.warn('性能优化模块未加载,请确保 argon-performance.js 已正确引入'); + } + + // ========================================================================== + // 原有初始化代�? + // ========================================================================== highlightJsRender(); waterflowInit(); }); @@ -3895,7 +4004,7 @@ $(document).on("click" , ".hljs-control-toggle-linenumber" , function(){ block.toggleClass("hljs-hide-linenumber"); }); -/*时间差计算*/ +/*时间差计�?/ function addPreZero(num, n) { var len = num.toString().length; while(len < n) { @@ -3915,10 +4024,10 @@ function humanTimeDiff(time){ return __("刚刚"); } if (delta < 1000 * 60 * 60){ - return parseInt(delta / (1000 * 60)) + " " + __("分钟前"); + return parseInt(delta / (1000 * 60)) + " " + __("分钟�?); } if (delta < 1000 * 60 * 60 * 24){ - return parseInt(delta / (1000 * 60 * 60)) + " " + __("小时前"); + return parseInt(delta / (1000 * 60 * 60)) + " " + __("小时�?); } let yesterday = new Date(now - 1000 * 60 * 60 * 24); yesterday.setHours(0); @@ -3977,7 +4086,7 @@ setInterval(function(){ void 0; }(); -/* ========== Modern UI Enhancements - 现代化交互动画增强 ========== */ +/* ========== Modern UI Enhancements - 现代化交互动画增�?========== */ (function() { 'use strict'; @@ -4018,7 +4127,7 @@ void 0; }); } - // 5. 页面加载进度条 + // 5. 页面加载进度�? function initLoadingBar() { if (document.getElementById('page-loading-bar')) return; var bar = document.createElement('div'); @@ -4056,20 +4165,20 @@ void 0; }); } - // 7. 主题切换动画 - 已在 header.php 中通过 setDarkmode 函数处理,此处不再重复 + // 7. 主题切换动画 - 已在 header.php 中通过 setDarkmode 函数处理,此处不再重�? function initThemeTransition() { // 移除 MutationObserver 避免无限循环导致内存泄漏 - // 主题切换过渡效果已在 setDarkmode() 函数中实现 + // 主题切换过渡效果已在 setDarkmode() 函数中实�? } - // 8. 减少动画偏好检测 + // 8. 减少动画偏好检�? function checkReducedMotion() { if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { document.documentElement.classList.add('reduced-motion'); } } - // 初始化 + // 初始�? function init() { checkReducedMotion(); initImageLoadAnimation();