在nodeloc.cc上的帖子使用,让chrome浏览器自动向下滑动刷时间
侧边栏壁纸
  • 累计撰写 108 篇文章
  • 累计收到 61 条评论

在nodeloc.cc上的帖子使用,让chrome浏览器自动向下滑动刷时间

wszx01
2025-06-08 / 0 评论 / 16 阅读

在nodeloc.cc上的帖子使用,让 chrome浏览器自动向下滑动刷时间
在Tampermonkey使用的代码,功能是开启后,让chrome浏览器自动向下滑动,模仿人在看帖子
找一个回帖长的页面,如 2200多个回帖页 ,Tampermonkey自动刷时间开始,期间可以页面最小化后做其它事。

3、NodeLOC控制面板【2025年7月2日更新,添加控制面板】

// ==UserScript==
// @name         NodeLOC控制面板
// @namespace    http://tampermonkey.net/
// @version      v 0.3
// @description  自动向下、上滚动页面,模拟人在浏览NodeLOC上的帖子,并增加控制面板
// @author       You
// @match        https://nodeloc.cc/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function () {
    'use strict';

    // 配置参数
    const config = {
        scrollInterval: 3000, // 滚动间隔(毫秒)
        scrollAmount: window.innerHeight * 1.8, // 每次滚动距离(像素)
        maxScrolls: 100 // 设置最大滚动次数,1次6个回帖左右,根据回帖多少设置
    };

    let scrollCount = 0;
    let scrollDirection = 1; // 滚动方向:1为向下,-1为向上
    let isScrolling = false;

    // 创建控制UI
    function createControlUI() {
        // 创建控制面板元素
        const controlPanel = document.createElement('div');
        controlPanel.id = 'autoScrollControl';
        document.body.appendChild(controlPanel);

        // 创建UI元素
        controlPanel.innerHTML = `
<div class="control-header">
    <div class="control-title">自动滚动控制</div>
    <button class="close-btn" id="closeControl">×</button>
</div>
<div class="buttons">
    <button class="btn btn-start" id="startBtn">开始滚动</button>
    <button class="btn btn-stop" id="stopBtn">停止滚动</button>
</div>`;

        // 添加样式
        GM_addStyle(`
#autoScrollControl {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 9999;
    background: rgba(30, 30, 50, 0.9);
    border-radius: 10px;
    padding: 15px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    border: 1px solid #444;
    backdrop-filter: blur(5px);
    min-width: 250px;
    color: #fff;
    font-family: Arial, sans-serif;
    transition: transform 0.3s ease;
}

#autoScrollControl:hover {
    transform: translateY(-5px);
}

#autoScrollControl .control-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 1px solid #444;
}

#autoScrollControl .control-title {
    font-size: 18px;
    font-weight: bold;
    color: #ff8a00;
}

#autoScrollControl .close-btn {
    background: none;
    border: none;
    color: #aaa;
    font-size: 20px;
    cursor: pointer;
    transition: color 0.3s;
}

#autoScrollControl .close-btn:hover {
    color: #fff;
}

#autoScrollControl .buttons {
    display: flex;
    gap: 10px;
    margin-top: 10px;
}

#autoScrollControl .btn {
    flex: 1;
    padding: 8px 15px;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.3s ease;
}

#autoScrollControl .btn-start {
    background: linear-gradient(to right, #22c1c3, #1a9c9e);
    color: white;
}

#autoScrollControl .btn-stop {
    background: linear-gradient(to right, #e52e71, #c41c5c);
    color: white;
}`);

        // 获取UI元素
        const startBtn = controlPanel.querySelector('#startBtn');
        const stopBtn = controlPanel.querySelector('#stopBtn');
        const closeBtn = controlPanel.querySelector('#closeControl');

        // 按钮事件
        startBtn.addEventListener('click', startAutoScroll);
        stopBtn.addEventListener('click', stopAutoScroll);

        // 关闭按钮
        closeBtn.addEventListener('click', function () {
            controlPanel.style.display = 'none';
        });
    }

    // 开始滚动
    function startAutoScroll() {
        if (isScrolling) return;
        isScrolling = true;
        startBtn.disabled = true;
        stopBtn.disabled = false;

        setTimeout(startAutoScrollInternal, config.scrollInterval);
    }

    function startAutoScrollInternal() {
        if (!isScrolling) return;

        if (scrollCount >= config.maxScrolls) {
            console.log('已达到最大滚动次数,将在45秒后反向滚动');
            setTimeout(() => {
                scrollCount = 0; // 重置滚动计数器
                scrollDirection *= -1; // 切换滚动方向
                startAutoScrollInternal(); // 重新开始滚动
            }, 45000); // 45秒后重启
            return;
        }

        window.scrollBy({
            top: config.scrollAmount * scrollDirection,
            left: 0,
            behavior: 'smooth'
        });

        scrollCount++;
        console.log(`第${scrollCount}次滚动`);

        setTimeout(startAutoScrollInternal, config.scrollInterval);
    }

    // 停止滚动
    function stopAutoScroll() {
        isScrolling = false;
        startBtn.disabled = false;
        stopBtn.disabled = true;
    }

    // 初始化
    window.addEventListener('load', function () {
        createControlUI();
    });
})();

2、循环自动滚动NodeLOC【2025年6月9日更新】

// ==UserScript==
// @name         循环自动滚动NodeLOC
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  自动向下滚动页面,模拟人在浏览NodeLOC上的帖子
// @author       You
// @match        https://nodeloc.cc/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 配置参数
    const config = {
        scrollInterval: 5000, // 滚动间隔(毫秒)
        scrollAmount: window.innerHeight * 0.8, // 每次滚动距离(像素)
        maxScrolls: 60 // 最大滚动次数,10次约为30个回帖,60次约为180个回帖,找一个180个回帖以上的
    };

    let scrollCount = 0;
    let scrollDirection = 1; // 滚动方向:1为向下,-1为向上

    // 开始自动滚动
    function startAutoScroll() {
        if (scrollCount >= config.maxScrolls) {
            console.log('已达到最大滚动次数,将在45秒后反向滚动');
            setTimeout(() => {
                scrollCount = 0; // 重置滚动计数器
                scrollDirection *= -1; // 切换滚动方向
                startAutoScroll(); // 重新开始滚动
            }, 45000); // 45秒后重启
            return;
        }

        window.scrollBy({
            top: config.scrollAmount * scrollDirection,
            left: 0,
            behavior: 'smooth'
        });

        scrollCount++;
        console.log(`第${scrollCount}次滚动`);

        setTimeout(startAutoScroll, config.scrollInterval);
    }

    // 初始化
    setTimeout(startAutoScroll, config.scrollInterval);
})();

1、单向自动滚动NodeLOC【2025年6月8日】

// ==UserScript==
// @name         自动滚动NodeLOC
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  自动向下滚动页面,模拟人在浏览NodeLOC上的帖子
// @author       You
// @match        https://nodeloc.cc/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 配置参数
    const config = {
        scrollInterval: 5000, // 滚动间隔(毫秒)
        scrollAmount: window.innerHeight * 0.8, // 每次滚动距离(像素)
        maxScrolls: 200 // 最大滚动次数
    };

    let scrollCount = 0;

    // 开始自动滚动
    function startAutoScroll() {
        if (scrollCount >= config.maxScrolls) {
            console.log('已达到最大滚动次数,停止自动滚动');
            return;
        }

        window.scrollBy({
            top: config.scrollAmount,
            left: 0,
            behavior: 'smooth'
        });

        scrollCount++;
        console.log(`第${scrollCount}次滚动`);

        setTimeout(startAutoScroll, config.scrollInterval);
    }

    // 初始化
    setTimeout(startAutoScroll, config.scrollInterval);
})();

坛友做的
1.自动滚动辅助器,还行,有不足

// ==UserScript==
// @name         自动滚动辅助器
// @namespace    https://example.com/
// @version      1.6
// @description  自动向下/向上滚动页面,到达底部时自动反向滚动
// @author       DeepSeek-R1
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function () {
    'use strict';

    // 配置参数
    const defaultSettings = {
        scrollSpeed: 1,         // 每次滚动的像素数
        scrollInterval: 25,     // 滚动间隔(ms)
        threshold: 100,         // 底部/顶部检测阈值(px)
        enableUI: true          // 是否显示控制UI
    };

    // 加载用户设置
    let settings = Object.assign({}, defaultSettings);
    if (GM_getValue('autoScrollSettings')) {
        settings = Object.assign(settings, GM_getValue('autoScrollSettings'));
    }

    // 状态变量
    let scrollDirection = 1;    // 1=向下, -1=向上
    let scrollIntervalId = null;
    let isScrolling = false;

    // 创建控制UI
    function createControlUI() {
        // 创建控制面板元素
        const controlPanel = document.createElement('div');
        controlPanel.id = 'autoScrollControl';
        document.body.appendChild(controlPanel);

        // 创建UI元素
        controlPanel.innerHTML = `
<div class="control-header">
    <div class="control-title">自动滚动控制</div>
    <button class="close-btn" id="closeControl">×</button>
</div>
<div class="control-group">
    <label class="control-label">滚动速度: px/帧</label>
    <div class="slider-container">
        <input type="range" id="speedSlider" class="slider" min="1" max="10" value="${settings.scrollSpeed}">
        <div class="value-display" id="speedDisplay">${settings.scrollSpeed}</div>
    </div>
</div>
<div class="control-group">
    <label class="control-label">刷新间隔: ms</label>
    <div class="slider-container">
        <input type="range" id="intervalSlider" class="slider" min="5" max="100" value="${settings.scrollInterval}">
        <div class="value-display" id="intervalDisplay">${settings.scrollInterval}</div>
    </div>
</div>
<div class="buttons">
    <button class="btn btn-start" id="startBtn">开始滚动</button>
    <button class="btn btn-stop" id="stopBtn">停止滚动</button>
</div>`;

        // 添加样式
        GM_addStyle(`
#autoScrollControl {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 9999;
    background: rgba(30, 30, 50, 0.9);
    border-radius: 10px;
    padding: 15px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    border: 1px solid #444;
    backdrop-filter: blur(5px);
    min-width: 250px;
    color: #fff;
    font-family: Arial, sans-serif;
    transition: transform 0.3s ease;
}

#autoScrollControl:hover {
    transform: translateY(-5px);
}

#autoScrollControl .control-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 1px solid #444;
}

#autoScrollControl .control-title {
    font-size: 18px;
    font-weight: bold;
    color: #ff8a00;
}

#autoScrollControl .close-btn {
    background: none;
    border: none;
    color: #aaa;
    font-size: 20px;
    cursor: pointer;
    transition: color 0.3s;
}

#autoScrollControl .close-btn:hover {
    color: #fff;
}

#autoScrollControl .control-group {
    margin-bottom: 15px;
}

#autoScrollControl .control-label {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    color: #a0b3ff;
}

#autoScrollControl .slider-container {
    display: flex;
    align-items: center;
    gap: 10px;
}

#autoScrollControl .slider {
    flex: 1;
    height: 6px;
    -webkit-appearance: none;
    background: rgba(255, 255, 255, 0.1);
    outline: none;
    border-radius: 3px;
}

#autoScrollControl .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #ff8a00;
    cursor: pointer;
    box-shadow: 0 0 5px rgba(255, 138, 0, 0.7);
}

#autoScrollControl .value-display {
    min-width: 40px;
    text-align: center;
    font-size: 14px;
    font-weight: bold;
    color: #ff8a00;
}

#autoScrollControl .buttons {
    display: flex;
    gap: 10px;
    margin-top: 10px;
}

#autoScrollControl .btn {
    flex: 1;
    padding: 8px 15px;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.3s ease;
}

#autoScrollControl .btn-start {
    background: linear-gradient(to right, #22c1c3, #1a9c9e);
    color: white;
}

#autoScrollControl .btn-stop {
    background: linear-gradient(to right, #e52e71, #c41c5c);
    color: white;
}`);

        // 获取UI元素
        const speedSlider = controlPanel.querySelector('#speedSlider');
        const speedDisplay = controlPanel.querySelector('#speedDisplay');
        const intervalSlider = controlPanel.querySelector('#intervalSlider');
        const intervalDisplay = controlPanel.querySelector('#intervalDisplay');
        const startBtn = controlPanel.querySelector('#startBtn');
        const stopBtn = controlPanel.querySelector('#stopBtn');
        const closeBtn = controlPanel.querySelector('#closeControl');

        // 滑块事件
        speedSlider.addEventListener('input', function () {
            settings.scrollSpeed = parseInt(this.value);
            speedDisplay.textContent = settings.scrollSpeed;
            GM_setValue('autoScrollSettings', settings);

            if (isScrolling) {
                stopAutoScroll();
                startAutoScroll();
            }
        });

        intervalSlider.addEventListener('input', function () {
            settings.scrollInterval = parseInt(this.value);
            intervalDisplay.textContent = settings.scrollInterval;
            GM_setValue('autoScrollSettings', settings);

            if (isScrolling) {
                stopAutoScroll();
                startAutoScroll();
            }
        });

        // 按钮事件
        startBtn.addEventListener('click', startAutoScroll);
        stopBtn.addEventListener('click', stopAutoScroll);

        // 关闭按钮
        closeBtn.addEventListener('click', function () {
            controlPanel.style.display = 'none';
            settings.enableUI = false;
            GM_setValue('autoScrollSettings', settings);
        });
    }

    // 开始滚动
    function startAutoScroll() {
        if (scrollIntervalId) return;
        isScrolling = true;

        scrollIntervalId = setInterval(() => {
            // 获取页面当前滚动位置和最大滚动位置
            const currentPos = window.pageYOffset || document.documentElement.scrollTop;
            const maxPos = document.documentElement.scrollHeight - window.innerHeight;

            // 检查是否到达底部或顶部
            if (scrollDirection === 1 && currentPos >= maxPos - settings.threshold) {
                scrollDirection = -1; // 到达底部,改为向上滚动
            } else if (scrollDirection === -1 && currentPos <= settings.threshold) {
                scrollDirection = 1; // 到达顶部,改为向下滚动
            }

            // 执行滚动
            window.scrollBy({
                top: settings.scrollSpeed * scrollDirection,
                behavior: 'instant'
            });
        }, settings.scrollInterval);
    }

    // 停止滚动
    function stopAutoScroll() {
        if (scrollIntervalId) {
            clearInterval(scrollIntervalId);
            scrollIntervalId = null;
            isScrolling = false;
        }
    }

    // 注册菜单命令
    GM_registerMenuCommand('开始自动滚动', startAutoScroll);
    GM_registerMenuCommand('停止自动滚动', stopAutoScroll);
    GM_registerMenuCommand('显示控制面板', function () {
        document.getElementById('autoScrollControl').style.display = 'block';
        settings.enableUI = true;
        GM_setValue('autoScrollSettings', settings);
    });

    // 初始化
    window.addEventListener('load', function () {
        createControlUI();
        if (!settings.enableUI) {
            document.getElementById('autoScrollControl').style.display = 'none';
        }
    });
})();

坛友做的
2.智能助手, 功能多用不上,电脑配置低卡,不推荐

// ==UserScript==
// @name         智能论坛助手 Pro
// @namespace    http://tampermonkey.net/
// @version      2.6.0
// @description  NodeLoc智能论坛助手 - 自动阅读/点赞/回复,升级进度追踪,弹窗检测,限制监控,数据统计,位置记忆等全方位功能
// @author       Enhanced by AI
// @match        https://meta.discourse.org/*
// @match        https://meta.appinn.net/*
// @match        https://community.openai.com/*
// @match        https://nodeloc.cc/*
// @match        https://bbs.tampermonkey.net.cn/*
// @match        https://greasyfork.org/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_notification
// @grant        GM_openInTab
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @license      MIT
// @icon         https://www.google.com/s2/favicons?domain=discourse.org
// @downloadURL  https://update.greasyfork.org/scripts/enhanced-forum-assistant/Enhanced%20Forum%20Assistant.user.js
// @updateURL    https://update.greasyfork.org/scripts/enhanced-forum-assistant/Enhanced%20Forum%20Assistant.meta.js
// ==/UserScript==

(function () {
  "use strict";

  // ===== 配置管理类 =====
  class ConfigManager {
    constructor() {
      this.defaultConfig = {
        // 基础配置
        possibleBaseURLs: [
          "https://linux.do",
          "https://meta.discourse.org",
          "https://meta.appinn.net",
          "https://community.openai.com",
          "https://nodeloc.cc",
          "https://bbs.tampermonkey.net.cn",
          "https://greasyfork.org"
        ],

        // 行为参数
        commentLimit: 1000,
        topicListLimit: 100,
        likeLimit: 55,
        stuckTimeout: 15000,
        minScrollDelta: 50,
        maxIdleTime: 60000,
        maxLogEntries: 200,
        minTopicChangeDelay: 3000,
        maxTopicChangeDelay: 8000,
        minReadTimeLower: 45000,
        minReadTimeUpper: 120000,
        fetchRetryDelay: 30000,

        // 滚动参数
        scrollSegmentDistanceMin: 300,
        scrollSegmentDistanceMax: 1000,
        scrollSegmentDurationMin: 2000,
        scrollSegmentDurationMax: 6000,
        randomPauseProbability: 0.2,
        randomPauseDurationMin: 100,
        randomPauseDurationMax: 800,

        // 贝塞尔曲线参数
        bezierP1Min: 0.1,
        bezierP1Max: 0.4,
        bezierP2Min: 0.6,
        bezierP2Max: 0.9,

        // 新增功能配置
        enableMouseSimulation: true,
        enableAdvancedBehavior: true,
        enableDataAnalysis: true,
        enableSafetyFeatures: true,
        autoReplyEnabled: false,
        keywordMonitoring: false,
        proxyEnabled: false,

        // UI配置
        theme: 'dark',
        language: 'zh-CN',
        showStatistics: true,
        compactMode: false
      };

      this.config = this.loadConfig();
    }

    loadConfig() {
      try {
        const saved = GM_getValue('forumAssistantConfig', '{}');
        return { ...this.defaultConfig, ...JSON.parse(saved) };
      } catch (e) {
        console.warn('配置加载失败,使用默认配置:', e);
        return { ...this.defaultConfig };
      }
    }

    saveConfig() {
      try {
        GM_setValue('forumAssistantConfig', JSON.stringify(this.config));
        return true;
      } catch (e) {
        console.error('配置保存失败:', e);
        return false;
      }
    }

    get(key) {
      return this.config[key];
    }

    set(key, value) {
      this.config[key] = value;
      this.saveConfig();
    }

    reset() {
      this.config = { ...this.defaultConfig };
      this.saveConfig();
    }

    exportConfig() {
      return JSON.stringify(this.config, null, 2);
    }

    importConfig(configStr) {
      try {
        const imported = JSON.parse(configStr);
        this.config = { ...this.defaultConfig, ...imported };
        this.saveConfig();
        return true;
      } catch (e) {
        console.error('配置导入失败:', e);
        return false;
      }
    }
  }

  // ===== 工具类 =====
  class Utils {
    static getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    static getRandomFloat(min, max) {
      return Math.random() * (max - min) + min;
    }

    static sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    // 安全的DOM元素创建
    static safeCreateElement(tagName, options = {}) {
      try {
        const element = document.createElement(tagName);
        if (!element) {
          console.error(`无法创建 ${tagName} 元素`);
          return null;
        }

        // 设置属性
        if (options.id) element.id = options.id;
        if (options.className) element.className = options.className;
        if (options.textContent) element.textContent = options.textContent;
        if (options.innerHTML) element.innerHTML = options.innerHTML;

        // 设置样式
        if (options.style && typeof options.style === 'object') {
          Object.assign(element.style, options.style);
        }

        return element;
      } catch (e) {
        console.error(`创建 ${tagName} 元素失败:`, e);
        return null;
      }
    }

    // 安全的DOM元素查找
    static safeQuerySelector(selector, parent = document) {
      try {
        if (!parent || typeof parent.querySelector !== 'function') {
          console.warn('无效的父元素');
          return null;
        }
        return parent.querySelector(selector);
      } catch (e) {
        console.error(`查找元素失败 (${selector}):`, e);
        return null;
      }
    }

    // 安全的DOM元素添加
    static safeAppendChild(parent, child) {
      try {
        if (!parent || !child) {
          console.warn('父元素或子元素为空');
          return false;
        }
        if (typeof parent.appendChild !== 'function') {
          console.warn('父元素不支持appendChild');
          return false;
        }
        parent.appendChild(child);
        return true;
      } catch (e) {
        console.error('添加子元素失败:', e);
        return false;
      }
    }

    // 安全的样式设置
    static safeSetStyle(element, property, value) {
      try {
        if (!element || !element.style) {
          console.warn('元素或样式对象不存在');
          return false;
        }
        element.style[property] = value;
        return true;
      } catch (e) {
        console.error(`设置样式失败 (${property}):`, e);
        return false;
      }
    }

    // 安全的内容设置
    static safeSetContent(element, content, useInnerHTML = false) {
      try {
        if (!element) {
          console.warn('元素不存在');
          return false;
        }
        if (useInnerHTML) {
          element.innerHTML = content;
        } else {
          element.textContent = content;
        }
        return true;
      } catch (e) {
        console.error('设置内容失败:', e);
        return false;
      }
    }

    static formatTime(ms) {
      const seconds = Math.floor(ms / 1000);
      const minutes = Math.floor(seconds / 60);
      const hours = Math.floor(minutes / 60);

      if (hours > 0) {
        return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
      } else if (minutes > 0) {
        return `${minutes}m ${seconds % 60}s`;
      } else {
        return `${seconds}s`;
      }
    }

    static formatNumber(num) {
      if (num >= 1000000) {
        return (num / 1000000).toFixed(1) + 'M';
      } else if (num >= 1000) {
        return (num / 1000).toFixed(1) + 'K';
      }
      return num.toString();
    }

    static debounce(func, wait) {
      let timeout;
      return function executedFunction(...args) {
        const later = () => {
          clearTimeout(timeout);
          func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
      };
    }

    static throttle(func, limit) {
      let inThrottle;
      return function() {
        const args = arguments;
        const context = this;
        if (!inThrottle) {
          func.apply(context, args);
          inThrottle = true;
          setTimeout(() => inThrottle = false, limit);
        }
      };
    }

    static generateUUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        const r = Math.random() * 16 | 0;
        const v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    }

    static detectForumType(url) {
      if (url.includes('discourse')) return 'discourse';
      if (url.includes('linux.do')) return 'discourse';
      if (url.includes('nodeloc.cc')) return 'discourse';
      if (url.includes('greasyfork.org')) return 'greasyfork';
      return 'unknown';
    }

    static cubicBezier(t, p0, p1, p2, p3) {
      const u = 1 - t;
      const tt = t * t;
      const uu = u * u;
      const uuu = uu * u;
      const ttt = tt * t;
      return uuu * p0 + 3 * uu * t * p1 + 3 * u * tt * p2 + ttt * p3;
    }
  }

  // ===== 日志管理类 =====
  class LogManager {
    constructor(config) {
      this.config = config;
      this.entries = [];
      this.logWindow = null;
      this.logContent = null;
      // 从存储中恢复统计数据,如果不存在则使用默认值
      const savedStats = GM_getValue('statistics', null);
      if (savedStats) {
        this.statistics = {
          totalActions: savedStats.totalActions || 0,
          totalReadTime: savedStats.totalReadTime || 0,
          topicsRead: savedStats.topicsRead || 0,
          likesGiven: savedStats.likesGiven || 0,
          errorsCount: savedStats.errorsCount || 0,
          startTime: savedStats.startTime || Date.now()
        };
      } else {
        this.statistics = {
          totalActions: 0,
          totalReadTime: 0,
          topicsRead: 0,
          likesGiven: 0,
          errorsCount: 0,
          startTime: Date.now()
        };
      }
    }

    createLogWindow() {
      if (this.logWindow) return;

      const isDark = this.config.get('theme') === 'dark';
      const isCompact = this.config.get('compactMode');

      this.logWindow = Utils.safeCreateElement("div", {
        id: "forum-assistant-log",
        style: {
          position: "fixed",
          top: "10px",
          right: "10px",
          width: isCompact ? "280px" : "350px",
          maxHeight: isCompact ? "300px" : "500px",
          backgroundColor: isDark ? "#2d3748" : "#fff",
          color: isDark ? "#e2e8f0" : "#2d3748",
          border: `1px solid ${isDark ? "#4a5568" : "#e2e8f0"}`,
          borderRadius: "8px",
          boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
          zIndex: "10000",
          display: "flex",
          flexDirection: "column",
          fontFamily: "'Consolas', 'Monaco', monospace",
          fontSize: isCompact ? "11px" : "12px",
          backdropFilter: "blur(10px)",
          resize: "both",
          overflow: "hidden"
        }
      });

      if (!this.logWindow) {
        console.error('无法创建日志窗口');
        return;
      }

      this.createLogHeader(isDark);
      this.createLogContent(isDark);
      this.createLogControls(isDark);

      if (!Utils.safeAppendChild(document.body, this.logWindow)) {
        console.error('无法添加日志窗口到页面');
        return;
      }

      this.makeResizable();
    }

    createLogHeader(isDark) {
      const header = document.createElement("div");
      Object.assign(header.style, {
        backgroundColor: isDark ? "#4a5568" : "#f7fafc",
        padding: "8px 12px",
        borderBottom: `1px solid ${isDark ? "#718096" : "#e2e8f0"}`,
        fontWeight: "bold",
        display: "flex",
        justifyContent: "space-between",
        alignItems: "center",
        cursor: "move"
      });

      const title = document.createElement("span");
      title.textContent = "智能论坛助手 Pro";

      const controls = document.createElement("div");
      controls.style.display = "flex";
      controls.style.gap = "5px";

      // 最小化按钮
      const minimizeBtn = this.createControlButton("−", () => this.toggleMinimize());
      // 关闭按钮
      const closeBtn = this.createControlButton("×", () => this.toggleVisibility());

      controls.appendChild(minimizeBtn);
      controls.appendChild(closeBtn);
      header.appendChild(title);
      header.appendChild(controls);
      this.logWindow.appendChild(header);

      // 使窗口可拖拽
      this.makeDraggable(header);
    }

    createLogContent(isDark) {
      this.logContent = Utils.safeCreateElement("pre", {
        style: {
          margin: "0",
          padding: "10px",
          overflowY: "auto",
          flex: "1",
          fontSize: "inherit",
          lineHeight: "1.4",
          whiteSpace: "pre-wrap",
          wordBreak: "break-word"
        }
      });

      if (this.logContent && this.logWindow) {
        Utils.safeAppendChild(this.logWindow, this.logContent);
      }
    }

    createLogControls(isDark) {
      const controls = document.createElement("div");
      Object.assign(controls.style, {
        padding: "8px",
        borderTop: `1px solid ${isDark ? "#718096" : "#e2e8f0"}`,
        display: "flex",
        gap: "5px",
        flexWrap: "wrap"
      });

      const clearBtn = this.createActionButton("清空", () => this.clear());
      const exportBtn = this.createActionButton("导出", () => this.exportLogs());
      const statsBtn = this.createActionButton("统计", () => this.showStatistics());

      controls.appendChild(clearBtn);
      controls.appendChild(exportBtn);
      controls.appendChild(statsBtn);
      this.logWindow.appendChild(controls);
    }

    createControlButton(text, onClick) {
      const btn = document.createElement("button");
      btn.textContent = text;
      Object.assign(btn.style, {
        background: "none",
        border: "none",
        color: "inherit",
        cursor: "pointer",
        padding: "2px 6px",
        borderRadius: "3px",
        fontSize: "14px",
        fontWeight: "bold"
      });
      btn.addEventListener("click", onClick);
      btn.addEventListener("mouseenter", () => {
        btn.style.backgroundColor = "rgba(255,255,255,0.1)";
      });
      btn.addEventListener("mouseleave", () => {
        btn.style.backgroundColor = "transparent";
      });
      return btn;
    }

    createActionButton(text, onClick) {
      const btn = document.createElement("button");
      btn.textContent = text;
      Object.assign(btn.style, {
        padding: "4px 8px",
        border: "1px solid currentColor",
        backgroundColor: "transparent",
        color: "inherit",
        cursor: "pointer",
        borderRadius: "4px",
        fontSize: "11px"
      });
      btn.addEventListener("click", onClick);
      return btn;
    }

    makeDraggable(header) {
      if (!header || !this.logWindow) return;

      let isDragging = false;
      let currentX, currentY, initialX, initialY;

      header.addEventListener("mousedown", (e) => {
        if (!this.logWindow) return;
        isDragging = true;
        initialX = e.clientX - this.logWindow.offsetLeft;
        initialY = e.clientY - this.logWindow.offsetTop;
      });

      document.addEventListener("mousemove", (e) => {
        if (isDragging && this.logWindow) {
          e.preventDefault();
          currentX = e.clientX - initialX;
          currentY = e.clientY - initialY;
          this.logWindow.style.left = currentX + "px";
          this.logWindow.style.top = currentY + "px";
          this.logWindow.style.right = "auto";
        }
      });

      document.addEventListener("mouseup", () => {
        isDragging = false;
      });
    }

    makeResizable() {
      if (!this.logWindow) return;

      // 简单的调整大小功能
      const resizer = document.createElement("div");
      Object.assign(resizer.style, {
        position: "absolute",
        bottom: "0",
        right: "0",
        width: "10px",
        height: "10px",
        cursor: "se-resize",
        backgroundColor: "rgba(128,128,128,0.3)"
      });
      this.logWindow.appendChild(resizer);

      let isResizing = false;
      resizer.addEventListener("mousedown", (e) => {
        isResizing = true;
        e.preventDefault();
      });

      document.addEventListener("mousemove", (e) => {
        if (isResizing && this.logWindow) {
          const rect = this.logWindow.getBoundingClientRect();
          const newWidth = e.clientX - rect.left;
          const newHeight = e.clientY - rect.top;

          if (newWidth > 200) this.logWindow.style.width = newWidth + "px";
          if (newHeight > 150) this.logWindow.style.height = newHeight + "px";
        }
      });

      document.addEventListener("mouseup", () => {
        isResizing = false;
      });
    }

    log(message, type = 'info') {
      const timestamp = new Date().toLocaleTimeString();
      const entry = {
        timestamp,
        message,
        type,
        id: Utils.generateUUID()
      };

      this.entries.push(entry);
      this.statistics.totalActions++;

      if (type === 'error') this.statistics.errorsCount++;

      // 限制日志条目数量
      const maxEntries = this.config.get('maxLogEntries');
      if (this.entries.length > maxEntries) {
        this.entries = this.entries.slice(-maxEntries);
      }

      this.updateLogDisplay();

      // 控制台输出
      const consoleMethod = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';
      console[consoleMethod](`[论坛助手] [${timestamp}] ${message}`);

      // 重要消息通知
      if (type === 'error' || (type === 'info' && message.includes('完成'))) {
        this.showNotification(message, type);
      }
    }

    updateLogDisplay() {
      if (!this.logContent) {
        console.warn('日志内容元素不存在');
        return;
      }

      try {
        const displayEntries = this.entries.map(entry => {
          const typeIcon = this.getTypeIcon(entry.type);
          return `${typeIcon} [${entry.timestamp}] ${entry.message}`;
        });

        this.logContent.textContent = displayEntries.join('\n');
        this.logContent.scrollTop = this.logContent.scrollHeight;
      } catch (e) {
        console.error('更新日志显示失败:', e);
      }
    }

    getTypeIcon(type) {
      const icons = {
        info: '📘',
        warn: '⚠️',
        error: '❌',
        success: '✅',
        action: '🔄'
      };
      return icons[type] || '📘';
    }

    showNotification(message, type) {
      if (typeof GM_notification !== 'undefined') {
        GM_notification({
          text: message,
          title: '智能论坛助手',
          timeout: 3000,
          onclick: () => {
            window.focus();
            this.logWindow?.scrollIntoView();
          }
        });
      }
    }

    clear() {
      this.entries = [];
      this.updateLogDisplay();
      this.log('日志已清空', 'action');
    }

    exportLogs() {
      const exportData = {
        timestamp: new Date().toISOString(),
        statistics: this.statistics,
        logs: this.entries,
        config: this.config.config
      };

      const blob = new Blob([JSON.stringify(exportData, null, 2)], {
        type: 'application/json'
      });

      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `forum-assistant-logs-${new Date().toISOString().split('T')[0]}.json`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      this.log('日志已导出', 'success');
    }

    showStatistics() {
      const runtime = Date.now() - this.statistics.startTime;
      const stats = `
📊 运行统计
━━━━━━━━━━━━━━━━━━━━
⏱️ 运行时间: ${Utils.formatTime(runtime)}
📖 已读话题: ${this.statistics.topicsRead}
👍 点赞数量: ${this.statistics.likesGiven}
🔄 总操作数: ${this.statistics.totalActions}
❌ 错误次数: ${this.statistics.errorsCount}
📈 效率: ${(this.statistics.topicsRead / (runtime / 3600000)).toFixed(2)} 话题/小时
━━━━━━━━━━━━━━━━━━━━`;

      alert(stats);
    }

    toggleMinimize() {
      if (!this.logWindow) return;

      const content = this.logWindow.querySelector('pre');
      const controls = this.logWindow.querySelector('div:last-child');

      if (!content || !controls) return;

      if (content.style.display === 'none') {
        content.style.display = 'block';
        controls.style.display = 'flex';
        this.logWindow.style.height = 'auto';
      } else {
        content.style.display = 'none';
        controls.style.display = 'none';
        this.logWindow.style.height = 'auto';
      }
    }

    toggleVisibility() {
      if (!this.logWindow) return;
      this.logWindow.style.display = this.logWindow.style.display === 'none' ? 'flex' : 'none';
    }

    updateStatistics(key, value = 1) {
      if (this.statistics.hasOwnProperty(key)) {
        this.statistics[key] += value;
        // 保存统计数据到存储
        GM_setValue('statistics', this.statistics);
      }
    }

    // 重置统计数据
    resetStatistics() {
      this.statistics = {
        totalActions: 0,
        totalReadTime: 0,
        topicsRead: 0,
        likesGiven: 0,
        errorsCount: 0,
        startTime: Date.now()
      };
      GM_setValue('statistics', this.statistics);
      this.log('统计数据已重置', 'info');
    }
  }

  // ===== 配置面板类 =====
  class ConfigPanel {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.panel = null;
      this.isVisible = false;
    }

    create() {
      if (this.panel) return;

      const isDark = this.config.get('theme') === 'dark';

      this.panel = document.createElement('div');
      this.panel.id = 'forum-assistant-config';
      Object.assign(this.panel.style, {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: '600px',
        maxHeight: '80vh',
        backgroundColor: isDark ? '#2d3748' : '#ffffff',
        color: isDark ? '#e2e8f0' : '#2d3748',
        border: `1px solid ${isDark ? '#4a5568' : '#e2e8f0'}`,
        borderRadius: '12px',
        boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
        zIndex: '10001',
        display: 'none',
        flexDirection: 'column',
        fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
        backdropFilter: 'blur(10px)'
      });

      this.createHeader();
      this.createContent();
      this.createFooter();

      document.body.appendChild(this.panel);
      this.createOverlay();
    }

    createHeader() {
      const header = document.createElement('div');
      Object.assign(header.style, {
        padding: '20px',
        borderBottom: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`,
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center'
      });

      const title = document.createElement('h2');
      title.textContent = '🛠️ 高级配置';
      title.style.margin = '0';
      title.style.fontSize = '20px';
      title.style.fontWeight = '600';

      const closeBtn = document.createElement('button');
      closeBtn.innerHTML = '✕';
      Object.assign(closeBtn.style, {
        background: 'none',
        border: 'none',
        fontSize: '18px',
        cursor: 'pointer',
        color: 'inherit',
        padding: '5px',
        borderRadius: '4px'
      });
      closeBtn.addEventListener('click', () => this.hide());

      header.appendChild(title);
      header.appendChild(closeBtn);
      this.panel.appendChild(header);
    }

    createContent() {
      const content = document.createElement('div');
      Object.assign(content.style, {
        padding: '20px',
        overflowY: 'auto',
        flex: '1'
      });

      // 创建标签页
      const tabs = this.createTabs();
      content.appendChild(tabs);

      // 创建配置区域
      const configArea = document.createElement('div');
      configArea.id = 'config-area';
      content.appendChild(configArea);

      this.panel.appendChild(content);

      // 默认显示基础配置
      this.showBasicConfig();
    }

    createTabs() {
      const tabContainer = document.createElement('div');
      Object.assign(tabContainer.style, {
        display: 'flex',
        marginBottom: '20px',
        borderBottom: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`
      });

      const tabs = [
        { id: 'basic', name: '基础设置', icon: '⚙️' },
        { id: 'behavior', name: '行为配置', icon: '🤖' },
        { id: 'advanced', name: '高级功能', icon: '🚀' },
        { id: 'ui', name: '界面设置', icon: '🎨' },
        { id: 'data', name: '数据管理', icon: '📊' }
      ];

      tabs.forEach(tab => {
        const tabBtn = document.createElement('button');
        tabBtn.innerHTML = `${tab.icon} ${tab.name}`;
        Object.assign(tabBtn.style, {
          padding: '10px 15px',
          border: 'none',
          background: 'none',
          color: 'inherit',
          cursor: 'pointer',
          borderBottom: '2px solid transparent',
          fontSize: '14px',
          fontWeight: '500'
        });

        tabBtn.addEventListener('click', () => {
          // 移除所有活动状态
          tabContainer.querySelectorAll('button').forEach(btn => {
            btn.style.borderBottomColor = 'transparent';
            btn.style.opacity = '0.7';
          });

          // 设置当前活动状态
          tabBtn.style.borderBottomColor = '#3182ce';
          tabBtn.style.opacity = '1';

          // 显示对应配置
          this.showConfigSection(tab.id);
        });

        tabContainer.appendChild(tabBtn);
      });

      // 默认激活第一个标签
      tabContainer.firstChild.click();

      return tabContainer;
    }

    showConfigSection(sectionId) {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到');
        return;
      }

      configArea.innerHTML = '';

      switch (sectionId) {
        case 'basic':
          this.showBasicConfig();
          break;
        case 'behavior':
          this.showBehaviorConfig();
          break;
        case 'advanced':
          this.showAdvancedConfig();
          break;
        case 'ui':
          this.showUIConfig();
          break;
        case 'data':
          this.showDataConfig();
          break;
      }
    }

    showBasicConfig() {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到 (showBasicConfig)');
        return;
      }

      const basicConfigs = [
        { key: 'commentLimit', label: '评论数限制', type: 'number', min: 100, max: 5000, step: 100, desc: '跳过评论数超过此值的帖子' },
        { key: 'topicListLimit', label: '话题缓存数量', type: 'number', min: 50, max: 500, step: 50, desc: '一次获取并缓存的话题数量' },
        { key: 'likeLimit', label: '每日点赞限制', type: 'number', min: 10, max: 200, step: 5, desc: '每日自动点赞的最大次数' },
        { key: 'minReadTimeLower', label: '最小阅读时间(秒)', type: 'number', min: 30, max: 300, step: 5, desc: '每个帖子的最小阅读时间', transform: v => v / 1000, reverseTransform: v => v * 1000 },
        { key: 'minReadTimeUpper', label: '最大阅读时间(秒)', type: 'number', min: 60, max: 600, step: 10, desc: '每个帖子的最大阅读时间', transform: v => v / 1000, reverseTransform: v => v * 1000 },
        { key: 'stuckTimeout', label: '卡住检测超时(秒)', type: 'number', min: 5, max: 60, step: 5, desc: '检测页面卡住的超时时间', transform: v => v / 1000, reverseTransform: v => v * 1000 }
      ];

      basicConfigs.forEach(config => {
        const group = this.createConfigGroup(config);
        if (group && configArea) {
          configArea.appendChild(group);
        }
      });
    }

    showBehaviorConfig() {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到 (showBehaviorConfig)');
        return;
      }

      const behaviorConfigs = [
        { key: 'scrollSegmentDistanceMin', label: '滚动最小距离(px)', type: 'number', min: 100, max: 1000, step: 50, desc: '每段滚动的最小距离' },
        { key: 'scrollSegmentDistanceMax', label: '滚动最大距离(px)', type: 'number', min: 500, max: 2000, step: 100, desc: '每段滚动的最大距离' },
        { key: 'scrollSegmentDurationMin', label: '滚动最小时长(ms)', type: 'number', min: 1000, max: 5000, step: 250, desc: '每段滚动的最小持续时间' },
        { key: 'scrollSegmentDurationMax', label: '滚动最大时长(ms)', type: 'number', min: 3000, max: 10000, step: 500, desc: '每段滚动的最大持续时间' },
        { key: 'randomPauseProbability', label: '随机暂停概率', type: 'range', min: 0, max: 1, step: 0.05, desc: '滚动过程中随机暂停的概率' },
        { key: 'minTopicChangeDelay', label: '话题切换最小延迟(ms)', type: 'number', min: 1000, max: 10000, step: 500, desc: '切换话题的最小延迟时间' },
        { key: 'maxTopicChangeDelay', label: '话题切换最大延迟(ms)', type: 'number', min: 3000, max: 20000, step: 1000, desc: '切换话题的最大延迟时间' }
      ];

      behaviorConfigs.forEach(config => {
        const group = this.createConfigGroup(config);
        if (group && configArea) {
          configArea.appendChild(group);
        }
      });
    }

    showAdvancedConfig() {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到 (showAdvancedConfig)');
        return;
      }

      const advancedConfigs = [
        { key: 'enableMouseSimulation', label: '启用鼠标模拟', type: 'checkbox', desc: '模拟真实的鼠标移动轨迹' },
        { key: 'enableAdvancedBehavior', label: '启用高级行为', type: 'checkbox', desc: '包括随机停留、页面交互等' },
        { key: 'enableDataAnalysis', label: '启用数据分析', type: 'checkbox', desc: '收集和分析使用统计数据' },
        { key: 'enableSafetyFeatures', label: '启用安全功能', type: 'checkbox', desc: '包括请求头随机化、行为混淆等' },
        { key: 'autoReplyEnabled', label: '启用自动回复', type: 'checkbox', desc: '自动回复特定类型的帖子' },
        { key: 'keywordMonitoring', label: '关键词监控', type: 'checkbox', desc: '监控特定关键词并执行操作' },
        { key: 'proxyEnabled', label: '启用代理', type: 'checkbox', desc: '通过代理服务器发送请求' }
      ];

      advancedConfigs.forEach(config => {
        const group = this.createConfigGroup(config);
        if (group && configArea) {
          configArea.appendChild(group);
        }
      });

      // 添加关键词设置区域
      if (this.config.get('keywordMonitoring')) {
        const keywordSection = this.createKeywordSection();
        if (keywordSection && configArea) {
          configArea.appendChild(keywordSection);
        }
      }
    }

    showUIConfig() {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到 (showUIConfig)');
        return;
      }

      const uiConfigs = [
        { key: 'theme', label: '主题', type: 'select', options: [
          { value: 'light', label: '浅色主题' },
          { value: 'dark', label: '深色主题' },
          { value: 'auto', label: '跟随系统' }
        ], desc: '选择界面主题' },
        { key: 'language', label: '语言', type: 'select', options: [
          { value: 'zh-CN', label: '简体中文' },
          { value: 'zh-TW', label: '繁体中文' },
          { value: 'en-US', label: 'English' }
        ], desc: '选择界面语言' },
        { key: 'showStatistics', label: '显示统计信息', type: 'checkbox', desc: '在界面中显示运行统计' },
        { key: 'compactMode', label: '紧凑模式', type: 'checkbox', desc: '使用更紧凑的界面布局' },
        { key: 'maxLogEntries', label: '最大日志条目', type: 'number', min: 50, max: 1000, step: 50, desc: '日志窗口保留的最大条目数' }
      ];

      uiConfigs.forEach(config => {
        const group = this.createConfigGroup(config);
        if (group && configArea) {
          configArea.appendChild(group);
        }
      });
    }

    showDataConfig() {
      const configArea = document.getElementById('config-area');
      if (!configArea) {
        console.error('配置区域元素未找到 (showDataConfig)');
        return;
      }

      // 数据管理区域
      const dataSection = document.createElement('div');
      if (!dataSection) {
        console.error('无法创建数据管理区域');
        return;
      }

      dataSection.innerHTML = `
        <h3 style="margin-top: 0; color: inherit;">📊 数据管理</h3>
        <div style="display: grid; gap: 15px;">
          <div style="padding: 15px; border: 1px solid currentColor; border-radius: 8px; opacity: 0.8;">
            <h4 style="margin: 0 0 10px 0;">配置管理</h4>
            <div style="display: flex; gap: 10px; flex-wrap: wrap;">
              <button id="export-config" style="padding: 8px 16px; border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 4px; cursor: pointer;">导出配置</button>
              <button id="import-config" style="padding: 8px 16px; border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 4px; cursor: pointer;">导入配置</button>
              <button id="reset-config" style="padding: 8px 16px; border: 1px solid #dc3545; background: transparent; color: #dc3545; border-radius: 4px; cursor: pointer;">重置配置</button>
            </div>
          </div>
          <div style="padding: 15px; border: 1px solid currentColor; border-radius: 8px; opacity: 0.8;">
            <h4 style="margin: 0 0 10px 0;">数据清理</h4>
            <div style="display: flex; gap: 10px; flex-wrap: wrap;">
              <button id="clear-logs" style="padding: 8px 16px; border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 4px; cursor: pointer;">清空日志</button>
              <button id="clear-cache" style="padding: 8px 16px; border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 4px; cursor: pointer;">清空缓存</button>
              <button id="clear-all" style="padding: 8px 16px; border: 1px solid #dc3545; background: transparent; color: #dc3545; border-radius: 4px; cursor: pointer;">清空所有数据</button>
            </div>
          </div>
        </div>
      `;

      try {
        configArea.appendChild(dataSection);
        // 绑定事件
        this.bindDataManagementEvents();
      } catch (e) {
        console.error('添加数据管理区域失败:', e);
      }
    }

    createConfigGroup(config) {
      const group = document.createElement('div');
      Object.assign(group.style, {
        marginBottom: '20px',
        padding: '15px',
        border: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`,
        borderRadius: '8px',
        backgroundColor: this.config.get('theme') === 'dark' ? '#374151' : '#f8fafc'
      });

      const label = document.createElement('label');
      label.style.display = 'block';
      label.style.marginBottom = '8px';
      label.style.fontWeight = '500';
      label.innerHTML = `${config.label} ${config.desc ? `<small style="opacity: 0.7; font-weight: normal;">(${config.desc})</small>` : ''}`;

      let input;
      const currentValue = config.transform ? config.transform(this.config.get(config.key)) : this.config.get(config.key);

      switch (config.type) {
        case 'number':
          input = document.createElement('input');
          input.type = 'number';
          input.min = config.min;
          input.max = config.max;
          input.step = config.step;
          input.value = currentValue;
          break;

        case 'range':
          const container = document.createElement('div');
          container.style.display = 'flex';
          container.style.alignItems = 'center';
          container.style.gap = '10px';

          input = document.createElement('input');
          input.type = 'range';
          input.min = config.min;
          input.max = config.max;
          input.step = config.step;
          input.value = currentValue;

          const valueDisplay = document.createElement('span');
          valueDisplay.textContent = currentValue;
          valueDisplay.style.minWidth = '50px';
          valueDisplay.style.textAlign = 'center';
          valueDisplay.style.fontSize = '14px';

          input.addEventListener('input', () => {
            valueDisplay.textContent = input.value;
          });

          container.appendChild(input);
          container.appendChild(valueDisplay);
          group.appendChild(label);
          group.appendChild(container);

          input.addEventListener('change', () => {
            this.config.set(config.key, parseFloat(input.value));
            this.logger.log(`配置已更新: ${config.label} = ${input.value}`, 'action');
          });

          return group;

        case 'checkbox':
          input = document.createElement('input');
          input.type = 'checkbox';
          input.checked = currentValue;
          input.style.marginRight = '8px';

          const checkboxLabel = document.createElement('label');
          checkboxLabel.style.display = 'flex';
          checkboxLabel.style.alignItems = 'center';
          checkboxLabel.style.cursor = 'pointer';
          checkboxLabel.appendChild(input);
          checkboxLabel.appendChild(document.createTextNode(config.label));

          if (config.desc) {
            const desc = document.createElement('div');
            desc.style.fontSize = '12px';
            desc.style.opacity = '0.7';
            desc.style.marginTop = '4px';
            desc.textContent = config.desc;
            group.appendChild(checkboxLabel);
            group.appendChild(desc);
          } else {
            group.appendChild(checkboxLabel);
          }

          input.addEventListener('change', () => {
            this.config.set(config.key, input.checked);
            this.logger.log(`配置已更新: ${config.label} = ${input.checked}`, 'action');

            // 特殊处理某些配置变更
            if (config.key === 'theme') {
              this.applyTheme();
            }
          });

          return group;

        case 'select':
          input = document.createElement('select');
          config.options.forEach(option => {
            const optionElement = document.createElement('option');
            optionElement.value = option.value;
            optionElement.textContent = option.label;
            optionElement.selected = option.value === currentValue;
            input.appendChild(optionElement);
          });
          break;

        default:
          input = document.createElement('input');
          input.type = 'text';
          input.value = currentValue;
      }

      // 通用样式
      if (input && config.type !== 'checkbox') {
        Object.assign(input.style, {
          width: '100%',
          padding: '8px 12px',
          border: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#d1d5db'}`,
          borderRadius: '6px',
          backgroundColor: this.config.get('theme') === 'dark' ? '#1f2937' : '#ffffff',
          color: 'inherit',
          fontSize: '14px'
        });

        // 通用事件处理
        input.addEventListener('change', () => {
          let value = input.value;
          if (config.type === 'number') {
            value = parseFloat(value);
            if (config.reverseTransform) {
              value = config.reverseTransform(value);
            }
          }
          this.config.set(config.key, value);
          this.logger.log(`配置已更新: ${config.label} = ${input.value}`, 'action');

          // 特殊处理
          if (config.key === 'theme') {
            this.applyTheme();
          }
        });
      }

      if (config.type !== 'checkbox') {
        group.appendChild(label);
        group.appendChild(input);
      }

      return group;
    }

    bindDataManagementEvents() {
      // 导出配置
      document.getElementById('export-config')?.addEventListener('click', () => {
        const configStr = this.config.exportConfig();
        const blob = new Blob([configStr], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `forum-assistant-config-${new Date().toISOString().split('T')[0]}.json`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        this.logger.log('配置已导出', 'success');
      });

      // 导入配置
      document.getElementById('import-config')?.addEventListener('click', () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json';
        input.addEventListener('change', (e) => {
          const file = e.target.files[0];
          if (file) {
            const reader = new FileReader();
            reader.onload = (e) => {
              try {
                const success = this.config.importConfig(e.target.result);
                if (success) {
                  this.logger.log('配置导入成功', 'success');
                  this.hide();
                  setTimeout(() => location.reload(), 1000);
                } else {
                  this.logger.log('配置导入失败', 'error');
                }
              } catch (error) {
                this.logger.log(`配置导入错误: ${error.message}`, 'error');
              }
            };
            reader.readAsText(file);
          }
        });
        input.click();
      });

      // 重置配置
      document.getElementById('reset-config')?.addEventListener('click', () => {
        if (confirm('确定要重置所有配置吗?此操作不可撤销。')) {
          this.config.reset();
          this.logger.log('配置已重置', 'action');
          this.hide();
          setTimeout(() => location.reload(), 1000);
        }
      });

      // 清空日志
      document.getElementById('clear-logs')?.addEventListener('click', () => {
        this.logger.clear();
      });

      // 清空缓存
      document.getElementById('clear-cache')?.addEventListener('click', () => {
        if (confirm('确定要清空所有缓存数据吗?')) {
          GM_listValues().forEach(key => {
            if (key.startsWith('topicList') || key.startsWith('latestPage')) {
              GM_deleteValue(key);
            }
          });
          this.logger.log('缓存已清空', 'action');
        }
      });

      // 清空所有数据
      document.getElementById('clear-all')?.addEventListener('click', () => {
        if (confirm('确定要清空所有数据吗?这将删除所有配置、日志和缓存数据。')) {
          GM_listValues().forEach(key => GM_deleteValue(key));
          this.logger.log('所有数据已清空', 'action');
          setTimeout(() => location.reload(), 1000);
        }
      });
    }

    createKeywordSection() {
      const section = document.createElement('div');
      section.style.marginTop = '20px';
      section.innerHTML = `
        <h4 style="margin: 0 0 15px 0; color: inherit;">🔍 关键词监控设置</h4>
        <div style="display: grid; gap: 10px;">
          <div>
            <label style="display: block; margin-bottom: 5px; font-weight: 500;">监控关键词 (每行一个):</label>
            <textarea id="keywords-input" style="width: 100%; height: 100px; padding: 8px; border: 1px solid currentColor; border-radius: 4px; background: transparent; color: inherit; resize: vertical;" placeholder="输入要监控的关键词,每行一个"></textarea>
          </div>
          <div>
            <label style="display: block; margin-bottom: 5px; font-weight: 500;">触发动作:</label>
            <select id="keyword-action" style="width: 100%; padding: 8px; border: 1px solid currentColor; border-radius: 4px; background: transparent; color: inherit;">
              <option value="like">自动点赞</option>
              <option value="reply">自动回复</option>
              <option value="notify">仅通知</option>
              <option value="collect">收藏帖子</option>
            </select>
          </div>
        </div>
      `;

      // 加载已保存的关键词
      const savedKeywords = this.config.get('monitorKeywords') || [];
      const keywordsInput = section.querySelector('#keywords-input');
      keywordsInput.value = savedKeywords.join('\n');

      // 保存关键词
      keywordsInput.addEventListener('blur', () => {
        const keywords = keywordsInput.value.split('\n').filter(k => k.trim());
        this.config.set('monitorKeywords', keywords);
        this.logger.log(`关键词已更新: ${keywords.length} 个`, 'action');
      });

      return section;
    }

    createFooter() {
      const footer = document.createElement('div');
      Object.assign(footer.style, {
        padding: '20px',
        borderTop: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`,
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center'
      });

      const version = document.createElement('span');
      version.textContent = 'v2.0.0';
      version.style.opacity = '0.6';
      version.style.fontSize = '12px';

      const buttons = document.createElement('div');
      buttons.style.display = 'flex';
      buttons.style.gap = '10px';

      const saveBtn = document.createElement('button');
      saveBtn.textContent = '保存设置';
      Object.assign(saveBtn.style, {
        padding: '8px 16px',
        backgroundColor: '#3182ce',
        color: 'white',
        border: 'none',
        borderRadius: '6px',
        cursor: 'pointer',
        fontSize: '14px',
        fontWeight: '500'
      });
      saveBtn.addEventListener('click', () => {
        this.config.saveConfig();
        this.logger.log('配置已保存', 'success');
        this.hide();
      });

      const cancelBtn = document.createElement('button');
      cancelBtn.textContent = '取消';
      Object.assign(cancelBtn.style, {
        padding: '8px 16px',
        backgroundColor: 'transparent',
        color: 'inherit',
        border: '1px solid currentColor',
        borderRadius: '6px',
        cursor: 'pointer',
        fontSize: '14px'
      });
      cancelBtn.addEventListener('click', () => this.hide());

      buttons.appendChild(cancelBtn);
      buttons.appendChild(saveBtn);
      footer.appendChild(version);
      footer.appendChild(buttons);
      this.panel.appendChild(footer);
    }

    createOverlay() {
      this.overlay = document.createElement('div');
      Object.assign(this.overlay.style, {
        position: 'fixed',
        top: '0',
        left: '0',
        width: '100%',
        height: '100%',
        backgroundColor: 'rgba(0, 0, 0, 0.5)',
        zIndex: '10000',
        display: 'none'
      });
      this.overlay.addEventListener('click', () => this.hide());
      document.body.appendChild(this.overlay);
    }

    show() {
      if (!this.panel) this.create();
      this.panel.style.display = 'flex';
      this.overlay.style.display = 'block';
      this.isVisible = true;
    }

    hide() {
      if (this.panel) this.panel.style.display = 'none';
      if (this.overlay) this.overlay.style.display = 'none';
      this.isVisible = false;
    }

    toggle() {
      if (this.isVisible) {
        this.hide();
      } else {
        this.show();
      }
    }

    applyTheme() {
      // 重新创建面板以应用新主题
      if (this.panel) {
        this.panel.remove();
        this.panel = null;
      }
      if (this.isVisible) {
        this.create();
        this.show();
      }
    }
  }

  // ===== 统计面板类 =====
  class StatisticsPanel {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.panel = null;
      this.isVisible = false;
      this.updateInterval = null;
      this.energyValue = '加载中...';
    }

    create() {
      if (this.panel) return;

      const isDark = this.config.get('theme') === 'dark';

      this.panel = document.createElement('div');
      this.panel.id = 'forum-assistant-stats';
      Object.assign(this.panel.style, {
        position: 'fixed',
        bottom: '10px',
        left: '10px',
        width: '280px',
        backgroundColor: isDark ? '#2d3748' : '#ffffff',
        color: isDark ? '#e2e8f0' : '#2d3748',
        border: `1px solid ${isDark ? '#4a5568' : '#e2e8f0'}`,
        borderRadius: '8px',
        boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
        zIndex: '9999',
        display: 'none',
        flexDirection: 'column',
        fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
        fontSize: '12px',
        backdropFilter: 'blur(10px)'
      });

      this.createHeader();
      this.createContent();

      document.body.appendChild(this.panel);
    }

    createHeader() {
      const header = document.createElement('div');
      Object.assign(header.style, {
        padding: '10px 12px',
        borderBottom: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`,
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        fontWeight: '600'
      });

      const title = document.createElement('span');
      title.textContent = '📊 运行统计';

      const toggleBtn = document.createElement('button');
      toggleBtn.innerHTML = '−';
      Object.assign(toggleBtn.style, {
        background: 'none',
        border: 'none',
        color: 'inherit',
        cursor: 'pointer',
        fontSize: '16px',
        padding: '2px 6px',
        borderRadius: '3px'
      });
      toggleBtn.addEventListener('click', () => this.toggleMinimize());

      header.appendChild(title);
      header.appendChild(toggleBtn);
      this.panel.appendChild(header);
    }

    createContent() {
      this.content = document.createElement('div');
      Object.assign(this.content.style, {
        padding: '12px',
        display: 'grid',
        gap: '8px'
      });

      this.panel.appendChild(this.content);
      this.updateContent();
    }

    updateContent() {
      if (!this.content) {
        console.warn('统计内容元素不存在');
        return;
      }

      try {
        const stats = this.logger.statistics;
        const runtime = Date.now() - stats.startTime;

        const items = [
          { label: '⏱️ 运行时间', value: Utils.formatTime(runtime) },
          { label: '📖 已读话题', value: stats.topicsRead },
          { label: '👍 点赞数量', value: stats.likesGiven },
          { label: '🔄 总操作数', value: stats.totalActions },
          { label: '❌ 错误次数', value: stats.errorsCount },
          { label: '📈 阅读效率', value: `${(stats.topicsRead / Math.max(runtime / 3600000, 0.1)).toFixed(1)} 话题/小时` }
        ];

        this.content.innerHTML = items.map(item => `
          <div style="display: flex; justify-content: space-between; align-items: center; padding: 4px 0;">
            <span style="opacity: 0.8;">${item.label}</span>
            <span style="font-weight: 600;">${item.value}</span>
          </div>
        `).join('') + `
          <div style="display: flex; justify-content: space-between; align-items: center; padding: 4px 0;">
            <span style="opacity: 0.8;">⚡ 能量值</span>
            <span style="font-weight: 600;">${this.energyValue}</span>
          </div>
          <div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.1);">
            <button id="reset-stats" style="width: 100%; padding: 6px 12px; border: 1px solid #dc3545;
                    background: #dc3545; color: white; border-radius: 4px; cursor: pointer; font-size: 11px;">
              🔄 重置统计
            </button>
          </div>
        `;
      } catch (e) {
        console.error('更新统计内容失败:', e);
      }
    }



    // 更新能量显示
    updateEnergyDisplay() {
      if (window.location.hostname !== 'nodeloc.cc') {
        this.energyValue = 'N/A';
        return;
      }

      GM_xmlhttpRequest({
        method: 'GET',
        url: 'https://nodeloc.cc/leaderboard/1.json',
        onload: (response) => {
          try {
            const data = JSON.parse(response.responseText);
            let energy = '--';
            if (data && data.personal && data.personal.user && typeof data.personal.user.total_score !== 'undefined') {
              energy = data.personal.user.total_score.toLocaleString();
            }
            this.energyValue = energy;
          } catch (e) {
            this.energyValue = '错误';
            console.error('[Energy Display] Error parsing data:', e);
          }
        },
        onerror: (error) => {
          this.energyValue = '失败';
          console.error('[Energy Display] Error fetching data:', error);
        }
      });
    }

    show() {
      if (!this.panel) this.create();
      this.panel.style.display = 'flex';
      this.isVisible = true;

      // 立即更新一次
      this.updateContent();
      this.updateEnergyDisplay();

      // 设置定时器
      if (this.updateInterval) clearInterval(this.updateInterval);
      this.updateInterval = setInterval(() => {
        this.updateContent();
        this.updateEnergyDisplay();
      }, 5000); // 5秒刷新一次

      // 绑定重置按钮事件
      setTimeout(() => {
        const resetBtn = document.getElementById('reset-stats');
        if (resetBtn) {
          resetBtn.addEventListener('click', () => {
            if (confirm('确定要重置所有统计数据吗?此操作不可撤销。')) {
              this.logger.resetStatistics();
              this.updateContent();
            }
          });
        }
      }, 100);
    }

    hide() {
      if (this.panel) this.panel.style.display = 'none';
      this.isVisible = false;

      // 停止更新
      if (this.updateInterval) {
        clearInterval(this.updateInterval);
        this.updateInterval = null;
      }
    }

    toggle() {
      if (this.isVisible) {
        this.hide();
      } else {
        this.show();
      }
    }

    toggleMinimize() {
      if (!this.content || !this.panel) return;

      const toggleBtn = this.panel.querySelector('button');
      if (!toggleBtn) return;

      if (this.content.style.display === 'none') {
        this.content.style.display = 'grid';
        toggleBtn.innerHTML = '−';
      } else {
        this.content.style.display = 'none';
        toggleBtn.innerHTML = '+';
      }
    }
  }

  // ===== 升级进度面板类 =====
  class UpgradeProgressPanel {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.panel = null;
      this.isVisible = false;
      this.updateInterval = null;
      this.upgradeProgress = '加载中...';
      this.unmetConditions = null;
      this.customUsername = GM_getValue('customUsername', '');
      this.currentUsername = null;
    }

    create() {
      if (this.panel) return;

      const isDark = this.config.get('theme') === 'dark';

      this.panel = document.createElement('div');
      this.panel.id = 'forum-assistant-upgrade';

      // 获取保存的位置,默认为左上角
      const savedPosition = GM_getValue('upgradeProgressPosition', { top: '10px', left: '10px' });

      Object.assign(this.panel.style, {
        position: 'fixed',
        top: savedPosition.top,
        left: savedPosition.left,
        width: '300px',
        backgroundColor: isDark ? '#2d3748' : '#ffffff',
        color: isDark ? '#e2e8f0' : '#2d3748',
        border: `1px solid ${isDark ? '#4a5568' : '#e2e8f0'}`,
        borderRadius: '8px',
        boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
        zIndex: '9998',
        display: 'none',
        flexDirection: 'column',
        fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
        fontSize: '12px',
        backdropFilter: 'blur(10px)'
      });

      this.createHeader();
      this.createContent();

      document.body.appendChild(this.panel);
    }

    createHeader() {
      const header = document.createElement('div');
      Object.assign(header.style, {
        padding: '10px 12px',
        borderBottom: `1px solid ${this.config.get('theme') === 'dark' ? '#4a5568' : '#e2e8f0'}`,
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        fontWeight: '600',
        cursor: 'move',
        userSelect: 'none',
        background: this.config.get('theme') === 'dark' ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.02)'
      });

      const title = document.createElement('span');
      title.textContent = '📈 升级进度';

      const toggleBtn = document.createElement('button');
      toggleBtn.innerHTML = '−';
      Object.assign(toggleBtn.style, {
        background: 'none',
        border: 'none',
        color: 'inherit',
        cursor: 'pointer',
        fontSize: '16px',
        padding: '2px 6px',
        borderRadius: '3px'
      });
      toggleBtn.addEventListener('click', () => this.hide());

      header.appendChild(title);
      header.appendChild(toggleBtn);
      this.panel.appendChild(header);

      // 使窗口可拖拽
      this.makeDraggable(header);
    }

    createContent() {
      this.content = document.createElement('div');
      Object.assign(this.content.style, {
        padding: '15px',
        display: 'flex',
        flexDirection: 'column',
        gap: '12px'
      });

      this.panel.appendChild(this.content);
      this.updateContent();
    }

    updateContent() {
      if (!this.content) return;

      const username = this.getEffectiveUsername();

      this.content.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: center;">
          <span style="opacity: 0.8;">👤 用户名:</span>
          <span style="font-weight: 600;">${username || '未设置'}</span>
        </div>
        <div style="display: flex; justify-content: space-between; align-items: center;">
          <span style="opacity: 0.8;">📊 当前进度:</span>
          <span style="font-weight: 600;">${this.upgradeProgress}</span>
        </div>
        ${this.unmetConditions ? `
        <div style="margin-top: 8px; padding: 8px; background: rgba(255,193,7,0.1); border-radius: 4px; border-left: 3px solid #ffc107;">
          <div style="font-size: 11px; font-weight: 600; margin-bottom: 4px; color: #f59e0b;">⚠️ 未完成条件:</div>
          <div style="font-size: 10px; line-height: 1.4; opacity: 0.9;">
            ${this.unmetConditions.map(condition => `• ${condition}`).join('<br>')}
          </div>
        </div>
        ` : ''}
        <div style="margin-top: 8px;">
          <input type="text" id="custom-username" placeholder="输入自定义用户名"
                 value="${this.customUsername}"
                 style="width: 100%; padding: 6px 8px; border: 1px solid currentColor; border-radius: 4px;
                        background: transparent; color: inherit; font-size: 12px;">
        </div>
        <div style="margin-top: 8px; display: flex; gap: 8px;">
          <button id="save-username" style="flex: 1; padding: 6px 12px; border: 1px solid #3182ce;
                  background: #3182ce; color: white; border-radius: 4px; cursor: pointer; font-size: 11px;">
            保存用户名
          </button>
          <button id="refresh-progress" style="flex: 1; padding: 6px 12px; border: 1px solid currentColor;
                  background: transparent; color: inherit; border-radius: 4px; cursor: pointer; font-size: 11px;">
            刷新进度
          </button>
        </div>
        <div style="margin-top: 8px; display: flex; gap: 8px;">
          <button id="test-api" style="flex: 1; padding: 6px 12px; border: 1px solid #e53e3e;
                  background: #e53e3e; color: white; border-radius: 4px; cursor: pointer; font-size: 11px;">
            🔧 测试API
          </button>
          <button id="reset-position" style="flex: 1; padding: 6px 12px; border: 1px solid #6b7280;
                  background: #6b7280; color: white; border-radius: 4px; cursor: pointer; font-size: 11px;">
            📍 重置位置
          </button>
        </div>
      `;

      // 绑定事件
      this.bindEvents();
    }

    bindEvents() {
      const saveBtn = this.content.querySelector('#save-username');
      const refreshBtn = this.content.querySelector('#refresh-progress');
      const testBtn = this.content.querySelector('#test-api');
      const resetPosBtn = this.content.querySelector('#reset-position');
      const usernameInput = this.content.querySelector('#custom-username');

      if (saveBtn) {
        saveBtn.addEventListener('click', () => {
          const username = usernameInput.value.trim();
          this.customUsername = username;
          GM_setValue('customUsername', username);
          this.logger.log(`自定义用户名已保存: ${username || '(清空)'}`, 'success');
          this.updateContent();
          this.updateUpgradeProgress();
        });
      }

      if (refreshBtn) {
        refreshBtn.addEventListener('click', () => {
          this.updateUpgradeProgress();
          this.logger.log('手动刷新升级进度', 'action');
        });
      }

      if (testBtn) {
        testBtn.addEventListener('click', () => {
          this.testApiConnection();
        });
      }

      if (resetPosBtn) {
        resetPosBtn.addEventListener('click', () => {
          this.resetPosition();
        });
      }
    }

    makeDraggable(header) {
      if (!header || !this.panel) return;

      let isDragging = false;
      let currentX, currentY, initialX, initialY;

      header.addEventListener("mousedown", (e) => {
        if (!this.panel) return;
        isDragging = true;
        initialX = e.clientX - this.panel.offsetLeft;
        initialY = e.clientY - this.panel.offsetTop;
        header.style.cursor = 'grabbing';
      });

      document.addEventListener("mousemove", (e) => {
        if (isDragging && this.panel) {
          e.preventDefault();
          currentX = e.clientX - initialX;
          currentY = e.clientY - initialY;

          // 限制在屏幕范围内
          const maxX = window.innerWidth - this.panel.offsetWidth;
          const maxY = window.innerHeight - this.panel.offsetHeight;

          currentX = Math.max(0, Math.min(currentX, maxX));
          currentY = Math.max(0, Math.min(currentY, maxY));

          this.panel.style.left = currentX + "px";
          this.panel.style.top = currentY + "px";
          this.panel.style.right = "auto";
          this.panel.style.bottom = "auto";
        }
      });

      document.addEventListener("mouseup", () => {
        if (isDragging && this.panel) {
          isDragging = false;
          header.style.cursor = 'move';

          // 保存当前位置
          const position = {
            top: this.panel.style.top,
            left: this.panel.style.left
          };
          GM_setValue('upgradeProgressPosition', position);
          console.log('[Upgrade Progress] 位置已保存:', position);
        }
      });
    }

    getEffectiveUsername() {
      // 优先使用自定义用户名
      if (this.customUsername) {
        return this.customUsername;
      }

      // 其次使用自动检测的用户名
      if (!this.currentUsername) {
        this.currentUsername = this.getCurrentUsername();
      }

      return this.currentUsername;
    }

    resetPosition() {
      // 重置到默认位置(左上角)
      const defaultPosition = { top: '10px', left: '10px' };

      if (this.panel) {
        this.panel.style.top = defaultPosition.top;
        this.panel.style.left = defaultPosition.left;
        this.panel.style.right = 'auto';
        this.panel.style.bottom = 'auto';
      }

      // 保存重置后的位置
      GM_setValue('upgradeProgressPosition', defaultPosition);
      this.logger.log('升级进度窗口位置已重置到左上角', 'success');
    }

    testApiConnection() {
      const username = this.getEffectiveUsername();
      if (!username) {
        alert('请先设置用户名');
        return;
      }

      this.logger.log('开始测试API连接...', 'action');

      // 测试基本的用户信息API
      GM_xmlhttpRequest({
        method: 'GET',
        url: `https://nodeloc.cc/u/${username}.json`,
        headers: {
          'Accept': 'application/json',
          'X-Requested-With': 'XMLHttpRequest',
          'Referer': window.location.href
        },
        onload: (response) => {
          console.log(`[API Test] 用户信息API响应状态: ${response.status}`);
          console.log(`[API Test] 用户信息API响应内容:`, response.responseText);

          if (response.status === 200) {
            try {
              const data = JSON.parse(response.responseText);
              if (data.user) {
                this.logger.log(`✅ 用户信息API正常,用户ID: ${data.user.id}`, 'success');

                // 继续测试升级进度API
                this.testUpgradeProgressApi(username);
              } else {
                this.logger.log('❌ 用户信息API返回数据异常', 'error');
              }
            } catch (e) {
              this.logger.log('❌ 用户信息API数据解析失败', 'error');
            }
          } else {
            this.logger.log(`❌ 用户信息API请求失败 (${response.status})`, 'error');
          }
        },
        onerror: (error) => {
          this.logger.log('❌ 用户信息API网络错误', 'error');
          console.error('[API Test] 用户信息API网络错误:', error);
        }
      });
    }

    testUpgradeProgressApi(username) {
      GM_xmlhttpRequest({
        method: 'GET',
        url: `https://nodeloc.cc/u/${username}/upgrade-progress.json`,
        headers: {
          'Accept': 'application/json, text/javascript, */*; q=0.01',
          'X-Requested-With': 'XMLHttpRequest',
          'Referer': window.location.href
        },
        onload: (response) => {
          console.log(`[API Test] 升级进度API响应状态: ${response.status}`);
          console.log(`[API Test] 升级进度API响应内容:`, response.responseText);

          if (response.status === 200) {
            try {
              const data = JSON.parse(response.responseText);
              console.log('[API Test] 升级进度API完整响应:', JSON.stringify(data, null, 2));

              if (data) {
                if (data.next_level) {
                  const nextLevel = data.next_level;
                  const nextLevelKeys = Object.keys(nextLevel);
                  this.logger.log(`✅ 升级进度API正常,next_level字段: ${nextLevelKeys.join(', ')}`, 'success');
                  console.log('[API Test] next_level详细数据:', nextLevel);
                  console.log('[API Test] next_level类型:', typeof nextLevel);

                  // 分析next_level的具体内容
                  if (typeof nextLevel === 'object') {
                    Object.entries(nextLevel).forEach(([key, value]) => {
                      console.log(`[API Test] next_level.${key}:`, value, `(类型: ${typeof value})`);
                    });
                  }
                } else {
                  const keys = Object.keys(data);
                  this.logger.log(`⚠️ 升级进度API无next_level,可用字段: ${keys.join(', ')}`, 'warning');
                  console.log('[API Test] 可用数据字段:', keys);
                  console.log('[API Test] 完整数据:', data);
                }
              } else {
                this.logger.log('❌ 升级进度API返回空数据', 'error');
              }
            } catch (e) {
              this.logger.log('❌ 升级进度API数据解析失败', 'error');
              console.error('[API Test] 解析错误:', e);
              console.error('[API Test] 原始响应:', response.responseText);
            }
          } else if (response.status === 403) {
            this.logger.log('❌ 升级进度API权限不足,可能需要登录', 'error');
          } else if (response.status === 404) {
            this.logger.log('❌ 升级进度API不存在或用户不存在', 'error');
          } else {
            this.logger.log(`❌ 升级进度API请求失败 (${response.status})`, 'error');
          }
        },
        onerror: (error) => {
          this.logger.log('❌ 升级进度API网络错误', 'error');
          console.error('[API Test] 升级进度API网络错误:', error);
        }
      });
    }

    getCurrentUsername() {
      // 方法1: 从用户菜单按钮获取
      const userMenuButton = document.querySelector('.header-dropdown-toggle.current-user');
      if (userMenuButton) {
        const img = userMenuButton.querySelector('img');
        if (img && img.alt) {
          console.log(`[Username] 从用户菜单获取到用户名: ${img.alt}`);
          return img.alt;
        }
      }

      // 方法2: 从用户链接获取
      const userLinks = document.querySelectorAll('a[href*="/u/"]');
      for (const userLink of userLinks) {
        const match = userLink.href.match(/\/u\/([^\/]+)/);
        if (match && match[1]) {
          console.log(`[Username] 从用户链接获取到用户名: ${match[1]}`);
          return match[1];
        }
      }

      // 方法3: 从当前页面URL获取(如果在用户页面)
      if (window.location.pathname.includes('/u/')) {
        const match = window.location.pathname.match(/\/u\/([^\/]+)/);
        if (match && match[1]) {
          console.log(`[Username] 从URL获取到用户名: ${match[1]}`);
          return match[1];
        }
      }

      // 方法4: 从页面标题获取
      const titleMatch = document.title.match(/(.+?)\s*-\s*NodeLoc/);
      if (titleMatch && titleMatch[1] && !titleMatch[1].includes('NodeLoc')) {
        console.log(`[Username] 从页面标题获取到用户名: ${titleMatch[1]}`);
        return titleMatch[1];
      }

      // 方法5: 从meta标签获取
      const metaUser = document.querySelector('meta[name="discourse-username"]');
      if (metaUser && metaUser.content) {
        console.log(`[Username] 从meta标签获取到用户名: ${metaUser.content}`);
        return metaUser.content;
      }

      console.log('[Username] 无法自动获取用户名');
      return null;
    }

    updateUpgradeProgress() {
      if (window.location.hostname !== 'nodeloc.cc') {
        this.upgradeProgress = 'N/A (非NodeLoc站点)';
        this.updateContent();
        return;
      }

      const username = this.getEffectiveUsername();
      if (!username) {
        this.upgradeProgress = '未设置用户名';
        this.updateContent();
        return;
      }

      this.upgradeProgress = '获取中...';
      this.updateContent();

      console.log(`[Upgrade Progress] 正在获取用户 ${username} 的升级进度`);

      GM_xmlhttpRequest({
        method: 'GET',
        url: `https://nodeloc.cc/u/${username}/upgrade-progress.json`,
        headers: {
          'Accept': 'application/json, text/javascript, */*; q=0.01',
          'X-Requested-With': 'XMLHttpRequest',
          'Referer': window.location.href
        },
        onload: (response) => {
          console.log(`[Upgrade Progress] 响应状态: ${response.status}`);
          console.log(`[Upgrade Progress] 响应内容:`, response.responseText);

          try {
            if (response.status === 200) {
              const data = JSON.parse(response.responseText);
              let progress = '获取不到信息';

              console.log(`[Upgrade Progress] 解析的数据:`, data);

              // 检查数据结构
              if (data) {
                console.log(`[Upgrade Progress] 完整数据结构:`, JSON.stringify(data, null, 2));

                // 方案1: 检查升级进度数据(基于真实的NodeLoc API结构)
                if (data.next_level !== undefined && data.next_level_name && data.met_count !== undefined && data.total_conditions !== undefined) {
                  // NodeLoc的真实数据结构
                  const nextLevelName = data.next_level_name;
                  const metCount = data.met_count;
                  const totalConditions = data.total_conditions;
                  const percentage = Math.round((metCount / totalConditions) * 100);

                  progress = `${nextLevelName} ${percentage}% (${metCount}/${totalConditions})`;

                  // 保存未完成条件
                  if (data.unmet_conditions && Array.isArray(data.unmet_conditions)) {
                    this.unmetConditions = data.unmet_conditions;
                  } else {
                    this.unmetConditions = null;
                  }

                  console.log(`[Upgrade Progress] 解析成功: ${progress}`);
                }
                // 方案2: 如果有next_level但结构不同
                else if (data.next_level) {
                  const nextLevel = data.next_level;
                  console.log(`[Upgrade Progress] next_level详细信息:`, nextLevel);
                  console.log(`[Upgrade Progress] next_level类型:`, typeof nextLevel);

                  if (typeof nextLevel === 'number') {
                    // next_level是数字,查找等级名称
                    if (data.next_level_name) {
                      progress = `下一等级: ${data.next_level_name} (等级${nextLevel})`;
                    } else {
                      const levelNames = ['新手', '基础会员', '会员', '资深会员', '钻石会员', '领导者'];
                      progress = `下一等级: ${levelNames[nextLevel] || `等级${nextLevel}`}`;
                    }
                  }
                  else if (typeof nextLevel === 'object') {
                    // 检查各种可能的字段组合
                    if (nextLevel.name && nextLevel.progress !== undefined && nextLevel.total !== undefined) {
                      const percentage = Math.round((nextLevel.progress / nextLevel.total) * 100);
                      progress = `${nextLevel.name} ${percentage}%`;
                    }
                    else if (nextLevel.name && nextLevel.current !== undefined && nextLevel.required !== undefined) {
                      const percentage = Math.round((nextLevel.current / nextLevel.required) * 100);
                      progress = `${nextLevel.name} ${percentage}%`;
                    }
                    else if (nextLevel.name) {
                      progress = `下一等级: ${nextLevel.name}`;
                    }
                    else {
                      // 显示对象的所有键值对
                      const entries = Object.entries(nextLevel).map(([key, value]) => `${key}: ${value}`);
                      progress = `next_level: {${entries.join(', ')}}`;
                    }
                  }
                  else if (typeof nextLevel === 'string') {
                    progress = `下一等级: ${nextLevel}`;
                  }
                  else {
                    progress = `next_level: ${JSON.stringify(nextLevel)}`;
                  }
                }
                // 方案2: 检查用户信任等级
                else if (data.user && data.user.trust_level !== undefined) {
                  const trustLevel = data.user.trust_level;
                  const levelNames = ['新手', '基础会员', '会员', '资深会员', '领导者'];
                  progress = `信任等级 ${trustLevel} (${levelNames[trustLevel] || '未知'})`;
                }
                // 方案3: 检查其他可能的数据结构
                else if (data.upgrade_progress) {
                  progress = `进度: ${JSON.stringify(data.upgrade_progress)}`;
                }
                else if (data.level_info) {
                  progress = `等级信息: ${JSON.stringify(data.level_info)}`;
                }
                else if (data.progress) {
                  progress = `进度: ${JSON.stringify(data.progress)}`;
                }
                // 方案4: 显示所有可用的键
                else {
                  const keys = Object.keys(data);
                  progress = `可用字段: ${keys.join(', ')}`;
                  console.warn('[Upgrade Progress] 未识别的数据结构,可用字段:', keys);
                  console.warn('[Upgrade Progress] 完整数据:', data);
                }
              } else {
                progress = '数据为空';
              }

              this.upgradeProgress = progress;
            } else if (response.status === 403) {
              this.upgradeProgress = '权限不足';
            } else if (response.status === 404) {
              this.upgradeProgress = '用户不存在';
            } else {
              this.upgradeProgress = `请求失败 (${response.status})`;
            }

            this.updateContent();
          } catch (e) {
            this.upgradeProgress = '数据解析错误';
            this.updateContent();
            console.error('[Upgrade Progress] 解析错误:', e);
            console.error('[Upgrade Progress] 原始响应:', response.responseText);
          }
        },
        onerror: (error) => {
          this.upgradeProgress = '网络请求失败';
          this.updateContent();
          console.error('[Upgrade Progress] 网络错误:', error);
        },
        ontimeout: () => {
          this.upgradeProgress = '请求超时';
          this.updateContent();
          console.error('[Upgrade Progress] 请求超时');
        },
        timeout: 10000 // 10秒超时
      });
    }

    show() {
      if (!this.panel) this.create();
      this.panel.style.display = 'flex';
      this.isVisible = true;

      // 保存显示状态
      GM_setValue('upgradeProgressVisible', true);

      // 立即更新一次
      this.updateContent();
      this.updateUpgradeProgress();

      // 设置定时器
      if (this.updateInterval) clearInterval(this.updateInterval);
      this.updateInterval = setInterval(() => {
        this.updateUpgradeProgress();
      }, 10000); // 10秒刷新一次
    }

    hide() {
      if (this.panel) this.panel.style.display = 'none';
      this.isVisible = false;

      // 保存隐藏状态
      GM_setValue('upgradeProgressVisible', false);

      // 停止更新
      if (this.updateInterval) {
        clearInterval(this.updateInterval);
        this.updateInterval = null;
      }
    }

    toggle() {
      if (this.isVisible) {
        this.hide();
      } else {
        this.show();
      }
    }
  }

  // ===== 控制面板类 =====
  class ControlPanel {
    constructor(config, logger, statsPanel, configPanel, upgradePanel) {
      this.config = config;
      this.logger = logger;
      this.statsPanel = statsPanel;
      this.configPanel = configPanel;
      this.upgradePanel = upgradePanel;
      this.panel = null;
      this.buttons = {};
    }

    create() {
      if (this.panel) return;

      const isDark = this.config.get('theme') === 'dark';

      this.panel = document.createElement('div');
      this.panel.id = 'forum-assistant-controls';
      Object.assign(this.panel.style, {
        position: 'fixed',
        bottom: '10px',
        right: '10px',
        display: 'flex',
        flexDirection: 'column',
        gap: '8px',
        zIndex: '9999'
      });

      // 创建控制按钮
      this.createControlButtons();

      document.body.appendChild(this.panel);
    }

    createControlButtons() {
      const buttons = [
        { id: 'toggle-reading', text: '开始阅读', icon: '📖', action: () => this.toggleReading() },
        { id: 'toggle-like', text: '启用点赞', icon: '👍', action: () => this.toggleAutoLike() },
        { id: 'show-stats', text: '显示统计', icon: '📊', action: () => this.statsPanel.toggle() },
        { id: 'show-upgrade', text: '升级进度', icon: '📈', action: () => this.toggleUpgradeProgress() },
        { id: 'show-config', text: '打开设置', icon: '⚙️', action: () => this.configPanel.toggle() },
        { id: 'show-logs', text: '显示日志', icon: '📋', action: () => this.logger.toggleVisibility() }
      ];

      buttons.forEach(btn => {
        const button = this.createButton(btn);
        this.buttons[btn.id] = button;
        this.panel.appendChild(button);
      });

      this.updateButtonStates();
    }

    createButton(config) {
      const isDark = this.config.get('theme') === 'dark';

      const button = document.createElement('button');
      button.innerHTML = `${config.icon} ${config.text}`;
      Object.assign(button.style, {
        padding: '10px 15px',
        backgroundColor: isDark ? '#4a5568' : '#ffffff',
        color: isDark ? '#e2e8f0' : '#2d3748',
        border: `1px solid ${isDark ? '#718096' : '#d1d5db'}`,
        borderRadius: '8px',
        cursor: 'pointer',
        fontSize: '13px',
        fontWeight: '500',
        display: 'flex',
        alignItems: 'center',
        gap: '6px',
        minWidth: '120px',
        justifyContent: 'flex-start',
        transition: 'all 0.2s ease',
        boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
      });

      button.addEventListener('click', config.action);

      // 悬停效果
      button.addEventListener('mouseenter', () => {
        button.style.transform = 'translateY(-1px)';
        button.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
      });

      button.addEventListener('mouseleave', () => {
        button.style.transform = 'translateY(0)';
        button.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
      });

      return button;
    }

    toggleReading() {
      const isReading = GM_getValue('isReading', false);
      GM_setValue('isReading', !isReading);

      this.updateButtonStates();

      if (!isReading) {
        this.logger.log('开始自动阅读', 'action');
        // 调用主程序的开始阅读逻辑
        if (window.forumAssistant && typeof window.forumAssistant.start === 'function') {
          window.forumAssistant.start();
        }
      } else {
        this.logger.log('停止自动阅读', 'action');
        // 调用主程序的停止阅读逻辑
        if (window.forumAssistant && typeof window.forumAssistant.stop === 'function') {
          window.forumAssistant.stop();
        }
      }
    }

    toggleAutoLike() {
      const rateLimitInfo = GM_getValue('rateLimitInfo', null);

      // 检查是否仍在限制期内
      if (rateLimitInfo && this.isRateLimitActive(rateLimitInfo)) {
        const remainingTime = this.getRemainingTime(rateLimitInfo);
        const canLikeTime = this.getCanLikeTime(rateLimitInfo);

        this.logger.log(`点赞仍在限制期内,剩余时间: ${remainingTime}`, 'warning');
        this.logger.log(`📅 预计可点赞时间: ${canLikeTime}`, 'info');
        this.logger.showNotification(`点赞受限,剩余时间: ${remainingTime}`, 'warning');
        return;
      }

      // 如果限制已过期,清除限制信息
      if (rateLimitInfo && !this.isRateLimitActive(rateLimitInfo)) {
        GM_setValue('rateLimitInfo', null);
        this.logger.log('点赞限制已过期,已清除限制信息', 'success');
      }

      const isEnabled = GM_getValue('autoLikeEnabled', false);
      const newState = !isEnabled;
      GM_setValue('autoLikeEnabled', newState);

      this.updateButtonStates();

      if (newState) {
        // 启用时显示详细信息
        this.logger.log(`🎯 自动点赞已启用`, 'success');
        this.showLikeStatusInfo();
      } else {
        this.logger.log(`⏸️ 自动点赞已禁用`, 'action');
      }
    }

    // 显示点赞状态信息
    showLikeStatusInfo() {
      const rateLimitInfo = GM_getValue('rateLimitInfo', null);

      if (rateLimitInfo && this.isRateLimitActive(rateLimitInfo)) {
        // 仍在限制期内
        const remainingTime = this.getRemainingTime(rateLimitInfo);
        const canLikeTime = this.getCanLikeTime(rateLimitInfo);

        this.logger.log(`⚠️ 当前状态: 点赞受限`, 'warning');
        this.logger.log(`⏰ 剩余等待时间: ${remainingTime}`, 'warning');
        this.logger.log(`📅 预计可点赞时间: ${canLikeTime}`, 'info');
        this.logger.log(`💡 限制原因: ${rateLimitInfo.message || '未知'}`, 'info');
      } else {
        // 可以正常点赞
        const currentTime = new Date().toLocaleString('zh-CN');
        this.logger.log(`✅ 当前状态: 可以正常点赞`, 'success');
        this.logger.log(`🕐 当前时间: ${currentTime}`, 'info');

        // 显示今日点赞统计
        const dailyLikeCount = GM_getValue('dailyLikeCount', 0);
        const maxLikes = this.siteAdapter?.getLimit('maxLikes') || 100;
        this.logger.log(`📊 今日点赞: ${dailyLikeCount}/${maxLikes}`, 'info');

        if (dailyLikeCount >= maxLikes) {
          this.logger.log(`⚠️ 今日点赞已达上限`, 'warning');
        } else {
          const remaining = maxLikes - dailyLikeCount;
          this.logger.log(`💪 剩余可点赞: ${remaining} 次`, 'success');
        }
      }
    }

    // 获取可以点赞的具体时间
    getCanLikeTime(rateLimitInfo) {
      if (!rateLimitInfo || !rateLimitInfo.waitSeconds || !rateLimitInfo.timestamp) {
        return '未知';
      }

      const canLikeTimestamp = rateLimitInfo.timestamp + (rateLimitInfo.waitSeconds * 1000);
      const canLikeDate = new Date(canLikeTimestamp);

      return canLikeDate.toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      });
    }

    // 获取剩余限制时间
    getRemainingTime(rateLimitInfo) {
      if (!rateLimitInfo || !rateLimitInfo.waitSeconds || !rateLimitInfo.timestamp) {
        return '未知';
      }

      const now = Date.now();
      const limitEndTime = rateLimitInfo.timestamp + (rateLimitInfo.waitSeconds * 1000);
      const remainingMs = limitEndTime - now;

      if (remainingMs <= 0) {
        return '已过期';
      }

      const hours = Math.floor(remainingMs / (1000 * 60 * 60));
      const minutes = Math.floor((remainingMs % (1000 * 60 * 60)) / (1000 * 60));

      if (hours > 0) {
        return `${hours}小时${minutes}分钟`;
      } else {
        return `${minutes}分钟`;
      }
    }

    toggleUpgradeProgress() {
      this.upgradePanel.toggle();
      this.updateButtonStates();
      this.logger.log(`升级进度面板已${this.upgradePanel.isVisible ? '显示' : '隐藏'}`, 'action');
    }

    updateButtonStates() {
      const isReading = GM_getValue('isReading', false);
      const isLikeEnabled = GM_getValue('autoLikeEnabled', false);
      const isUpgradeVisible = this.upgradePanel.isVisible;
      const rateLimitInfo = GM_getValue('rateLimitInfo', null);

      if (this.buttons && this.buttons['toggle-reading']) {
        const btn = this.buttons['toggle-reading'];
        if (btn) {
          btn.innerHTML = `📖 ${isReading ? '停止阅读' : '开始阅读'}`;
          btn.style.backgroundColor = isReading ? '#dc3545' : (this.config.get('theme') === 'dark' ? '#4a5568' : '#ffffff');
          btn.style.color = isReading ? '#ffffff' : (this.config.get('theme') === 'dark' ? '#e2e8f0' : '#2d3748');
        }
      }

      if (this.buttons && this.buttons['toggle-like']) {
        const btn = this.buttons['toggle-like'];
        if (btn) {
          // 检查是否有限制信息
          if (rateLimitInfo && this.isRateLimitActive(rateLimitInfo)) {
            btn.innerHTML = `🚫 点赞受限`;
            btn.style.backgroundColor = '#dc3545';
            btn.style.color = '#ffffff';
            btn.title = `点赞已达限制,剩余等待时间: ${rateLimitInfo.timeLeft}`;
          } else {
            btn.innerHTML = `👍 ${isLikeEnabled ? '禁用点赞' : '启用点赞'}`;
            btn.style.backgroundColor = isLikeEnabled ? '#28a745' : (this.config.get('theme') === 'dark' ? '#4a5568' : '#ffffff');
            btn.style.color = isLikeEnabled ? '#ffffff' : (this.config.get('theme') === 'dark' ? '#e2e8f0' : '#2d3748');
            btn.title = isLikeEnabled ? '点击禁用自动点赞' : '点击启用自动点赞';
          }
        }
      }

      if (this.buttons && this.buttons['show-upgrade']) {
        const btn = this.buttons['show-upgrade'];
        if (btn) {
          btn.innerHTML = `📈 ${isUpgradeVisible ? '隐藏进度' : '升级进度'}`;
          btn.style.backgroundColor = isUpgradeVisible ? '#8b5cf6' : (this.config.get('theme') === 'dark' ? '#4a5568' : '#ffffff');
          btn.style.color = isUpgradeVisible ? '#ffffff' : (this.config.get('theme') === 'dark' ? '#e2e8f0' : '#2d3748');
        }
      }
    }

    // 检查限制是否仍然有效
    isRateLimitActive(rateLimitInfo) {
      if (!rateLimitInfo || !rateLimitInfo.waitSeconds || !rateLimitInfo.timestamp) {
        return false;
      }

      const now = Date.now();
      const limitEndTime = rateLimitInfo.timestamp + (rateLimitInfo.waitSeconds * 1000);

      return now < limitEndTime;
    }

    show() {
      if (!this.panel) this.create();
      this.panel.style.display = 'flex';
    }

    hide() {
      if (this.panel) this.panel.style.display = 'none';
    }
  }

  // ===== 状态指示器类 =====
  class StatusIndicator {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.indicator = null;
      this.statusText = null;
      this.progressBar = null;
    }

    create() {
      if (this.indicator) return;

      const isDark = this.config.get('theme') === 'dark';

      this.indicator = document.createElement('div');
      this.indicator.id = 'forum-assistant-status';
      Object.assign(this.indicator.style, {
        position: 'fixed',
        top: '10px',
        left: '50%',
        transform: 'translateX(-50%)',
        backgroundColor: isDark ? '#2d3748' : '#ffffff',
        color: isDark ? '#e2e8f0' : '#2d3748',
        border: `1px solid ${isDark ? '#4a5568' : '#e2e8f0'}`,
        borderRadius: '20px',
        padding: '8px 16px',
        fontSize: '12px',
        fontWeight: '500',
        zIndex: '9998',
        display: 'none',
        alignItems: 'center',
        gap: '8px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
        backdropFilter: 'blur(10px)',
        minWidth: '200px',
        justifyContent: 'center'
      });

      // 状态图标
      this.statusIcon = document.createElement('span');
      this.statusIcon.textContent = '⏸️';

      // 状态文本
      this.statusText = document.createElement('span');
      this.statusText.textContent = '待机中';

      // 进度条容器
      const progressContainer = document.createElement('div');
      Object.assign(progressContainer.style, {
        width: '60px',
        height: '4px',
        backgroundColor: isDark ? '#4a5568' : '#e2e8f0',
        borderRadius: '2px',
        overflow: 'hidden'
      });

      // 进度条
      this.progressBar = document.createElement('div');
      Object.assign(this.progressBar.style, {
        width: '0%',
        height: '100%',
        backgroundColor: '#3182ce',
        borderRadius: '2px',
        transition: 'width 0.3s ease'
      });

      progressContainer.appendChild(this.progressBar);

      this.indicator.appendChild(this.statusIcon);
      this.indicator.appendChild(this.statusText);
      this.indicator.appendChild(progressContainer);

      document.body.appendChild(this.indicator);
    }

    updateStatus(status, progress = 0) {
      if (!this.indicator) this.create();

      const statusConfig = {
        idle: { icon: '⏸️', text: '待机中', color: '#6b7280' },
        reading: { icon: '📖', text: '阅读中', color: '#3182ce' },
        scrolling: { icon: '🔄', text: '滚动中', color: '#10b981' },
        liking: { icon: '👍', text: '点赞中', color: '#f59e0b' },
        switching: { icon: '🔀', text: '切换话题', color: '#8b5cf6' },
        error: { icon: '❌', text: '出现错误', color: '#dc3545' },
        loading: { icon: '⏳', text: '加载中', color: '#6366f1' }
      };

      const config = statusConfig[status] || statusConfig.idle;

      if (this.statusIcon) this.statusIcon.textContent = config.icon;
      if (this.statusText) this.statusText.textContent = config.text;
      if (this.progressBar) {
        this.progressBar.style.backgroundColor = config.color;
        this.progressBar.style.width = `${Math.max(0, Math.min(100, progress))}%`;
      }

      // 自动显示/隐藏
      if (status !== 'idle') {
        this.show();
      } else {
        setTimeout(() => this.hide(), 2000);
      }
    }

    show() {
      if (!this.indicator) this.create();
      this.indicator.style.display = 'flex';
    }

    hide() {
      if (this.indicator) this.indicator.style.display = 'none';
    }
  }

  // ===== 智能行为模拟类 =====
  class BehaviorSimulator {
    constructor(config, logger, statusIndicator) {
      this.config = config;
      this.logger = logger;
      this.statusIndicator = statusIndicator;
      this.mouseTracker = null;
      this.behaviorQueue = [];
      this.isSimulating = false;
    }

    // 鼠标移动模拟
    simulateMouseMovement() {
      if (!this.config.get('enableMouseSimulation')) return;

      const startX = Math.random() * window.innerWidth;
      const startY = Math.random() * window.innerHeight;
      const endX = Math.random() * window.innerWidth;
      const endY = Math.random() * window.innerHeight;

      const duration = Utils.getRandomInt(1000, 3000);
      const steps = 30;
      const stepDuration = duration / steps;

      let currentStep = 0;
      const moveInterval = setInterval(() => {
        if (currentStep >= steps) {
          clearInterval(moveInterval);
          return;
        }

        const progress = currentStep / steps;
        const easeProgress = this.easeInOutCubic(progress);

        const currentX = startX + (endX - startX) * easeProgress;
        const currentY = startY + (endY - startY) * easeProgress;

        // 创建鼠标移动事件
        const event = new MouseEvent('mousemove', {
          clientX: currentX,
          clientY: currentY,
          bubbles: true
        });
        document.dispatchEvent(event);

        currentStep++;
      }, stepDuration);
    }

    // 随机页面交互
    async simulatePageInteraction() {
      if (!this.config.get('enableAdvancedBehavior')) return;

      const interactions = [
        () => this.simulateTextSelection(),
        () => this.simulateScrollPause(),
        () => this.simulateElementHover(),
        () => this.simulateKeyboardActivity(),
        () => this.simulateWindowResize()
      ];

      const randomInteraction = interactions[Math.floor(Math.random() * interactions.length)];
      await randomInteraction();
    }

    // 文本选择模拟
    simulateTextSelection() {
      const textElements = document.querySelectorAll('p, div, span, h1, h2, h3, h4, h5, h6');
      if (textElements.length === 0) return;

      const randomElement = textElements[Math.floor(Math.random() * textElements.length)];
      const text = randomElement.textContent;

      if (text.length > 10) {
        const startIndex = Math.floor(Math.random() * (text.length - 10));
        const endIndex = startIndex + Utils.getRandomInt(5, 20);

        try {
          const range = document.createRange();
          const textNode = randomElement.firstChild;
          if (textNode && textNode.nodeType === Node.TEXT_NODE) {
            range.setStart(textNode, Math.min(startIndex, textNode.textContent.length));
            range.setEnd(textNode, Math.min(endIndex, textNode.textContent.length));

            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);

            // 短暂保持选择状态
            setTimeout(() => {
              selection.removeAllRanges();
            }, Utils.getRandomInt(500, 2000));

            this.logger.log('模拟文本选择', 'action');
          }
        } catch (e) {
          // 忽略选择错误
        }
      }
    }

    // 滚动暂停模拟
    async simulateScrollPause() {
      const pauseDuration = Utils.getRandomInt(1000, 5000);
      this.statusIndicator.updateStatus('reading', 50);

      await Utils.sleep(pauseDuration);
      this.logger.log(`模拟阅读暂停 ${pauseDuration}ms`, 'action');
    }

    // 元素悬停模拟
    simulateElementHover() {
      const hoverableElements = document.querySelectorAll('a, button, .btn, [role="button"]');
      if (hoverableElements.length === 0) return;

      const randomElement = hoverableElements[Math.floor(Math.random() * hoverableElements.length)];

      // 触发悬停事件
      const mouseEnter = new MouseEvent('mouseenter', { bubbles: true });
      const mouseOver = new MouseEvent('mouseover', { bubbles: true });

      randomElement.dispatchEvent(mouseEnter);
      randomElement.dispatchEvent(mouseOver);

      // 短暂悬停后移开
      setTimeout(() => {
        const mouseLeave = new MouseEvent('mouseleave', { bubbles: true });
        const mouseOut = new MouseEvent('mouseout', { bubbles: true });

        randomElement.dispatchEvent(mouseLeave);
        randomElement.dispatchEvent(mouseOut);
      }, Utils.getRandomInt(500, 2000));

      this.logger.log('模拟元素悬停', 'action');
    }

    // 键盘活动模拟
    simulateKeyboardActivity() {
      const keys = ['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp', 'Home', 'End'];
      const randomKey = keys[Math.floor(Math.random() * keys.length)];

      const keyEvent = new KeyboardEvent('keydown', {
        key: randomKey,
        code: randomKey,
        bubbles: true
      });

      document.dispatchEvent(keyEvent);
      this.logger.log(`模拟按键: ${randomKey}`, 'action');
    }

    // 窗口大小调整模拟
    simulateWindowResize() {
      // 模拟窗口大小变化事件
      const resizeEvent = new Event('resize');
      window.dispatchEvent(resizeEvent);
      this.logger.log('模拟窗口调整', 'action');
    }

    // 随机行为触发
    async triggerRandomBehavior() {
      if (!this.isSimulating) return;

      const behaviors = [
        { action: () => this.simulateMouseMovement(), weight: 3 },
        { action: () => this.simulatePageInteraction(), weight: 2 },
        { action: () => this.simulateScrollPause(), weight: 1 }
      ];

      // 权重随机选择
      const totalWeight = behaviors.reduce((sum, b) => sum + b.weight, 0);
      let random = Math.random() * totalWeight;

      for (const behavior of behaviors) {
        random -= behavior.weight;
        if (random <= 0) {
          await behavior.action();
          break;
        }
      }

      // 随机间隔后再次触发
      const nextDelay = Utils.getRandomInt(5000, 15000);
      setTimeout(() => this.triggerRandomBehavior(), nextDelay);
    }

    // 缓动函数
    easeInOutCubic(t) {
      return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
    }

    // 开始行为模拟
    start() {
      if (this.isSimulating) return;

      this.isSimulating = true;
      this.logger.log('开始智能行为模拟', 'action');

      // 启动随机行为
      setTimeout(() => this.triggerRandomBehavior(), Utils.getRandomInt(2000, 5000));
    }

    // 停止行为模拟
    stop() {
      this.isSimulating = false;
      this.logger.log('停止智能行为模拟', 'action');
    }
  }

  // ===== 增强滚动系统类 =====
  class EnhancedScrollSystem {
    constructor(config, logger, statusIndicator, behaviorSimulator) {
      this.config = config;
      this.logger = logger;
      this.statusIndicator = statusIndicator;
      this.behaviorSimulator = behaviorSimulator;

      this.scrollInterval = null;
      this.checkScrollTimeout = null;
      this.lastScrollY = 0;
      this.scrollDirection = 'down';
      this.isScrolling = false;
      this.scrollStartTime = 0;
    }

    // 贝塞尔曲线分段滚动 (向下)
    async scrollWithBezier() {
      if (this.scrollInterval !== null) {
        clearInterval(this.scrollInterval);
      }

      const startY = window.scrollY;
      const documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
      const windowHeight = window.innerHeight;
      const pageBottom = documentHeight - windowHeight;

      // 检查是否已接近底部
      if (startY >= pageBottom - 10) {
        this.logger.log("已接近页面底部,停止向下滚动", 'info');
        this.statusIndicator.updateStatus('idle');
        return false;
      }

      this.isScrolling = true;
      this.scrollStartTime = Date.now();
      this.statusIndicator.updateStatus('scrolling', 0);

      // 计算滚动参数
      const segmentDistance = Utils.getRandomInt(
        this.config.get('scrollSegmentDistanceMin'),
        this.config.get('scrollSegmentDistanceMax')
      );
      const targetY = Math.min(startY + segmentDistance, pageBottom);
      const totalDuration = Utils.getRandomInt(
        this.config.get('scrollSegmentDurationMin'),
        this.config.get('scrollSegmentDurationMax')
      );
      const steps = Math.max(20, Math.round(totalDuration / 50));
      const stepDuration = totalDuration / steps;

      // 随机贝塞尔控制点
      const p0 = 0, p3 = 1;
      const p1 = Utils.getRandomFloat(this.config.get('bezierP1Min'), this.config.get('bezierP1Max'));
      const p2 = Utils.getRandomFloat(this.config.get('bezierP2Min'), this.config.get('bezierP2Max'));

      this.logger.log(`向下滚动: ${Math.round(startY)} → ${Math.round(targetY)} (${Math.round(targetY - startY)}px, ${totalDuration}ms)`, 'action');

      let currentStep = 0;

      return new Promise((resolve) => {
        this.scrollInterval = setInterval(async () => {
          if (currentStep >= steps) {
            clearInterval(this.scrollInterval);
            this.scrollInterval = null;
            this.isScrolling = false;

            window.scrollTo(0, targetY);
            this.statusIndicator.updateStatus('idle');
            this.logger.log("向下滚动完成", 'success');

            // 随机触发行为模拟
            if (Math.random() < 0.3) {
              await this.behaviorSimulator.simulatePageInteraction();
            }

            resolve(true);
            return;
          }

          const t = currentStep / steps;
          const progress = Utils.cubicBezier(t, p0, p1, p2, p3);
          const scrollPosition = startY + (targetY - startY) * progress;

          window.scrollTo(0, scrollPosition);

          // 更新进度
          const scrollProgress = (currentStep / steps) * 100;
          this.statusIndicator.updateStatus('scrolling', scrollProgress);

          currentStep++;

          // 随机暂停
          if (Math.random() < this.config.get('randomPauseProbability')) {
            const pauseDuration = Utils.getRandomInt(
              this.config.get('randomPauseDurationMin'),
              this.config.get('randomPauseDurationMax')
            );
            await Utils.sleep(pauseDuration);
          }
        }, stepDuration);
      });
    }

    // 贝塞尔曲线分段滚动 (向上)
    async scrollUpWithBezier() {
      if (this.scrollInterval !== null) {
        clearInterval(this.scrollInterval);
      }

      const startY = window.scrollY;

      // 检查是否已接近顶部
      if (startY <= 10) {
        this.logger.log("已接近页面顶部,停止向上滚动", 'info');
        this.statusIndicator.updateStatus('idle');
        return false;
      }

      this.isScrolling = true;
      this.scrollStartTime = Date.now();
      this.statusIndicator.updateStatus('scrolling', 0);

      // 计算滚动参数
      const segmentDistance = Utils.getRandomInt(
        this.config.get('scrollSegmentDistanceMin'),
        this.config.get('scrollSegmentDistanceMax')
      );
      const targetY = Math.max(startY - segmentDistance, 0);
      const totalDuration = Utils.getRandomInt(
        this.config.get('scrollSegmentDurationMin'),
        this.config.get('scrollSegmentDurationMax')
      );
      const steps = Math.max(20, Math.round(totalDuration / 50));
      const stepDuration = totalDuration / steps;

      // 随机贝塞尔控制点
      const p0 = 0, p3 = 1;
      const p1 = Utils.getRandomFloat(this.config.get('bezierP1Min'), this.config.get('bezierP1Max'));
      const p2 = Utils.getRandomFloat(this.config.get('bezierP2Min'), this.config.get('bezierP2Max'));

      this.logger.log(`向上滚动: ${Math.round(startY)} → ${Math.round(targetY)} (${Math.round(startY - targetY)}px, ${totalDuration}ms)`, 'action');

      let currentStep = 0;

      return new Promise((resolve) => {
        this.scrollInterval = setInterval(async () => {
          if (currentStep >= steps) {
            clearInterval(this.scrollInterval);
            this.scrollInterval = null;
            this.isScrolling = false;

            window.scrollTo(0, targetY);
            this.statusIndicator.updateStatus('idle');
            this.logger.log("向上滚动完成", 'success');

            // 随机触发行为模拟
            if (Math.random() < 0.3) {
              await this.behaviorSimulator.simulatePageInteraction();
            }

            resolve(true);
            return;
          }

          const t = currentStep / steps;
          const progress = Utils.cubicBezier(t, p0, p1, p2, p3);
          const scrollPosition = startY - (startY - targetY) * progress;

          window.scrollTo(0, scrollPosition);

          // 更新进度
          const scrollProgress = (currentStep / steps) * 100;
          this.statusIndicator.updateStatus('scrolling', scrollProgress);

          currentStep++;

          // 随机暂停
          if (Math.random() < this.config.get('randomPauseProbability')) {
            const pauseDuration = Utils.getRandomInt(
              this.config.get('randomPauseDurationMin'),
              this.config.get('randomPauseDurationMax')
            );
            await Utils.sleep(pauseDuration);
          }
        }, stepDuration);
      });
    }

    // 智能滚动决策
    async performIntelligentScroll() {
      if (this.isScrolling) return false;

      const documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
      const windowHeight = window.innerHeight;
      const currentY = window.scrollY;
      const isAtBottom = currentY + windowHeight >= documentHeight - 10;
      const isAtTop = currentY <= 10;

      let scrollSuccess = false;

      if (this.scrollDirection === 'down') {
        if (isAtBottom) {
          this.logger.log("到达底部,切换为向上滚动", 'info');
          this.scrollDirection = 'up';
          scrollSuccess = await this.scrollUpWithBezier();
        } else {
          scrollSuccess = await this.scrollWithBezier();
        }
      } else { // scrollDirection === 'up'
        if (isAtTop) {
          this.logger.log("到达顶部,切换为向下滚动", 'info');
          this.scrollDirection = 'down';
          scrollSuccess = await this.scrollWithBezier();
        } else {
          scrollSuccess = await this.scrollUpWithBezier();
        }
      }

      return scrollSuccess;
    }

    // 停止所有滚动
    stopScrolling() {
      if (this.scrollInterval) {
        clearInterval(this.scrollInterval);
        this.scrollInterval = null;
      }
      if (this.checkScrollTimeout) {
        clearTimeout(this.checkScrollTimeout);
        this.checkScrollTimeout = null;
      }
      this.isScrolling = false;
      this.statusIndicator.updateStatus('idle');
    }

    // 检查是否卡住
    isStuck() {
      const currentScrollY = window.scrollY;
      const scrollDelta = Math.abs(currentScrollY - this.lastScrollY);
      const timeSinceLastScroll = Date.now() - this.scrollStartTime;

      const isStuck = !this.isScrolling &&
                     scrollDelta < this.config.get('minScrollDelta') &&
                     timeSinceLastScroll > this.config.get('stuckTimeout');

      if (!this.isScrolling) {
        this.lastScrollY = currentScrollY;
      }

      return isStuck;
    }
  }

  // ===== 数据分析类 =====
  class DataAnalyzer {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.sessionData = {
        startTime: Date.now(),
        topicsVisited: [],
        scrollEvents: [],
        likeEvents: [],
        errorEvents: [],
        behaviorEvents: []
      };
      this.historicalData = this.loadHistoricalData();
    }

    // 加载历史数据
    loadHistoricalData() {
      try {
        const data = GM_getValue('analyticsData', null);
        const parsedData = data ? JSON.parse(data) : {};
        const defaults = {
          totalSessions: 0,
          totalTopicsRead: 0,
          totalLikesGiven: 0,
          totalReadingTime: 0,
          dailyStats: {},
          weeklyStats: {},
          monthlyStats: {},
          topicCategories: {},
          readingPatterns: [],
          efficiencyMetrics: []
        };
        return { ...defaults, ...parsedData };
      } catch (e) {
        return {
          totalSessions: 0,
          totalTopicsRead: 0,
          totalLikesGiven: 0,
          totalReadingTime: 0,
          dailyStats: {},
          weeklyStats: {},
          monthlyStats: {},
          topicCategories: {},
          readingPatterns: [],
          efficiencyMetrics: []
        };
      }
    }

    // 保存历史数据
    saveHistoricalData() {
      try {
        GM_setValue('analyticsData', JSON.stringify(this.historicalData));
      } catch (e) {
        this.logger.log('保存分析数据失败', 'error');
      }
    }

    // 记录话题访问
    recordTopicVisit(topicId, topicTitle, category, readTime) {
      const visitData = {
        topicId,
        topicTitle,
        category: category || 'unknown',
        readTime,
        timestamp: Date.now(),
        scrollCount: this.sessionData.scrollEvents.length,
        likeGiven: this.sessionData.likeEvents.some(e => e.topicId === topicId)
      };

      this.sessionData.topicsVisited.push(visitData);
      this.updateHistoricalStats(visitData);
      this.logger.log(`记录话题访问: ${topicTitle} (${Utils.formatTime(readTime)})`, 'action');
    }

    // 记录滚动事件
    recordScrollEvent(direction, distance, duration) {
      const scrollData = {
        direction,
        distance,
        duration,
        timestamp: Date.now(),
        scrollSpeed: distance / duration
      };

      this.sessionData.scrollEvents.push(scrollData);
    }

    // 记录点赞事件
    recordLikeEvent(topicId, postId) {
      const likeData = {
        topicId,
        postId,
        timestamp: Date.now()
      };

      this.sessionData.likeEvents.push(likeData);
      this.historicalData.totalLikesGiven++;
    }

    // 记录错误事件
    recordErrorEvent(errorType, errorMessage, context) {
      const errorData = {
        type: errorType,
        message: errorMessage,
        context,
        timestamp: Date.now()
      };

      this.sessionData.errorEvents.push(errorData);
    }

    // 记录行为事件
    recordBehaviorEvent(behaviorType, details) {
      const behaviorData = {
        type: behaviorType,
        details,
        timestamp: Date.now()
      };

      this.sessionData.behaviorEvents.push(behaviorData);
    }

    // 更新历史统计
    updateHistoricalStats(visitData) {
      const today = new Date().toISOString().split('T')[0];
      const thisWeek = this.getWeekKey(new Date());
      const thisMonth = new Date().toISOString().substring(0, 7);

      // 更新总计
      this.historicalData.totalTopicsRead++;
      this.historicalData.totalReadingTime += visitData.readTime;

      // 更新日统计
      if (!this.historicalData.dailyStats[today]) {
        this.historicalData.dailyStats[today] = {
          topicsRead: 0,
          readingTime: 0,
          likesGiven: 0,
          categories: {}
        };
      }
      this.historicalData.dailyStats[today].topicsRead++;
      this.historicalData.dailyStats[today].readingTime += visitData.readTime;

      // 更新周统计
      if (!this.historicalData.weeklyStats[thisWeek]) {
        this.historicalData.weeklyStats[thisWeek] = {
          topicsRead: 0,
          readingTime: 0,
          likesGiven: 0
        };
      }
      this.historicalData.weeklyStats[thisWeek].topicsRead++;
      this.historicalData.weeklyStats[thisWeek].readingTime += visitData.readTime;

      // 更新月统计
      if (!this.historicalData.monthlyStats[thisMonth]) {
        this.historicalData.monthlyStats[thisMonth] = {
          topicsRead: 0,
          readingTime: 0,
          likesGiven: 0
        };
      }
      this.historicalData.monthlyStats[thisMonth].topicsRead++;
      this.historicalData.monthlyStats[thisMonth].readingTime += visitData.readTime;

      // 更新分类统计
      if (!this.historicalData.topicCategories[visitData.category]) {
        this.historicalData.topicCategories[visitData.category] = {
          count: 0,
          totalTime: 0,
          avgTime: 0
        };
      }
      const categoryStats = this.historicalData.topicCategories[visitData.category];
      if (!categoryStats) {
        this.historicalData.topicCategories[visitData.category] = {
          count: 0,
          totalTime: 0,
          avgTime: 0
        };
      }
      categoryStats.count++;
      categoryStats.totalTime += visitData.readTime;
      categoryStats.avgTime = categoryStats.totalTime / categoryStats.count;
    }

    // 生成效率报告
    generateEfficiencyReport() {
      const sessionDuration = Date.now() - this.sessionData.startTime;
      const topicsPerHour = (this.sessionData.topicsVisited.length / (sessionDuration / 3600000)).toFixed(2);
      const avgReadTime = this.sessionData.topicsVisited.length > 0
        ? this.sessionData.topicsVisited.reduce((sum, t) => sum + t.readTime, 0) / this.sessionData.topicsVisited.length
        : 0;

      const report = {
        session: {
          duration: sessionDuration,
          topicsRead: this.sessionData.topicsVisited.length,
          topicsPerHour: parseFloat(topicsPerHour),
          avgReadTime,
          scrollEvents: this.sessionData.scrollEvents.length,
          likeEvents: this.sessionData.likeEvents.length,
          errorEvents: this.sessionData.errorEvents.length
        },
        historical: {
          totalSessions: this.historicalData.totalSessions,
          totalTopicsRead: this.historicalData.totalTopicsRead,
          totalReadingTime: this.historicalData.totalReadingTime,
          avgTopicsPerSession: this.historicalData.totalSessions > 0
            ? (this.historicalData.totalTopicsRead / this.historicalData.totalSessions).toFixed(2)
            : 0
        },
        trends: this.analyzeTrends(),
        recommendations: this.generateRecommendations()
      };

      return report;
    }

    // 分析趋势
    analyzeTrends() {
      const recentDays = Object.keys(this.historicalData.dailyStats)
        .sort()
        .slice(-7);

      if (recentDays.length < 2) return null;

      const firstDay = this.historicalData.dailyStats[recentDays[0]];
      const lastDay = this.historicalData.dailyStats[recentDays[recentDays.length - 1]];

      return {
        topicsReadTrend: lastDay.topicsRead - firstDay.topicsRead,
        readingTimeTrend: lastDay.readingTime - firstDay.readingTime,
        period: `${recentDays[0]} 到 ${recentDays[recentDays.length - 1]}`
      };
    }

    // 生成建议
    generateRecommendations() {
      const recommendations = [];
      const avgReadTime = this.sessionData.topicsVisited.length > 0
        ? this.sessionData.topicsVisited.reduce((sum, t) => sum + t.readTime, 0) / this.sessionData.topicsVisited.length
        : 0;

      if (avgReadTime < 30000) {
        recommendations.push('建议增加每个话题的阅读时间,提高内容理解度');
      }

      if (this.sessionData.errorEvents.length > 5) {
        recommendations.push('检测到较多错误,建议检查网络连接或调整配置');
      }

      const scrollToReadRatio = this.sessionData.scrollEvents.length / Math.max(this.sessionData.topicsVisited.length, 1);
      if (scrollToReadRatio > 20) {
        recommendations.push('滚动频率较高,建议调整滚动参数以提高效率');
      }

      return recommendations;
    }

    // 获取周键
    getWeekKey(date) {
      const year = date.getFullYear();
      const week = this.getWeekNumber(date);
      return `${year}-W${week.toString().padStart(2, '0')}`;
    }

    // 获取周数
    getWeekNumber(date) {
      const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
      const dayNum = d.getUTCDay() || 7;
      d.setUTCDate(d.getUTCDate() + 4 - dayNum);
      const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
      return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
    }

    // 结束会话
    endSession() {
      this.historicalData.totalSessions++;
      this.saveHistoricalData();

      const report = this.generateEfficiencyReport();
      this.logger.log(`会话结束 - 阅读 ${report.session.topicsRead} 个话题,用时 ${Utils.formatTime(report.session.duration)}`, 'success');

      return report;
    }

    // 导出分析数据
    exportAnalyticsData() {
      const exportData = {
        sessionData: this.sessionData,
        historicalData: this.historicalData,
        report: this.generateEfficiencyReport(),
        exportTime: new Date().toISOString()
      };

      const blob = new Blob([JSON.stringify(exportData, null, 2)], {
        type: 'application/json'
      });

      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `forum-assistant-analytics-${new Date().toISOString().split('T')[0]}.json`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      this.logger.log('分析数据已导出', 'success');
    }
  }

  // ===== 安全和隐私增强类 =====
  class SecurityManager {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15'
      ];
      this.proxyList = [];
      this.currentFingerprint = this.generateFingerprint();
    }

    // 生成随机指纹
    generateFingerprint() {
      return {
        userAgent: this.getRandomUserAgent(),
        language: this.getRandomLanguage(),
        timezone: this.getRandomTimezone(),
        screen: this.getRandomScreen(),
        colorDepth: this.getRandomColorDepth(),
        platform: this.getRandomPlatform()
      };
    }

    // 获取随机User-Agent
    getRandomUserAgent() {
      return this.userAgents[Math.floor(Math.random() * this.userAgents.length)];
    }

    // 获取随机语言
    getRandomLanguage() {
      const languages = ['zh-CN', 'zh-TW', 'en-US', 'en-GB', 'ja-JP', 'ko-KR'];
      return languages[Math.floor(Math.random() * languages.length)];
    }

    // 获取随机时区
    getRandomTimezone() {
      const timezones = [
        'Asia/Shanghai', 'Asia/Hong_Kong', 'Asia/Taipei',
        'Asia/Tokyo', 'Asia/Seoul', 'America/New_York',
        'Europe/London', 'Australia/Sydney'
      ];
      return timezones[Math.floor(Math.random() * timezones.length)];
    }

    // 获取随机屏幕分辨率
    getRandomScreen() {
      const screens = [
        { width: 1920, height: 1080 },
        { width: 1366, height: 768 },
        { width: 1440, height: 900 },
        { width: 1536, height: 864 },
        { width: 2560, height: 1440 }
      ];
      return screens[Math.floor(Math.random() * screens.length)];
    }

    // 获取随机颜色深度
    getRandomColorDepth() {
      const depths = [24, 32];
      return depths[Math.floor(Math.random() * depths.length)];
    }

    // 获取随机平台
    getRandomPlatform() {
      const platforms = ['Win32', 'MacIntel', 'Linux x86_64'];
      return platforms[Math.floor(Math.random() * platforms.length)];
    }

    // 随机化请求头
    randomizeHeaders(baseHeaders = {}) {
      const randomHeaders = {
        'User-Agent': this.currentFingerprint.userAgent,
        'Accept-Language': `${this.currentFingerprint.language},en;q=0.9`,
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'DNT': Math.random() > 0.5 ? '1' : '0',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'none',
        'Cache-Control': Math.random() > 0.5 ? 'no-cache' : 'max-age=0'
      };

      // 随机添加一些可选头
      if (Math.random() > 0.7) {
        randomHeaders['Sec-CH-UA'] = this.generateSecChUa();
      }

      if (Math.random() > 0.8) {
        randomHeaders['Sec-CH-UA-Mobile'] = '?0';
        randomHeaders['Sec-CH-UA-Platform'] = `"${this.currentFingerprint.platform}"`;
      }

      return { ...randomHeaders, ...baseHeaders };
    }

    // 生成Sec-CH-UA头
    generateSecChUa() {
      const brands = [
        '"Google Chrome";v="120", "Chromium";v="120", "Not_A Brand";v="99"',
        '"Google Chrome";v="119", "Chromium";v="119", "Not_A Brand";v="99"',
        '"Microsoft Edge";v="120", "Chromium";v="120", "Not_A Brand";v="99"'
      ];
      return brands[Math.floor(Math.random() * brands.length)];
    }

    // 增强的fetch请求
    async secureRequest(url, options = {}) {
      if (!this.config.get('enableSafetyFeatures')) {
        return fetch(url, options);
      }

      // 随机延迟
      const delay = Utils.getRandomInt(100, 500);
      await Utils.sleep(delay);

      // 随机化请求头
      const secureHeaders = this.randomizeHeaders(options.headers || {});

      const secureOptions = {
        ...options,
        headers: secureHeaders
      };

      // 如果启用代理
      if (this.config.get('proxyEnabled') && this.proxyList.length > 0) {
        // 这里可以添加代理逻辑
        this.logger.log('使用代理发送请求', 'action');
      }

      try {
        const response = await fetch(url, secureOptions);

        // 记录请求
        this.logger.log(`安全请求: ${url.substring(0, 50)}...`, 'action');

        return response;
      } catch (error) {
        this.logger.log(`安全请求失败: ${error.message}`, 'error');
        throw error;
      }
    }

    // 行为指纹混淆
    obfuscateBehavior() {
      if (!this.config.get('enableSafetyFeatures')) return;

      // 随机改变指纹
      if (Math.random() < 0.1) {
        this.currentFingerprint = this.generateFingerprint();
        this.logger.log('更新行为指纹', 'action');
      }

      // 随机添加噪声事件
      this.addNoiseEvents();
    }

    // 添加噪声事件
    addNoiseEvents() {
      const noiseEvents = [
        () => this.simulateRandomClick(),
        () => this.simulateRandomKeyPress(),
        () => this.simulateRandomMouseMove(),
        () => this.simulateRandomScroll()
      ];

      // 随机执行1-2个噪声事件
      const eventCount = Utils.getRandomInt(1, 2);
      for (let i = 0; i < eventCount; i++) {
        const randomEvent = noiseEvents[Math.floor(Math.random() * noiseEvents.length)];
        setTimeout(randomEvent, Utils.getRandomInt(100, 1000));
      }
    }

    // 模拟随机点击
    simulateRandomClick() {
      const x = Math.random() * window.innerWidth;
      const y = Math.random() * window.innerHeight;

      const clickEvent = new MouseEvent('click', {
        clientX: x,
        clientY: y,
        bubbles: false // 不冒泡,避免触发实际功能
      });

      // 创建一个不可见的元素来接收点击
      const dummyElement = document.createElement('div');
      dummyElement.style.position = 'absolute';
      dummyElement.style.left = x + 'px';
      dummyElement.style.top = y + 'px';
      dummyElement.style.width = '1px';
      dummyElement.style.height = '1px';
      dummyElement.style.opacity = '0';
      dummyElement.style.pointerEvents = 'none';

      document.body.appendChild(dummyElement);
      dummyElement.dispatchEvent(clickEvent);

      setTimeout(() => {
        document.body.removeChild(dummyElement);
      }, 100);
    }

    // 模拟随机按键
    simulateRandomKeyPress() {
      const keys = ['Tab', 'Shift', 'Control', 'Alt'];
      const randomKey = keys[Math.floor(Math.random() * keys.length)];

      const keyEvent = new KeyboardEvent('keydown', {
        key: randomKey,
        bubbles: false
      });

      document.dispatchEvent(keyEvent);
    }

    // 模拟随机鼠标移动
    simulateRandomMouseMove() {
      const x = Math.random() * window.innerWidth;
      const y = Math.random() * window.innerHeight;

      const moveEvent = new MouseEvent('mousemove', {
        clientX: x,
        clientY: y,
        bubbles: false
      });

      document.dispatchEvent(moveEvent);
    }

    // 模拟随机滚动
    simulateRandomScroll() {
      const scrollEvent = new WheelEvent('wheel', {
        deltaY: Utils.getRandomInt(-100, 100),
        bubbles: false
      });

      document.dispatchEvent(scrollEvent);
    }

    // 检测反爬虫机制
    detectAntiBot() {
      const indicators = [];

      // 检测常见的反爬虫脚本
      if (window.navigator.webdriver) {
        indicators.push('webdriver detected');
      }

      if (window.chrome && window.chrome.runtime && window.chrome.runtime.onConnect) {
        // 可能是自动化浏览器
        indicators.push('automation detected');
      }

      // 检测异常的性能指标
      if (performance.timing) {
        const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
        if (loadTime < 100) {
          indicators.push('suspicious load time');
        }
      }

      if (indicators.length > 0) {
        this.logger.log(`检测到反爬虫指标: ${indicators.join(', ')}`, 'warn');
        return true;
      }

      return false;
    }

    // 启动安全监控
    startSecurityMonitoring() {
      if (!this.config.get('enableSafetyFeatures')) return;

      // 定期检测反爬虫
      setInterval(() => {
        if (this.detectAntiBot()) {
          this.obfuscateBehavior();
        }
      }, 30000);

      // 定期混淆行为
      setInterval(() => {
        this.obfuscateBehavior();
      }, Utils.getRandomInt(60000, 120000));

      this.logger.log('安全监控已启动', 'success');
    }

    // 清理痕迹
    cleanupTraces() {
      try {
        // 清理localStorage中的敏感数据
        const sensitiveKeys = ['topicList', 'latestPage', 'clickCounter'];
        sensitiveKeys.forEach(key => {
          if (Math.random() < 0.1) { // 10%概率清理
            localStorage.removeItem(key);
          }
        });

        // 清理sessionStorage
        if (Math.random() < 0.05) { // 5%概率清理
          sessionStorage.clear();
        }

        this.logger.log('执行痕迹清理', 'action');
      } catch (e) {
        // 忽略清理错误
      }
    }
  }

  // ===== 多站点适配器类 =====
  class SiteAdapter {
    constructor(config, logger) {
      this.config = config;
      this.logger = logger;
      this.currentSite = this.detectSite();
      this.siteConfigs = this.initializeSiteConfigs();
    }

    // 检测当前站点
    detectSite() {
      const url = window.location.href;
      const hostname = window.location.hostname;

      const siteMap = {
        'linux.do': 'linuxdo',
        'meta.discourse.org': 'discourse-meta',
        'meta.appinn.net': 'appinn',
        'community.openai.com': 'openai',
        'nodeloc.cc': 'nodeloc',
        'bbs.tampermonkey.net.cn': 'tampermonkey',
        'greasyfork.org': 'greasyfork'
      };

      for (const [domain, siteId] of Object.entries(siteMap)) {
        if (hostname.includes(domain)) {
          this.logger.log(`检测到站点: ${siteId}`, 'info');
          return siteId;
        }
      }

      // 尝试检测Discourse论坛
      if (this.isDiscourse()) {
        this.logger.log('检测到Discourse论坛', 'info');
        return 'discourse-generic';
      }

      this.logger.log('未知站点类型', 'warn');
      return 'unknown';
    }

    // 检测是否为Discourse论坛
    isDiscourse() {
      return !!(
        document.querySelector('meta[name="discourse_theme_ids"]') ||
        document.querySelector('meta[name="discourse_current_homepage"]') ||
        document.querySelector('#discourse-modal') ||
        window.Discourse ||
        document.body.classList.contains('discourse')
      );
    }

    // 初始化站点配置
    initializeSiteConfigs() {
      return {
        'linuxdo': {
          name: 'Linux.do',
          type: 'discourse',
          apiEndpoint: '/latest.json',
          topicUrlPattern: '/t/topic/{id}/{post}',
          selectors: {
            likeButton: '.discourse-reactions-reaction-button:not(.my-reaction)',
            topicTitle: '.fancy-title',
            postContent: '.cooked',
            userAvatar: '.avatar',
            replyButton: '.reply'
          },
          features: {
            reactions: true,
            categories: true,
            tags: true,
            privateMessages: true
          },
          limits: {
            maxComments: 1000,
            maxLikes: 50,
            readTimeMin: 45000,
            readTimeMax: 120000
          }
        },

        'nodeloc': {
          name: 'NodeLoc',
          type: 'discourse',
          apiEndpoint: '/latest.json',
          topicUrlPattern: '/t/topic/{id}/{post}',
          selectors: {
            likeButton: '.discourse-reactions-reaction-button:not(.my-reaction)',
            topicTitle: '.fancy-title',
            postContent: '.cooked'
          },
          features: {
            reactions: true,
            categories: true
          },
          limits: {
            maxComments: 800,
            maxLikes: 40,
            readTimeMin: 30000,
            readTimeMax: 90000
          }
        },

        'discourse-meta': {
          name: 'Discourse Meta',
          type: 'discourse',
          apiEndpoint: '/latest.json',
          topicUrlPattern: '/t/{slug}/{id}/{post}',
          selectors: {
            likeButton: '.like-button:not(.has-like)',
            topicTitle: '.fancy-title',
            postContent: '.cooked'
          },
          features: {
            likes: true,
            categories: true,
            tags: true
          },
          limits: {
            maxComments: 1500,
            maxLikes: 60,
            readTimeMin: 60000,
            readTimeMax: 150000
          }
        },

        'greasyfork': {
          name: 'Greasy Fork',
          type: 'custom',
          apiEndpoint: null,
          selectors: {
            scriptLink: 'a[href*="/scripts/"]',
            scriptTitle: '.script-name',
            scriptDescription: '.script-description'
          },
          features: {
            scripts: true,
            reviews: true
          },
          limits: {
            maxScripts: 100,
            readTimeMin: 20000,
            readTimeMax: 60000
          }
        },

        'unknown': {
          name: 'Unknown Site',
          type: 'generic',
          apiEndpoint: null,
          selectors: {
            likeButton: '.like, .upvote, [data-action="like"]',
            content: 'article, .post, .content'
          },
          features: {},
          limits: {
            maxComments: 500,
            maxLikes: 20,
            readTimeMin: 30000,
            readTimeMax: 90000
          }
        }
      };
    }

    // 获取当前站点配置
    getSiteConfig() {
      return this.siteConfigs[this.currentSite] || this.siteConfigs['unknown'];
    }

    // 获取API端点
    getApiEndpoint(endpoint) {
      const siteConfig = this.getSiteConfig();
      const baseUrl = `${window.location.protocol}//${window.location.hostname}`;

      switch (endpoint) {
        case 'latest':
          return siteConfig.apiEndpoint ? `${baseUrl}${siteConfig.apiEndpoint}` : null;
        case 'topics':
          return `${baseUrl}/topics.json`;
        case 'categories':
          return `${baseUrl}/categories.json`;
        default:
          return null;
      }
    }

    // 构建话题URL
    buildTopicUrl(topicId, postNumber = 1) {
      const siteConfig = this.getSiteConfig();
      const baseUrl = `${window.location.protocol}//${window.location.hostname}`;

      if (siteConfig.topicUrlPattern) {
        return `${baseUrl}${siteConfig.topicUrlPattern
          .replace('{id}', topicId)
          .replace('{post}', postNumber)
          .replace('{slug}', 'topic')}`;
      }

      return `${baseUrl}/t/${topicId}`;
    }

    // 获取选择器
    getSelector(type) {
      const siteConfig = this.getSiteConfig();
      return siteConfig.selectors[type] || null;
    }

    // 检查功能支持
    hasFeature(feature) {
      const siteConfig = this.getSiteConfig();
      return siteConfig.features[feature] || false;
    }

    // 获取限制配置
    getLimit(type) {
      const siteConfig = this.getSiteConfig();
      return siteConfig.limits[type] || 0;
    }

    // 站点特定的话题获取
    async fetchTopics(page = 0) {
      const apiUrl = this.getApiEndpoint('latest');
      if (!apiUrl) {
        this.logger.log('当前站点不支持API获取话题', 'warn');
        return [];
      }

      try {
        const url = `${apiUrl}?no_definitions=true&page=${page}`;
        const response = await fetch(url);

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }

        const data = await response.json();
        const topics = data?.topic_list?.topics || [];

        // 站点特定的过滤逻辑
        return this.filterTopics(topics);

      } catch (error) {
        this.logger.log(`获取话题失败: ${error.message}`, 'error');
        return [];
      }
    }

    // 过滤话题
    filterTopics(topics) {
      const maxComments = this.getLimit('maxComments');

      return topics.filter(topic => {
        if (!topic || !topic.id) return false;
        if (topic.posts_count > maxComments) return false;
        if (topic.closed || topic.archived) return false;

        // 站点特定过滤
        switch (this.currentSite) {
          case 'linuxdo':
            // 过滤掉某些分类
            if (topic.category_id && [1, 2].includes(topic.category_id)) return false;
            break;
          case 'nodeloc':
            // 只保留特定分类
            if (topic.category_id && ![5, 6, 7].includes(topic.category_id)) return false;
            break;
        }

        return true;
      });
    }

    // 站点特定的点赞逻辑
    async performLike(element) {
      const siteConfig = this.getSiteConfig();

      if (!this.hasFeature('reactions') && !this.hasFeature('likes')) {
        return false;
      }

      try {
        // 检查元素是否可点击
        if (element.classList.contains('my-reaction') ||
            element.classList.contains('has-like') ||
            element.disabled) {
          return false;
        }

        // 模拟点击
        const event = new MouseEvent('click', {
          bubbles: true,
          cancelable: true
        });

        element.dispatchEvent(event);

        // 等待响应
        await Utils.sleep(Utils.getRandomInt(500, 1500));

        return true;

      } catch (error) {
        this.logger.log(`点赞失败: ${error.message}`, 'error');
        return false;
      }
    }

    // 获取页面信息
    getPageInfo() {
      const siteConfig = this.getSiteConfig();

      return {
        site: this.currentSite,
        siteName: siteConfig.name,
        type: siteConfig.type,
        url: window.location.href,
        title: document.title,
        isTopicPage: this.isTopicPage(),
        topicId: this.extractTopicId(),
        hasLikeButtons: this.hasLikeButtons()
      };
    }

    // 检查是否为话题页面
    isTopicPage() {
      const patterns = [
        /\/t\/[^/]+\/\d+/,  // Discourse pattern
        /\/topic\/\d+/,     // Generic topic pattern
        /\/thread\/\d+/,    // Forum thread pattern
        /\/scripts\/\d+/    // Greasyfork script pattern
      ];

      return patterns.some(pattern => pattern.test(window.location.pathname));
    }

    // 提取话题ID
    extractTopicId() {
      const path = window.location.pathname;
      const matches = path.match(/\/(?:t|topic|thread|scripts)\/(?:[^/]+\/)?(\d+)/);
      return matches ? parseInt(matches[1]) : null;
    }

    // 检查是否有点赞按钮
    hasLikeButtons() {
      const selector = this.getSelector('likeButton');
      return selector ? document.querySelectorAll(selector).length > 0 : false;
    }
  }

  // ===== 主程序类 =====
  class ForumAssistant {
    constructor() {
      this.config = new ConfigManager();
      this.logger = new LogManager(this.config);
      this.statusIndicator = new StatusIndicator(this.config, this.logger);
      this.behaviorSimulator = new BehaviorSimulator(this.config, this.logger, this.statusIndicator);
      this.scrollSystem = new EnhancedScrollSystem(this.config, this.logger, this.statusIndicator, this.behaviorSimulator);
      this.dataAnalyzer = new DataAnalyzer(this.config, this.logger);
      this.securityManager = new SecurityManager(this.config, this.logger);
      this.siteAdapter = new SiteAdapter(this.config, this.logger);
      this.automationEngine = new AutomationEngine(this.config, this.logger, this.siteAdapter);

      // UI组件
      this.statsPanel = new StatisticsPanel(this.config, this.logger);
      this.configPanel = new ConfigPanel(this.config, this.logger);
      this.upgradePanel = new UpgradeProgressPanel(this.config, this.logger);
      this.controlPanel = new ControlPanel(this.config, this.logger, this.statsPanel, this.configPanel, this.upgradePanel);

      // 状态变量
      this.isRunning = false;
      this.currentTopic = null;
      this.topicStartTime = Date.now();
      this.requiredReadTime = 0;
      this.mainLoop = null;
      this.stuckCheckInterval = null;

      this.initialize();
    }

    // 初始化
    async initialize() {
      try {
        this.logger.log('智能论坛助手 Pro 初始化中...', 'info');

        // 等待DOM完全准备好
        await this.waitForDOM();

        // 创建UI (使用延迟确保DOM稳定)
        setTimeout(() => {
          try {
            this.logger.createLogWindow();
            this.statusIndicator.create();
            this.controlPanel.create();

            if (this.config.get('showStatistics')) {
              this.statsPanel.show();
            }

            // 恢复升级进度窗口状态
            const upgradeProgressVisible = GM_getValue('upgradeProgressVisible', false);
            if (upgradeProgressVisible) {
              this.upgradePanel.show();
            }
          } catch (uiError) {
            console.error('UI创建失败:', uiError);
            this.logger.log(`UI创建失败: ${uiError.message}`, 'error');
          }
        }, 500);

        // 启动安全监控
        this.securityManager.startSecurityMonitoring();

      // 启动弹窗监控
      this.startPopupMonitoring();

      // 启动网络请求监控
      this.startNetworkMonitoring();

        // 检查站点兼容性
        const pageInfo = this.siteAdapter.getPageInfo();
        this.logger.log(`当前站点: ${pageInfo.siteName} (${pageInfo.type})`, 'info');

        // 恢复运行状态
        const wasRunning = GM_getValue('isReading', false);
        if (wasRunning) {
          await Utils.sleep(2000); // 等待页面完全加载
          this.start();
        }

        this.logger.log('初始化完成', 'success');

        this.setupNavigationListener();

      } catch (error) {
        console.error('初始化错误:', error);
        this.logger.log(`初始化失败: ${error.message}`, 'error');
      }
    }

    // 设置导航监听器
    setupNavigationListener() {
        this.lastUrl = window.location.href;

        const observer = new MutationObserver(() => {
            const currentUrl = window.location.href;
            if (currentUrl !== this.lastUrl) {
                this.handleUrlChange(currentUrl);
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        window.addEventListener('popstate', () => {
            this.handleUrlChange(window.location.href);
        });

        this.logger.log('导航监听器已设置', 'info');
    }

    // 处理URL变化
    handleUrlChange(newUrl) {
        const newPath = new URL(newUrl).pathname;
        const oldPath = new URL(this.lastUrl).pathname;

        // 只有当pathname的主体部分发生变化时,才认为是真正的导航
        const newPathBase = newPath.split('/').slice(0, 3).join('/');
        const oldPathBase = oldPath.split('/').slice(0, 3).join('/');

        if (newPathBase !== oldPathBase) {
            this.logger.log(`URL 路径发生变化: ${newPath}`, 'info');
            this.lastUrl = newUrl;

            // 停止当前的活动
            if (this.isRunning) {
                this.stop();
            }

            // 延迟后重新启动,以确保页面内容已加载
            setTimeout(() => {
                const pageInfo = this.siteAdapter.getPageInfo();
                if (pageInfo.isTopicPage) {
                    this.start();
                } else {
                    this.navigateToNextTopic();
                }
            }, 2000);
        }
    }

    // 等待DOM准备就绪
    async waitForDOM() {
      return new Promise((resolve) => {
        if (document.body && document.head) {
          resolve();
          return;
        }

        const observer = new MutationObserver(() => {
          if (document.body && document.head) {
            observer.disconnect();
            resolve();
          }
        });

        observer.observe(document.documentElement, {
          childList: true,
          subtree: true
        });

        // 超时保护
        setTimeout(() => {
          observer.disconnect();
          resolve();
        }, 5000);
      });
    }

    // 开始运行
    async start() {
      if (this.isRunning) return;

      this.isRunning = true;
      GM_setValue('isReading', true);

      // 安全更新控制面板状态
      try {
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }
      } catch (e) {
        console.error('更新按钮状态失败:', e);
      }

      this.logger.log('开始自动阅读', 'success');
      this.statusIndicator.updateStatus('loading');

      // 启动行为模拟
      if (this.config.get('enableAdvancedBehavior')) {
        this.behaviorSimulator.start();
      }

      // 启动自动化引擎
      if (this.config.get('autoReplyEnabled') || this.config.get('keywordMonitoring')) {
        this.automationEngine.start();
      }

      // 开始主循环
      this.startMainLoop();

      // 启动卡住检测
      this.startStuckDetection();

      // 如果不在话题页面,导航到话题
      const pageInfo = this.siteAdapter.getPageInfo();
      if (!pageInfo.isTopicPage) {
        await this.navigateToNextTopic();
      } else {
        this.startTopicReading();
      }
    }

    // 停止运行
    stop() {
      if (!this.isRunning) return;

      this.isRunning = false;
      GM_setValue('isReading', false);

      // 安全更新控制面板状态
      try {
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }
      } catch (e) {
        console.error('更新按钮状态失败:', e);
      }

      this.logger.log('停止自动阅读', 'action');
      this.statusIndicator.updateStatus('idle');

      // 停止所有组件
      this.scrollSystem.stopScrolling();
      this.behaviorSimulator.stop();
      this.automationEngine.stop();

      // 清理定时器
      if (this.mainLoop) {
        clearTimeout(this.mainLoop);
        this.mainLoop = null;
      }

      if (this.stuckCheckInterval) {
        clearInterval(this.stuckCheckInterval);
        this.stuckCheckInterval = null;
      }

      // 结束会话分析
      try {
        const report = this.dataAnalyzer.endSession();
        this.logger.log(`会话报告: 阅读${report.session.topicsRead}个话题`, 'info');
      } catch (e) {
        console.error('生成会话报告失败:', e);
      }
    }

    // 开始主循环
    startMainLoop() {
      const checkInterval = 3000; // 3秒检查一次

      const mainCheck = async () => {
        if (!this.isRunning) return;

        try {
          await this.performMainCheck();
        } catch (error) {
          this.logger.log(`主循环错误: ${error.message}`, 'error');
          this.dataAnalyzer.recordErrorEvent('main_loop', error.message, 'main_check');
        }

        // 安排下次检查
        this.mainLoop = setTimeout(mainCheck, checkInterval);
      };

      mainCheck();
    }

    // 执行主要检查
    async performMainCheck() {
      const now = Date.now();
      const readDuration = now - this.topicStartTime;
      const maxIdleTime = Math.max(this.config.get('maxIdleTime'), this.requiredReadTime);

      // 检查是否需要切换话题
      if (this.shouldSwitchTopic(readDuration, maxIdleTime)) {
        await this.navigateToNextTopic();
        return;
      }

      // 执行滚动
      if (!this.scrollSystem.isScrolling) {
        const scrollSuccess = await this.scrollSystem.performIntelligentScroll();
        if (scrollSuccess) {
          this.dataAnalyzer.recordScrollEvent(
            this.scrollSystem.scrollDirection,
            this.config.get('scrollSegmentDistanceMin'),
            this.config.get('scrollSegmentDurationMin')
          );
        }
      }

      // 执行点赞
      if (GM_getValue('autoLikeEnabled', false)) {
        await this.performAutoLike();
      }

      // 安全混淆
      if (Math.random() < 0.1) {
        this.securityManager.obfuscateBehavior();
      }
    }

    // 判断是否应该切换话题
    shouldSwitchTopic(readDuration, maxIdleTime) {
      const documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
      const windowHeight = window.innerHeight;
      const currentY = window.scrollY;
      const isAtBottom = currentY + windowHeight >= documentHeight - 10;
      const isAtTop = currentY <= 10;

      // 超时切换
      if (readDuration > maxIdleTime) {
        this.logger.log(`阅读超时 (${Utils.formatTime(readDuration)}),切换话题`, 'info');
        return true;
      }

      // 达到最小阅读时间且在页面边界
      if (readDuration >= this.requiredReadTime && (isAtBottom || isAtTop)) {
        this.logger.log(`阅读完成 (${Utils.formatTime(readDuration)}),切换话题`, 'info');
        return true;
      }

      return false;
    }

    // 导航到下一个话题
    async navigateToNextTopic() {
      this.statusIndicator.updateStatus('switching');

      try {
        // 记录当前话题的阅读数据
        if (this.currentTopic) {
          const readTime = Date.now() - this.topicStartTime;
          this.dataAnalyzer.recordTopicVisit(
            this.currentTopic.id,
            this.currentTopic.title || document.title,
            this.currentTopic.category,
            readTime
          );
          this.logger.updateStatistics('topicsRead');
        }

        // 获取下一个话题
        const nextTopic = await this.getNextTopic();
        if (!nextTopic) {
          this.logger.log('没有更多话题,停止运行', 'warn');
          this.stop();
          return;
        }

        // 随机延迟
        const delay = Utils.getRandomInt(
          this.config.get('minTopicChangeDelay'),
          this.config.get('maxTopicChangeDelay')
        );

        this.logger.log(`等待 ${Utils.formatTime(delay)} 后切换到话题: ${nextTopic.title || nextTopic.id}`, 'info');
        await Utils.sleep(delay);

        // 导航到新话题
        const topicUrl = this.siteAdapter.buildTopicUrl(nextTopic.id, nextTopic.last_read_post_number || 1);

        // 在当前标签页中导航
        window.location.href = topicUrl;

      } catch (error) {
        this.logger.log(`话题切换失败: ${error.message}`, 'error');
        this.dataAnalyzer.recordErrorEvent('topic_switch', error.message, 'navigation');

        // 重试
        setTimeout(() => this.navigateToNextTopic(), 10000);
      }
    }

    // 开始话题阅读
    startTopicReading() {
      const pageInfo = this.siteAdapter.getPageInfo();
      this.currentTopic = {
        id: pageInfo.topicId,
        title: pageInfo.title,
        url: pageInfo.url
      };

      this.topicStartTime = Date.now();
      this.requiredReadTime = Utils.getRandomInt(
        this.config.get('minReadTimeLower'),
        this.config.get('minReadTimeUpper')
      );

      this.scrollSystem.scrollDirection = 'down';
      this.statusIndicator.updateStatus('reading');

      this.logger.log(`开始阅读话题: ${this.currentTopic.title} (需要 ${Utils.formatTime(this.requiredReadTime)})`, 'info');
    }

    // 获取下一个话题
    async getNextTopic() {
      // 尝试从缓存获取
      let topicList = GM_getValue('topicList', '[]');
      try {
        topicList = JSON.parse(topicList);
      } catch (e) {
        topicList = [];
      }

      if (topicList.length === 0) {
        // 获取新话题
        this.logger.log('话题列表为空,获取新话题...', 'info');
        const newTopics = await this.fetchTopics();
        if (newTopics.length === 0) {
          return null;
        }
        topicList = newTopics;
        GM_setValue('topicList', JSON.stringify(topicList));
      }

      // 返回第一个话题并从列表中移除
      const nextTopic = topicList.shift();
      GM_setValue('topicList', JSON.stringify(topicList));

      return nextTopic;
    }

    // 获取话题列表
    async fetchTopics() {
      const topics = [];
      const maxRetries = 3;
      let page = GM_getValue('latestPage', 0);

      for (let retry = 0; retry < maxRetries; retry++) {
        try {
          page++;
          const pageTopics = await this.siteAdapter.fetchTopics(page);

          if (pageTopics.length > 0) {
            topics.push(...pageTopics);
            GM_setValue('latestPage', page);

            if (topics.length >= this.config.get('topicListLimit')) {
              break;
            }
          } else {
            // 没有更多话题,重置页码
            GM_setValue('latestPage', 0);
            break;
          }
        } catch (error) {
          this.logger.log(`获取话题失败 (页面 ${page}): ${error.message}`, 'error');
          await Utils.sleep(1000);
        }
      }

      this.logger.log(`获取到 ${topics.length} 个话题`, 'success');
      return topics.slice(0, this.config.get('topicListLimit'));
    }

    // 检测是否有弹窗出现
    checkForPopups() {
      // 需要忽略的弹窗类型(信息性弹窗,不应停止点赞)
      const ignoredPopupSelectors = [
        '.user-card',           // 用户信息卡片
        '.user-tooltip',        // 用户提示框
        '.topic-entrance',      // 话题入口
        '.quote-button',        // 引用按钮
        '.post-menu',          // 帖子菜单
        '.dropdown-menu',      // 下拉菜单
        '.autocomplete',       // 自动完成
        '.suggestion-menu',    // 建议菜单
        '.emoji-picker',       // 表情选择器
        '.preview-popup'       // 预览弹窗
      ];

      // 需要检测的弹窗选择器(会阻止操作的弹窗)
      const criticalPopupSelectors = [
        '.modal', '.popup', '.dialog', '.overlay',
        '.alert', '.notification', '.toast',
        '[role="dialog"]', '[role="alertdialog"]',
        '.swal2-container', '.sweetalert2-container',
        '.layui-layer', '.layer-shade',
        '.ant-modal', '.el-dialog',
        '.v-dialog', '.q-dialog',
        // NodeLoc 特定的重要弹窗
        '.fancybox-container', '.fancybox-overlay',
        '.ui-dialog', '.ui-widget-overlay',
        '.bootbox', '.confirm-dialog',
        '.error-dialog', '.warning-dialog'
      ];

      // 首先检查是否是应该忽略的弹窗
      for (const selector of ignoredPopupSelectors) {
        const popup = document.querySelector(selector);
        if (popup && this.isElementVisible(popup)) {
          // 这是信息性弹窗,不需要停止点赞
          return null;
        }
      }

      // 检查关键弹窗
      for (const selector of criticalPopupSelectors) {
        const popup = document.querySelector(selector);
        if (popup && this.isElementVisible(popup)) {
          return popup;
        }
      }

      // 检查是否有遮罩层(但排除用户卡片相关的)
      const overlays = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]');
      for (const overlay of overlays) {
        // 跳过用户卡片相关的遮罩
        if (overlay.id === 'user-card' ||
            overlay.classList.contains('user-card') ||
            overlay.closest('.user-card')) {
          continue;
        }

        const style = getComputedStyle(overlay);
        if (style.zIndex > 1000 &&
            (style.backgroundColor !== 'rgba(0, 0, 0, 0)' ||
             style.background !== 'none')) {
          return overlay;
        }
      }

      return null;
    }

    // 检查元素是否可见
    isElementVisible(element) {
      if (!element) return false;

      const style = getComputedStyle(element);
      return element.style.display !== 'none' &&
             style.display !== 'none' &&
             style.visibility !== 'hidden' &&
             style.opacity !== '0';
    }

    // 启动弹窗监控
    startPopupMonitoring() {
      // 使用 MutationObserver 监控 DOM 变化
      const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          mutation.addedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) {
              this.checkNewElementForPopup(node);
            }
          });
        });
      });

      observer.observe(document.body, {
        childList: true,
        subtree: true
      });

      // 定期检查弹窗
      setInterval(() => {
        this.performPopupCheck();
      }, 3000); // 每3秒检查一次

      this.logger.log('弹窗监控已启动', 'info');
    }

    // 检查新元素是否为弹窗
    checkNewElementForPopup(element) {
      const popupClasses = [
        'modal', 'popup', 'dialog', 'overlay', 'alert', 'notification', 'toast',
        'swal2-container', 'sweetalert2-container', 'layui-layer', 'layer-shade',
        'ant-modal', 'el-dialog', 'v-dialog', 'q-dialog',
        'fancybox-container', 'fancybox-overlay', 'ui-dialog', 'ui-widget-overlay'
      ];

      const hasPopupClass = popupClasses.some(className =>
        element.classList && element.classList.contains(className)
      );

      const hasPopupRole = element.getAttribute &&
        (element.getAttribute('role') === 'dialog' ||
         element.getAttribute('role') === 'alertdialog');

      if (hasPopupClass || hasPopupRole) {
        setTimeout(() => {
          this.handlePopupDetected(element);
        }, 500); // 延迟500ms确保弹窗完全显示
      }
    }

    // 定期执行弹窗检查
    performPopupCheck() {
      const popup = this.checkForPopups();
      if (popup) {
        this.handlePopupDetected(popup);
      }
    }

    // 处理检测到的弹窗
    handlePopupDetected(popup) {
      const isLikeEnabled = GM_getValue('autoLikeEnabled', false);

      if (isLikeEnabled) {
        this.logger.log('🚨 检测到弹窗,自动停止点赞功能', 'warning');
        GM_setValue('autoLikeEnabled', false);

        // 更新控制面板按钮状态
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }

        // 显示通知
        this.logger.showNotification('检测到弹窗,已自动停止点赞功能', 'warning');

        // 记录弹窗信息
        const popupInfo = {
          className: popup.className || '',
          id: popup.id || '',
          tagName: popup.tagName || '',
          timestamp: new Date().toLocaleString()
        };

        this.logger.log(`弹窗详情: ${JSON.stringify(popupInfo)}`, 'info');
      }
    }

    // 启动网络请求监控
    startNetworkMonitoring() {
      // 监控 XMLHttpRequest
      const originalXHROpen = XMLHttpRequest.prototype.open;
      const originalXHRSend = XMLHttpRequest.prototype.send;

      XMLHttpRequest.prototype.open = function(method, url, ...args) {
        this._method = method;
        this._url = url;
        return originalXHROpen.apply(this, [method, url, ...args]);
      };

      XMLHttpRequest.prototype.send = function(data) {
        const xhr = this;

        // 监听响应
        xhr.addEventListener('readystatechange', () => {
          if (xhr.readyState === 4) {
            this.handleNetworkResponse(xhr._method, xhr._url, xhr.status, xhr.responseText);
          }
        });

        return originalXHRSend.apply(this, [data]);
      }.bind(this);

      // 监控 fetch 请求
      const originalFetch = window.fetch;
      window.fetch = async function(url, options = {}) {
        const method = options.method || 'GET';

        try {
          const response = await originalFetch.apply(this, [url, options]);

          // 检查响应
          if (response.status === 429) {
            const responseText = await response.clone().text();
            this.handleNetworkResponse(method, url, response.status, responseText);
          }

          return response;
        } catch (error) {
          return Promise.reject(error);
        }
      }.bind(this);

      this.logger.log('网络请求监控已启动', 'info');
    }

    // 处理网络响应
    handleNetworkResponse(method, url, status, responseText) {
      // 检查是否是点赞相关的请求
      const isLikeRequest = url && (
        url.includes('discourse-reactions') ||
        url.includes('custom-reactions') ||
        url.includes('/like') ||
        url.includes('/heart') ||
        url.includes('/toggle')
      );

      if (isLikeRequest && status === 429) {
        this.handleRateLimitError(responseText);
      }
    }

    // 处理点赞限制错误
    handleRateLimitError(responseText) {
      try {
        const errorData = JSON.parse(responseText);

        if (errorData.errors && errorData.errors.length > 0) {
          const errorMessage = errorData.errors[0];
          const timeLeft = errorData.extras?.time_left || '未知';
          const waitSeconds = errorData.extras?.wait_seconds || 0;

          this.logger.log(`🚫 点赞限制触发`, 'error');
          this.logger.log(`📝 限制详情: ${errorMessage}`, 'error');
          this.logger.log(`⏰ 剩余等待时间: ${timeLeft}`, 'warning');

          // 计算具体可点赞时间
          if (waitSeconds > 0) {
            const canLikeTimestamp = Date.now() + (waitSeconds * 1000);
            const canLikeTime = new Date(canLikeTimestamp).toLocaleString('zh-CN', {
              year: 'numeric',
              month: '2-digit',
              day: '2-digit',
              hour: '2-digit',
              minute: '2-digit',
              second: '2-digit'
            });
            this.logger.log(`📅 预计可点赞时间: ${canLikeTime}`, 'info');
          }

          // 自动停止点赞功能
          GM_setValue('autoLikeEnabled', false);

          // 保存限制信息
          const rateLimitInfo = {
            message: errorMessage,
            timeLeft: timeLeft,
            waitSeconds: waitSeconds,
            timestamp: Date.now()
          };
          GM_setValue('rateLimitInfo', rateLimitInfo);

          // 更新控制面板状态
          if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
            this.controlPanel.updateButtonStates();
          }

          // 显示通知
          this.logger.showNotification(`点赞已达限制,需等待 ${timeLeft}`, 'error');

          this.logger.log('🛑 已自动停止点赞功能,避免继续触发限制', 'action');

          // 显示详细的限制信息摘要
          this.showRateLimitSummary(rateLimitInfo);
        }
      } catch (parseError) {
        this.logger.log('解析限制错误信息失败', 'error');

        // 即使解析失败,也要停止点赞
        GM_setValue('autoLikeEnabled', false);
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }
        this.logger.showNotification('检测到点赞限制,已自动停止', 'warning');
      }
    }

    // 显示限制信息摘要
    showRateLimitSummary(rateLimitInfo) {
      this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'info');
      this.logger.log('📊 点赞限制信息摘要', 'info');
      this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'info');

      const currentTime = new Date().toLocaleString('zh-CN');
      this.logger.log(`🕐 触发时间: ${currentTime}`, 'info');

      if (rateLimitInfo.waitSeconds > 0) {
        const canLikeTime = this.getCanLikeTime(rateLimitInfo);
        this.logger.log(`📅 恢复时间: ${canLikeTime}`, 'info');

        // 计算具体的小时和分钟
        const hours = Math.floor(rateLimitInfo.waitSeconds / 3600);
        const minutes = Math.floor((rateLimitInfo.waitSeconds % 3600) / 60);

        if (hours > 0) {
          this.logger.log(`⏳ 等待时长: ${hours}小时${minutes}分钟`, 'info');
        } else {
          this.logger.log(`⏳ 等待时长: ${minutes}分钟`, 'info');
        }
      }

      this.logger.log(`💡 建议: 请在恢复时间后重新启用点赞功能`, 'info');
      this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'info');
    }

    // 获取可以点赞的具体时间
    getCanLikeTime(rateLimitInfo) {
      if (!rateLimitInfo || !rateLimitInfo.waitSeconds || !rateLimitInfo.timestamp) {
        return '未知';
      }

      const canLikeTimestamp = rateLimitInfo.timestamp + (rateLimitInfo.waitSeconds * 1000);
      const canLikeDate = new Date(canLikeTimestamp);

      return canLikeDate.toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      });
    }

    // 执行自动点赞
    async performAutoLike() {
      if (!this.siteAdapter.hasFeature('reactions') && !this.siteAdapter.hasFeature('likes')) {
        return;
      }

      // 检查是否启用了自动点赞
      if (!GM_getValue('autoLikeEnabled', false)) {
        return;
      }

      // 检查是否在限制期内
      const rateLimitInfo = GM_getValue('rateLimitInfo', null);
      if (rateLimitInfo && this.controlPanel.isRateLimitActive(rateLimitInfo)) {
        this.logger.log('点赞仍在限制期内,跳过自动点赞', 'warning');
        return;
      }

      // 检查是否有弹窗出现
      const popup = this.checkForPopups();
      if (popup) {
        this.logger.log('检测到弹窗,自动停止点赞功能', 'warning');
        GM_setValue('autoLikeEnabled', false);

        // 更新控制面板按钮状态
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }

        return;
      }

      const likeSelector = this.siteAdapter.getSelector('likeButton');
      if (!likeSelector) return;

      const likeButtons = document.querySelectorAll(likeSelector);
      const maxLikes = this.siteAdapter.getLimit('maxLikes');
      const currentLikes = GM_getValue('dailyLikeCount', 0);

      if (currentLikes >= maxLikes) {
        return;
      }

      for (const button of likeButtons) {
        if (currentLikes >= maxLikes) break;

        // 在每次点赞前再次检查弹窗
        const popupCheck = this.checkForPopups();
        if (popupCheck) {
          this.logger.log('点赞过程中检测到弹窗,停止点赞', 'warning');
          GM_setValue('autoLikeEnabled', false);

          // 更新控制面板按钮状态
          if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
            this.controlPanel.updateButtonStates();
          }

          break;
        }

        const success = await this.siteAdapter.performLike(button);
        if (success) {
          GM_setValue('dailyLikeCount', currentLikes + 1);
          this.dataAnalyzer.recordLikeEvent(this.currentTopic?.id, null);
          this.logger.updateStatistics('likesGiven');
          this.logger.log(`点赞成功 (${currentLikes + 1}/${maxLikes})`, 'success');

          // 随机延迟
          await Utils.sleep(Utils.getRandomInt(2000, 5000));
        }
      }
    }

    // 启动卡住检测
    startStuckDetection() {
      this.stuckCheckInterval = setInterval(() => {
        if (!this.isRunning) return;

        if (this.scrollSystem.isStuck()) {
          this.logger.log('检测到页面卡住,强制切换话题', 'warn');
          this.navigateToNextTopic();
        }
      }, this.config.get('stuckTimeout'));
    }
  }


  // ===== 自动化引擎类 =====
  class AutomationEngine {
    constructor(config, logger, siteAdapter) {
      this.config = config;
      this.logger = logger;
      this.siteAdapter = siteAdapter;
      this.isRunning = false;
      this.keywordPatterns = [];
      this.autoReplyTemplates = [];
      this.monitoringInterval = null;
      this.initializeTemplates();
    }

    // 初始化模板
    initializeTemplates() {
      this.autoReplyTemplates = [
        {
          trigger: ['谢谢', '感谢', 'thanks', 'thank you'],
          responses: ['不客气!', '很高兴能帮到你!', '互相帮助!', '🤝'],
          weight: 0.3
        },
        {
          trigger: ['问题', '求助', 'help', 'question'],
          responses: ['我来看看能不能帮到你', '这个问题很有意思', '让我想想...', '可以详细说说吗?'],
          weight: 0.2
        },
        {
          trigger: ['好的', '不错', 'good', 'nice', '赞'],
          responses: ['👍', '同感!', '确实如此', '说得对'],
          weight: 0.4
        },
        {
          trigger: ['教程', 'tutorial', '指南', 'guide'],
          responses: ['很实用的教程!', '学到了,感谢分享', '收藏了!', '这个教程很详细'],
          weight: 0.5
        }
      ];

      // 加载用户自定义关键词
      const customKeywords = this.config.get('monitorKeywords') || [];
      this.keywordPatterns = customKeywords.map(keyword => ({
        pattern: new RegExp(keyword, 'i'),
        keyword: keyword,
        action: this.config.get('keywordAction') || 'notify'
      }));
    }

    // 启动自动化引擎
    start() {
      if (this.isRunning) return;

      this.isRunning = true;
      this.logger.log('自动化引擎已启动', 'success');

      // 启动关键词监控
      if (this.config.get('keywordMonitoring')) {
        this.startKeywordMonitoring();
      }

      // 启动自动回复监控
      if (this.config.get('autoReplyEnabled')) {
        this.startAutoReplyMonitoring();
      }
    }

    // 停止自动化引擎
    stop() {
      if (!this.isRunning) return;

      this.isRunning = false;
      this.logger.log('自动化引擎已停止', 'action');

      if (this.monitoringInterval) {
        clearInterval(this.monitoringInterval);
        this.monitoringInterval = null;
      }
    }

    // 启动关键词监控
    startKeywordMonitoring() {
      this.monitoringInterval = setInterval(() => {
        this.scanForKeywords();
      }, 5000); // 每5秒扫描一次

      this.logger.log(`关键词监控已启动,监控 ${this.keywordPatterns.length} 个关键词`, 'info');
    }

    // 扫描关键词
    scanForKeywords() {
      if (!this.isRunning || this.keywordPatterns.length === 0) return;

      // 获取页面文本内容
      const contentSelector = this.siteAdapter.getSelector('postContent') || 'article, .post, .content';
      const contentElements = document.querySelectorAll(contentSelector);

      contentElements.forEach((element, index) => {
        // 避免重复扫描
        if (element.dataset.scanned) return;
        element.dataset.scanned = 'true';

        const text = element.textContent.toLowerCase();

        this.keywordPatterns.forEach(({ pattern, keyword, action }) => {
          if (pattern.test(text)) {
            this.handleKeywordMatch(keyword, action, element, text);
          }
        });
      });
    }

    // 处理关键词匹配
    async handleKeywordMatch(keyword, action, element, text) {
      this.logger.log(`检测到关键词: ${keyword}`, 'success');

      switch (action) {
        case 'like':
          await this.performAutoLike(element);
          break;
        case 'reply':
          await this.performAutoReply(element, keyword);
          break;
        case 'notify':
          this.showKeywordNotification(keyword, text.substring(0, 100));
          break;
        case 'collect':
          await this.collectPost(element);
          break;
      }
    }

    // 执行自动点赞(关键词触发)
    async performAutoLike(element) {
      // 检查是否启用了自动点赞
      if (!GM_getValue('autoLikeEnabled', false)) {
        return;
      }

      // 检查是否有弹窗出现
      const popup = this.checkForPopups();
      if (popup) {
        this.logger.log('检测到弹窗,停止关键词触发的点赞', 'warning');
        GM_setValue('autoLikeEnabled', false);

        // 更新控制面板按钮状态
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }

        return;
      }

      const likeButton = element.querySelector(this.siteAdapter.getSelector('likeButton'));
      if (likeButton) {
        const success = await this.siteAdapter.performLike(likeButton);
        if (success) {
          this.logger.log('关键词触发自动点赞', 'success');
        }
      }
    }

    // 检测是否有弹窗出现(AutomationEngine版本)
    checkForPopups() {
      // 需要忽略的弹窗类型(信息性弹窗,不应停止点赞)
      const ignoredPopupSelectors = [
        '.user-card',           // 用户信息卡片
        '.user-tooltip',        // 用户提示框
        '.topic-entrance',      // 话题入口
        '.quote-button',        // 引用按钮
        '.post-menu',          // 帖子菜单
        '.dropdown-menu',      // 下拉菜单
        '.autocomplete',       // 自动完成
        '.suggestion-menu',    // 建议菜单
        '.emoji-picker',       // 表情选择器
        '.preview-popup'       // 预览弹窗
      ];

      // 需要检测的弹窗选择器(会阻止操作的弹窗)
      const criticalPopupSelectors = [
        '.modal', '.popup', '.dialog', '.overlay',
        '.alert', '.notification', '.toast',
        '[role="dialog"]', '[role="alertdialog"]',
        '.swal2-container', '.sweetalert2-container',
        '.layui-layer', '.layer-shade',
        '.ant-modal', '.el-dialog',
        '.v-dialog', '.q-dialog',
        // NodeLoc 特定的重要弹窗
        '.fancybox-container', '.fancybox-overlay',
        '.ui-dialog', '.ui-widget-overlay',
        '.bootbox', '.confirm-dialog',
        '.error-dialog', '.warning-dialog'
      ];

      // 首先检查是否是应该忽略的弹窗
      for (const selector of ignoredPopupSelectors) {
        const popup = document.querySelector(selector);
        if (popup && this.isElementVisible(popup)) {
          // 这是信息性弹窗,不需要停止点赞
          return null;
        }
      }

      // 检查关键弹窗
      for (const selector of criticalPopupSelectors) {
        const popup = document.querySelector(selector);
        if (popup && this.isElementVisible(popup)) {
          return popup;
        }
      }

      // 检查是否有遮罩层(但排除用户卡片相关的)
      const overlays = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]');
      for (const overlay of overlays) {
        // 跳过用户卡片相关的遮罩
        if (overlay.id === 'user-card' ||
            overlay.classList.contains('user-card') ||
            overlay.closest('.user-card')) {
          continue;
        }

        const style = getComputedStyle(overlay);
        if (style.zIndex > 1000 &&
            (style.backgroundColor !== 'rgba(0, 0, 0, 0)' ||
             style.background !== 'none')) {
          return overlay;
        }
      }

      return null;
    }

    // 检查元素是否可见
    isElementVisible(element) {
      if (!element) return false;

      const style = getComputedStyle(element);
      return element.style.display !== 'none' &&
             style.display !== 'none' &&
             style.visibility !== 'hidden' &&
             style.opacity !== '0';
    }

    // 执行自动回复
    async performAutoReply(element, keyword) {
      if (!this.siteAdapter.hasFeature('replies')) return;

      const replyButton = element.querySelector(this.siteAdapter.getSelector('replyButton'));
      if (!replyButton) return;

      // 生成回复内容
      const replyContent = this.generateReplyContent(keyword);
      if (!replyContent) return;

      try {
        // 点击回复按钮
        replyButton.click();

        // 等待回复框出现
        await Utils.sleep(1000);

        // 查找回复输入框
        const replyInput = document.querySelector('textarea[placeholder*="回复"], .reply-area textarea, .composer-input');
        if (replyInput) {
          // 模拟输入
          await this.simulateTyping(replyInput, replyContent);

          // 查找发送按钮
          const sendButton = document.querySelector('.btn-primary[title*="发送"], .submit-reply, .create');
          if (sendButton && !sendButton.disabled) {
            // 随机延迟后发送
            await Utils.sleep(Utils.getRandomInt(2000, 5000));
            sendButton.click();

            this.logger.log(`自动回复: ${replyContent}`, 'success');
          }
        }
      } catch (error) {
        this.logger.log(`自动回复失败: ${error.message}`, 'error');
      }
    }

    // 生成回复内容
    generateReplyContent(keyword) {
      const matchingTemplates = this.autoReplyTemplates.filter(template =>
        template.trigger.some(trigger => keyword.toLowerCase().includes(trigger.toLowerCase()))
      );

      if (matchingTemplates.length === 0) {
        // 使用通用回复
        const genericReplies = ['👍', '有道理', '学习了', '感谢分享'];
        return genericReplies[Math.floor(Math.random() * genericReplies.length)];
      }

      // 根据权重选择模板
      const totalWeight = matchingTemplates.reduce((sum, t) => sum + t.weight, 0);
      let random = Math.random() * totalWeight;

      for (const template of matchingTemplates) {
        random -= template.weight;
        if (random <= 0) {
          const responses = template.responses;
          return responses[Math.floor(Math.random() * responses.length)];
        }
      }

      return null;
    }

    // 模拟打字
    async simulateTyping(input, text) {
      input.focus();
      input.value = '';

      // 逐字符输入
      for (let i = 0; i < text.length; i++) {
        input.value += text[i];

        // 触发输入事件
        const inputEvent = new Event('input', { bubbles: true });
        input.dispatchEvent(inputEvent);

        // 随机延迟
        await Utils.sleep(Utils.getRandomInt(50, 150));
      }

      // 触发最终事件
      const changeEvent = new Event('change', { bubbles: true });
      input.dispatchEvent(changeEvent);
    }

    // 显示关键词通知
    showKeywordNotification(keyword, context) {
      if (typeof GM_notification !== 'undefined') {
        GM_notification({
          text: `检测到关键词: ${keyword}\n${context}...`,
          title: '智能论坛助手',
          timeout: 5000,
          onclick: () => {
            window.focus();
          }
        });
      }
    }

    // 收藏帖子
    async collectPost(element) {
      // 查找收藏按钮
      const bookmarkButton = element.querySelector('.bookmark, [title*="收藏"], [data-action="bookmark"]');
      if (bookmarkButton && !bookmarkButton.classList.contains('bookmarked')) {
        bookmarkButton.click();
        this.logger.log('自动收藏帖子', 'success');
        await Utils.sleep(1000);
      }
    }

    // 启动自动回复监控
    startAutoReplyMonitoring() {
      // 监控新帖子
      const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          mutation.addedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) {
              this.scanNewContent(node);
            }
          });
        });
      });

      observer.observe(document.body, {
        childList: true,
        subtree: true
      });

      this.logger.log('自动回复监控已启动', 'info');
    }

    // 扫描新内容
    scanNewContent(element) {
      if (!this.isRunning) return;

      // 检查是否为帖子内容
      const postSelectors = ['.post', '.topic-post', '.cooked', 'article'];
      const isPost = postSelectors.some(selector =>
        element.matches && element.matches(selector)
      );

      if (isPost) {
        const text = element.textContent.toLowerCase();

        // 检查是否应该自动回复
        const shouldReply = this.autoReplyTemplates.some(template =>
          template.trigger.some(trigger => text.includes(trigger.toLowerCase()))
        );

        if (shouldReply && Math.random() < 0.3) { // 30%概率回复
          setTimeout(() => {
            this.performAutoReply(element, text);
          }, Utils.getRandomInt(5000, 15000)); // 5-15秒后回复
        }
      }
    }

    // 智能互动
    async performSmartInteraction() {
      const interactions = [
        () => this.likeRandomPosts(),
        () => this.followInterestingUsers(),
        () => this.bookmarkUsefulContent(),
        () => this.shareContent()
      ];

      const randomInteraction = interactions[Math.floor(Math.random() * interactions.length)];
      await randomInteraction();
    }

    // 点赞随机帖子
    async likeRandomPosts() {
      // 检查是否启用了自动点赞
      if (!GM_getValue('autoLikeEnabled', false)) {
        return;
      }

      // 检查是否有弹窗出现
      const popup = this.checkForPopups();
      if (popup) {
        this.logger.log('检测到弹窗,停止随机点赞', 'warning');
        GM_setValue('autoLikeEnabled', false);

        // 更新控制面板按钮状态
        if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
          this.controlPanel.updateButtonStates();
        }

        return;
      }

      const likeButtons = document.querySelectorAll(this.siteAdapter.getSelector('likeButton'));
      const maxLikes = Math.min(3, likeButtons.length);

      for (let i = 0; i < maxLikes; i++) {
        // 在每次点赞前检查弹窗
        const popupCheck = this.checkForPopups();
        if (popupCheck) {
          this.logger.log('随机点赞过程中检测到弹窗,停止点赞', 'warning');
          GM_setValue('autoLikeEnabled', false);

          // 更新控制面板按钮状态
          if (this.controlPanel && typeof this.controlPanel.updateButtonStates === 'function') {
            this.controlPanel.updateButtonStates();
          }

          break;
        }

        const randomButton = likeButtons[Math.floor(Math.random() * likeButtons.length)];
        if (randomButton) {
          await this.siteAdapter.performLike(randomButton);
          await Utils.sleep(Utils.getRandomInt(2000, 5000));
        }
      }
    }

    // 关注有趣的用户
    async followInterestingUsers() {
      const userLinks = document.querySelectorAll('a[href*="/u/"], .user-link');
      if (userLinks.length > 0 && Math.random() < 0.1) { // 10%概率
        const randomUser = userLinks[Math.floor(Math.random() * userLinks.length)];
        // 这里可以添加关注逻辑
        this.logger.log('发现有趣用户', 'info');
      }
    }

    // 收藏有用内容
    async bookmarkUsefulContent() {
      const usefulKeywords = ['教程', '指南', '技巧', 'tutorial', 'guide', 'tip'];
      const posts = document.querySelectorAll('.post, .topic-post');

      posts.forEach(async (post) => {
        const text = post.textContent.toLowerCase();
        const isUseful = usefulKeywords.some(keyword => text.includes(keyword));

        if (isUseful && Math.random() < 0.2) { // 20%概率收藏
          await this.collectPost(post);
        }
      });
    }

    // 分享内容
    async shareContent() {
      // 查找分享按钮
      const shareButtons = document.querySelectorAll('.share, [title*="分享"], [data-action="share"]');
      if (shareButtons.length > 0 && Math.random() < 0.05) { // 5%概率分享
        const randomShare = shareButtons[Math.floor(Math.random() * shareButtons.length)];
        randomShare.click();
        this.logger.log('分享有趣内容', 'action');
      }
    }
  }

  // ===== 每日任务管理器 =====
  class DailyTaskManager {
    constructor(config, logger, forumAssistant) {
      this.config = config;
      this.logger = logger;
      this.forumAssistant = forumAssistant;
      this.checkInterval = null;
    }

    // 启动每日任务检查
    start() {
      // 立即检查一次
      this.checkDailyTasks();

      // 每分钟检查一次
      this.checkInterval = setInterval(() => {
        this.checkDailyTasks();
      }, 60000);

      this.logger.log('每日任务管理器已启动', 'info');
    }

    // 停止每日任务检查
    stop() {
      if (this.checkInterval) {
        clearInterval(this.checkInterval);
        this.checkInterval = null;
      }
    }

    // 检查每日任务
    checkDailyTasks() {
      const now = new Date();
      const today = now.toISOString().split('T')[0];
      const lastRunDate = GM_getValue('dailyTaskLastRunDate', '');

      // 检查是否为新的一天
      if (lastRunDate !== today) {
        this.resetDailyCounters();
        GM_setValue('dailyTaskLastRunDate', today);
      }

      // 检查是否在自动启动时间范围内 (00:10-00:15)
      if (now.getHours() === 0 && now.getMinutes() >= 10 && now.getMinutes() < 15) {
        const autoStarted = GM_getValue('autoStartedToday', false);
        if (!autoStarted) {
          this.performDailyAutoStart();
          GM_setValue('autoStartedToday', true);
        }
      }

      // 重置自动启动标志(在非启动时间)
      if (now.getHours() !== 0 || now.getMinutes() < 10 || now.getMinutes() >= 15) {
        GM_setValue('autoStartedToday', false);
      }
    }

    // 重置每日计数器
    resetDailyCounters() {
      GM_setValue('dailyLikeCount', 0);
      GM_setValue('dailyTopicsRead', 0);
      GM_setValue('dailyErrors', 0);

      this.logger.log('每日计数器已重置', 'action');
    }

    // 执行每日自动启动
    performDailyAutoStart() {
      this.logger.log('执行每日自动启动任务', 'success');

      try {
        // 启用自动点赞
        GM_setValue('autoLikeEnabled', true);

        // 启动论坛助手
        if (!this.forumAssistant.isRunning) {
          setTimeout(() => {
            this.forumAssistant.start();
          }, Utils.getRandomInt(5000, 15000)); // 5-15秒后启动
        }

        this.logger.log('每日自动启动完成', 'success');

      } catch (error) {
        this.logger.log(`每日自动启动失败: ${error.message}`, 'error');
      }
    }

    // 获取每日统计
    getDailyStats() {
      return {
        likesGiven: GM_getValue('dailyLikeCount', 0),
        topicsRead: GM_getValue('dailyTopicsRead', 0),
        errors: GM_getValue('dailyErrors', 0),
        date: new Date().toISOString().split('T')[0]
      };
    }
  }

  // ===== 全局变量和初始化 =====
  let forumAssistant = null;
  let dailyTaskManager = null;

  // ===== 安全检查函数 =====
  function safeElementAccess(element, property, defaultValue = null) {
    try {
      if (!element || typeof element !== 'object') return defaultValue;
      return element[property] || defaultValue;
    } catch (e) {
      console.warn('安全访问元素属性失败:', e);
      return defaultValue;
    }
  }

  function safeStyleAccess(element, property, value) {
    try {
      if (!element || !element.style) return false;
      element.style[property] = value;
      return true;
    } catch (e) {
      console.warn('安全设置样式失败:', e);
      return false;
    }
  }

  // ===== 主初始化函数 =====
  function initializeForumAssistant() {
    // 防止重复初始化
    if (window.forumAssistantInitialized) {
      console.log('智能论坛助手已经初始化,跳过重复初始化');
      return;
    }

    try {
      console.log('开始初始化智能论坛助手 Pro...');

      // 检查必要的API
      if (typeof GM_getValue === 'undefined') {
        console.warn('GM_getValue 不可用,使用 localStorage 作为备用');
        window.GM_getValue = (key, defaultValue) => {
          try {
            const value = localStorage.getItem('gm_' + key);
            return value !== null ? JSON.parse(value) : defaultValue;
          } catch (e) {
            return defaultValue;
          }
        };
        window.GM_setValue = (key, value) => {
          try {
            localStorage.setItem('gm_' + key, JSON.stringify(value));
          } catch (e) {
            console.error('存储失败:', e);
          }
        };
        window.GM_deleteValue = (key) => {
          try {
            localStorage.removeItem('gm_' + key);
          } catch (e) {
            console.error('删除失败:', e);
          }
        };
        window.GM_listValues = () => {
          try {
            return Object.keys(localStorage).filter(key => key.startsWith('gm_')).map(key => key.substring(3));
          } catch (e) {
            return [];
          }
        };
      }

      // 创建主程序实例
      forumAssistant = new ForumAssistant();

      // 创建每日任务管理器
      dailyTaskManager = new DailyTaskManager(
        forumAssistant.config,
        forumAssistant.logger,
        forumAssistant
      );

      // 启动每日任务管理器
      dailyTaskManager.start();

      // 绑定全局事件
      bindGlobalEvents();

      // 将实例暴露到全局,供控制面板调用
      window.forumAssistant = forumAssistant;

      // 标记初始化完成
      window.forumAssistantInitialized = true;

      console.log('智能论坛助手 Pro 初始化完成');

    } catch (error) {
      console.error('智能论坛助手初始化失败:', error);

      // 显示错误通知
      if (typeof GM_notification !== 'undefined') {
        GM_notification({
          text: `初始化失败: ${error.message}`,
          title: '智能论坛助手',
          timeout: 5000
        });
      } else {
        // 备用通知方式
        setTimeout(() => {
          alert(`智能论坛助手初始化失败: ${error.message}`);
        }, 1000);
      }
    }
  }

  // ===== 绑定全局事件 =====
  function bindGlobalEvents() {
    // 页面卸载时保存数据
    window.addEventListener('beforeunload', () => {
      if (forumAssistant && forumAssistant.isRunning) {
        forumAssistant.dataAnalyzer.endSession();
      }
    });

    // 页面可见性变化
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        // 页面隐藏时暂停某些功能
        if (forumAssistant) {
          forumAssistant.behaviorSimulator.stop();
        }
      } else {
        // 页面显示时恢复功能
        if (forumAssistant && forumAssistant.isRunning) {
          forumAssistant.behaviorSimulator.start();
        }
      }
    });

    // 键盘快捷键
    document.addEventListener('keydown', (e) => {
      // Ctrl+Shift+F: 开启/关闭论坛助手
      if (e.ctrlKey && e.shiftKey && e.key === 'F') {
        e.preventDefault();
        if (forumAssistant) {
          if (forumAssistant.isRunning) {
            forumAssistant.stop();
          } else {
            forumAssistant.start();
          }
        }
      }

      // Ctrl+Shift+C: 打开配置面板
      if (e.ctrlKey && e.shiftKey && e.key === 'C') {
        e.preventDefault();
        if (forumAssistant) {
          forumAssistant.configPanel.toggle();
        }
      }

      // Ctrl+Shift+S: 显示/隐藏统计面板
      if (e.ctrlKey && e.shiftKey && e.key === 'S') {
        e.preventDefault();
        if (forumAssistant) {
          forumAssistant.statsPanel.toggle();
        }
      }
    });

    // 错误处理
    window.addEventListener('error', (e) => {
      try {
        console.error('全局错误捕获:', e.message, e.filename, e.lineno);
        if (forumAssistant && forumAssistant.logger) {
          forumAssistant.logger.log(`全局错误: ${e.message} (${e.filename}:${e.lineno})`, 'error');
          if (forumAssistant.dataAnalyzer) {
            forumAssistant.dataAnalyzer.recordErrorEvent('global', e.message, e.filename);
          }
        }
      } catch (err) {
        console.error('错误处理器本身出错:', err);
      }
    });

    // 未处理的Promise拒绝
    window.addEventListener('unhandledrejection', (e) => {
      try {
        console.error('未处理的Promise拒绝:', e.reason);
        if (forumAssistant && forumAssistant.logger) {
          forumAssistant.logger.log(`未处理的Promise拒绝: ${e.reason}`, 'error');
          if (forumAssistant.dataAnalyzer) {
            forumAssistant.dataAnalyzer.recordErrorEvent('promise', e.reason, 'unhandled_rejection');
          }
        }
        // 防止控制台错误
        e.preventDefault();
      } catch (err) {
        console.error('Promise拒绝处理器出错:', err);
      }
    });
  }

  // ===== 脚本启动 =====

  // 安全启动函数
  function safeInitialize() {
    try {
      // 检查环境
      if (typeof document === 'undefined') {
        console.error('document 对象不可用');
        return;
      }

      // 检查是否在支持的页面
      const supportedDomains = ['linux.do', 'meta.discourse.org', 'meta.appinn.net', 'community.openai.com', 'nodeloc.cc', 'bbs.tampermonkey.net.cn', 'greasyfork.org'];
      const currentDomain = window.location.hostname;
      const isSupported = supportedDomains.some(domain => currentDomain.includes(domain));

      if (!isSupported) {
        console.log('当前域名不在支持列表中:', currentDomain);
        // 仍然尝试初始化,可能是新的Discourse站点
      }

      console.log('开始安全初始化...');
      initializeForumAssistant();

    } catch (error) {
      console.error('安全初始化失败:', error);
      // 延迟重试
      setTimeout(() => {
        console.log('尝试重新初始化...');
        initializeForumAssistant();
      }, 3000);
    }
  }

  // 多种启动方式确保脚本能够运行
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', safeInitialize);
  } else if (document.readyState === 'interactive' || document.readyState === 'complete') {
    // DOM已经加载完成,立即初始化
    setTimeout(safeInitialize, 100);
  }

  // 备用启动方式1(window.load事件)
  window.addEventListener('load', () => {
    if (!window.forumAssistantInitialized) {
      console.log('备用启动方式1触发 (window.load)');
      setTimeout(safeInitialize, 1000);
    }
  });

  // 备用启动方式2(延迟启动)
  setTimeout(() => {
    if (!window.forumAssistantInitialized) {
      console.log('备用启动方式2触发 (延迟启动)');
      safeInitialize();
    }
  }, 5000);

  // 备用启动方式3(用户交互后启动)
  const interactionEvents = ['click', 'scroll', 'keydown'];
  const startOnInteraction = () => {
    if (!window.forumAssistantInitialized) {
      console.log('备用启动方式3触发 (用户交互)');
      safeInitialize();
      // 移除事件监听器
      interactionEvents.forEach(event => {
        document.removeEventListener(event, startOnInteraction);
      });
    }
  };

  interactionEvents.forEach(event => {
    document.addEventListener(event, startOnInteraction, { once: true, passive: true });
  });

})();
0

评论 (0)

取消