Greasy Fork

Greasy Fork is available in English.

linux.do 小助手(增强版)

自动浏览、点赞、只看楼主、楼层号、保存帖子到本地、清爽模式、黑白灰模式、用户信息展示(批量展示)、查看用户话题、Credit积分悬浮窗。支持拖动和最小化控制面板。支持 linux.do 和 idcflare.com

当前为 2025-12-25 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        linux.do 小助手(增强版)
// @description 自动浏览、点赞、只看楼主、楼层号、保存帖子到本地、清爽模式、黑白灰模式、用户信息展示(批量展示)、查看用户话题、Credit积分悬浮窗。支持拖动和最小化控制面板。支持 linux.do 和 idcflare.com
// @namespace    https://example.com/userscripts
// @match       https://linux.do/*
// @match       https://idcflare.com/*
// @grant       GM_xmlhttpRequest
// @grant       GM_addStyle
// @grant       GM_setValue
// @grant       GM_getValue
// @connect     connect.linux.do
// @connect     credit.linux.do
// @connect     linux.do
// @connect     *
// @run-at      document-idle
// @version     1.7.0
// @author      quantumcat & nulluser & enhanced & idear
// @license     MIT
// @icon        https://www.google.com/s2/favicons?domain=linux.do
// ==/UserScript==

// 获取当前站点域名
const CURRENT_DOMAIN = window.location.hostname;
const BASE_URL = `https://${CURRENT_DOMAIN}`;

// 配置项
const CONFIG = {
    scroll: {
        minSpeed: 10,
        maxSpeed: 15,
        minDistance: 2,
        maxDistance: 4,
        checkInterval: 500,
        fastScrollChance: 0.08,
        fastScrollMin: 80,
        fastScrollMax: 200
    },
    time: {
        browseTime: 3600000,
        restTime: 600000,
        minPause: 300,
        maxPause: 500,
        loadWait: 1500,
    },
    article: {
        commentLimit: 5000,
        topicListLimit: 100,
        retryLimit: 3
    },
    levelRequirements: {
        0: { // 0级升1级
            topics_entered: 5,
            posts_read_count: 30,
            time_read: 600 // 10分钟 = 600秒
        },
        1: { // 1级升2级
            days_visited: 15,
            likes_given: 1,
            likes_received: 1,
            post_count: 3,
            topics_entered: 20,
            posts_read_count: 100,
            time_read: 3600 // 60分钟 = 3600秒
        }
    },
    mustRead: {
        posts: [
            {
                id: '1051',
                url: 'https://linux.do/t/topic/1051/'
            },
            {
                id: '5973',
                url: 'https://linux.do/t/topic/5973'
            },
            {
                id: '102770',
                url: 'https://linux.do/t/topic/102770'
            },
            {
                id: '154010',
                url: 'https://linux.do/t/topic/154010'
            },
            {
                id: '149576',
                url: 'https://linux.do/t/topic/149576'
            },
            {
                id: '22118',
                url: 'https://linux.do/t/topic/22118'
            },
        ],
        likesNeeded: 5
    }
};

// 工具函数
const Utils = {
    random: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
    sleep: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
    isPageLoaded: () => {
        const loadingElements = document.querySelectorAll('.loading, .infinite-scroll');
        return loadingElements.length === 0;
    },
    isNearBottom: () => {
        const {scrollHeight, clientHeight, scrollTop} = document.documentElement;
        return (scrollTop + clientHeight) >= (scrollHeight - 200);
    },
    debounce: (func, wait) => {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }
};

// 存储管理
const Storage = {
    get: (key, defaultValue = null) => {
        try {
            const value = localStorage.getItem(key);
            return value ? JSON.parse(value) : defaultValue;
        } catch {
            return defaultValue;
        }
    },
    set: (key, value) => {
        try {
            localStorage.setItem(key, JSON.stringify(value));
            return true;
        } catch (error) {
            console.error('Storage error:', error);
            return false;
        }
    }
};

// 用户信息助手类
class UserInfoHelper {
    constructor() {
        this.userInfoCache = new Map();
        this.pendingRequests = new Map();
        this.TRUST_LEVEL_LABELS = {
            0: 'Lv0',
            1: 'Lv1',
            2: 'Lv2',
            3: 'Lv3',
            4: 'Lv4'
        };
        this.DAY_IN_MS = 24 * 60 * 60 * 1000;
        this.revealInProgress = false;
        this.isEnabled = true; // 用户信息展示是否启用
        this.observer = null;

        this.init();
    }

    enable() {
        this.isEnabled = true;
        this.init();
    }

    disable() {
        this.isEnabled = false;
        if (this.observer) {
            this.observer.disconnect();
            this.observer = null;
        }
    }

    init() {
        if (!this.isEnabled) return;

        // 如果已有观察器,先断开
        if (this.observer) {
            this.observer.disconnect();
        }

        // 使用防抖,避免频繁触发
        const debouncedEnhance = this.debounce(() => {
            if (this.isEnabled) {
                this.enhanceUserInfo();
            }
        }, 300);

        // 监听页面变化,自动为新加载的用户添加信息
        this.observer = new MutationObserver(() => {
            if (this.isEnabled) {
                debouncedEnhance();
            }
        });

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

        // 初始增强
        this.enhanceUserInfo();
    }

    debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    isTopicPage() {
        return window.location.pathname.includes('/t/topic/');
    }

    async enhanceUserInfo() {
        if (!this.isTopicPage()) return;

        const articles = document.querySelectorAll('.topic-post article');
        for (const article of articles) {
            const anchor = article.querySelector('.names a[data-user-card]');
            if (!anchor) continue;

            const slug = anchor.getAttribute('data-user-card');
            if (!slug) continue;

            const normalizedSlug = slug.trim().toLowerCase();

            // 检查是否已经添加过信息
            if (article.querySelector(`.user-reg-info[data-user="${normalizedSlug}"]`)) {
                continue;
            }

            // 检查是否是第一楼(楼主)
            const postWrapper = article.closest('.topic-post');
            const postNumber = postWrapper?.getAttribute('data-post-number');
            const isFirstPost = postNumber === '1';

            // 第一楼直接显示,其他楼添加按钮
            if (isFirstPost) {
                await this.loadAndDisplayUserInfo(anchor, slug, normalizedSlug);
            } else {
                this.addInfoButton(anchor, slug, normalizedSlug);
            }
        }
    }

    addInfoButton(anchor, rawSlug, normalizedSlug) {
        const namesContainer = anchor.closest('.names');
        if (!namesContainer) return;

        // 检查是否已有按钮或信息
        if (namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`)) {
            return;
        }

        // 如果已经有信息节点,不添加按钮
        if (namesContainer.querySelector(`.user-reg-info[data-user="${normalizedSlug}"]`)) {
            return;
        }

        const button = document.createElement('button');
        button.className = 'user-info-btn';
        button.setAttribute('data-user', normalizedSlug);
        button.setAttribute('data-raw-slug', rawSlug);
        button.textContent = '📊';
        button.title = '点击查看用户注册信息';
        button.style.cssText = `
            margin-left: 6px;
            font-size: 14px;
            cursor: pointer;
            background: none;
            border: none;
            padding: 2px 4px;
            opacity: 0.6;
            transition: opacity 0.2s;
            vertical-align: middle;
        `;

        button.addEventListener('mouseenter', () => {
            button.style.opacity = '1';
        });

        button.addEventListener('mouseleave', () => {
            button.style.opacity = '0.6';
        });

        button.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();
            if (button.disabled) return;

            button.disabled = true;
            button.textContent = '⏳';

            try {
                await this.loadAndDisplayUserInfo(anchor, rawSlug, normalizedSlug);
                // 成功后按钮会被 loadAndDisplayUserInfo 中移除
            } catch (error) {
                console.error('加载用户信息失败:', error);
                button.textContent = '📊';
                button.disabled = false;
            }
        });

        anchor.insertAdjacentElement('afterend', button);

        // 添加"查看话题"按钮
        this.addTopicsButton(anchor, rawSlug, normalizedSlug);
    }

    addTopicsButton(anchor, rawSlug, normalizedSlug) {
        const namesContainer = anchor.closest('.names');
        if (!namesContainer) return;

        // 检查是否已有话题按钮
        if (namesContainer.querySelector(`.user-topics-btn[data-user="${normalizedSlug}"]`)) {
            return;
        }

        const topicsBtn = document.createElement('a');
        topicsBtn.className = 'user-topics-btn';
        topicsBtn.setAttribute('data-user', normalizedSlug);
        topicsBtn.href = `${BASE_URL}/u/${rawSlug}/activity/topics`;
        topicsBtn.target = '_blank';
        topicsBtn.textContent = '查看话题';
        topicsBtn.title = '查看该用户的话题';
        topicsBtn.style.cssText = `
            margin-left: 6px;
            font-size: 12px;
            cursor: pointer;
            text-decoration: none;
            padding: 2px 6px;
            opacity: 0.7;
            transition: all 0.2s;
            vertical-align: middle;
            display: inline-block;
            color: #667eea;
            background: rgba(102, 126, 234, 0.1);
            border-radius: 4px;
        `;

        topicsBtn.addEventListener('mouseenter', () => {
            topicsBtn.style.opacity = '1';
            topicsBtn.style.background = 'rgba(102, 126, 234, 0.2)';
        });

        topicsBtn.addEventListener('mouseleave', () => {
            topicsBtn.style.opacity = '0.7';
            topicsBtn.style.background = 'rgba(102, 126, 234, 0.1)';
        });

        // 插入到信息按钮后面
        const infoBtn = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
        if (infoBtn) {
            infoBtn.insertAdjacentElement('afterend', topicsBtn);
        } else {
            anchor.insertAdjacentElement('afterend', topicsBtn);
        }
    }

    async loadAndDisplayUserInfo(anchor, slug, normalizedSlug) {
        const namesContainer = anchor.closest('.names');
        if (!namesContainer) return;

        // 再次检查是否已经存在,避免重复
        const existingInfo = namesContainer.querySelector(`.user-reg-info[data-user="${normalizedSlug}"]`);
        if (existingInfo) {
            console.log(`用户 ${normalizedSlug} 信息已存在,跳过`);
            // 确保按钮被移除
            const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
            if (button) button.remove();
            return;
        }

        const info = await this.fetchUserInfo(slug, normalizedSlug);
        if (!info) {
            // 获取失败,恢复按钮
            const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
            if (button) {
                button.textContent = '📊';
                button.disabled = false;
            }
            return;
        }

        const infoNode = this.buildInfoNode(info, normalizedSlug);
        if (!infoNode) {
            // 构建失败,恢复按钮
            const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
            if (button) {
                button.textContent = '📊';
                button.disabled = false;
            }
            return;
        }

        // 最后一次检查,确保在异步等待期间没有被其他调用添加
        const finalCheck = namesContainer.querySelector(`.user-reg-info[data-user="${normalizedSlug}"]`);
        if (finalCheck) {
            console.log(`用户 ${normalizedSlug} 信息在等待期间已被添加,跳过`);
            // 移除按钮
            const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
            if (button) button.remove();
            return;
        }

        // 先移除信息按钮
        const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
        if (button) button.remove();

        // 添加信息节点
        anchor.insertAdjacentElement('afterend', infoNode);

        // 确保话题按钮存在(如果还没有添加)
        if (!namesContainer.querySelector(`.user-topics-btn[data-user="${normalizedSlug}"]`)) {
            this.addTopicsButton(anchor, slug, normalizedSlug);
        }
    }

    async fetchUserInfo(slug, normalizedSlug) {
        // 检查缓存
        if (this.userInfoCache.has(normalizedSlug)) {
            return this.userInfoCache.get(normalizedSlug);
        }

        // 检查是否正在请求
        if (this.pendingRequests.has(normalizedSlug)) {
            return this.pendingRequests.get(normalizedSlug);
        }

        // 创建请求
        const requestPromise = this.doFetchUserInfo(slug, normalizedSlug);
        this.pendingRequests.set(normalizedSlug, requestPromise);

        try {
            const info = await requestPromise;
            if (info) {
                this.userInfoCache.set(normalizedSlug, info);
            }
            return info;
        } finally {
            this.pendingRequests.delete(normalizedSlug);
        }
    }

    async doFetchUserInfo(slug, normalizedSlug) {
        try {
            // 使用两个API并行请求,与原脚本保持一致
            const PROFILE_API_BUILDERS = [
                (s) => `${BASE_URL}/u/${encodeURIComponent(s)}.json`,
                (s) => `${BASE_URL}/users/${encodeURIComponent(s)}.json`,
            ];

            const SUMMARY_API_BUILDERS = [
                (s) => `${BASE_URL}/u/${encodeURIComponent(s)}/summary.json`,
                (s) => `${BASE_URL}/users/${encodeURIComponent(s)}/summary.json`,
            ];

            const [profileData, summaryData] = await Promise.all([
                this.fetchFirstAvailable(PROFILE_API_BUILDERS, slug),
                this.fetchFirstAvailable(SUMMARY_API_BUILDERS, slug),
            ]);

            if (!profileData && !summaryData) {
                return null;
            }

            const user = profileData && (profileData.user || profileData);
            const summary = summaryData && (summaryData.user_summary || summaryData.summary || summaryData);

            const createdAt = this.pickCreatedAt(user) || (summary && this.pickCreatedAt(summary));
            if (!createdAt) {
                return null;
            }

            const topicCount = this.pickFirstNumber(
                user && (user.topic_count ?? user.topicCount),
                summary && (summary.topic_count ?? summary.topics_count),
            );

            const totalPostCount = this.pickFirstNumber(
                user && (user.post_count ?? user.postCount),
                summary && (summary.post_count ?? summary.posts_count),
            );

            let repliesCount = this.pickFirstNumber(
                summary && (summary.replies_count ?? summary.reply_count),
            );
            if (repliesCount === null && totalPostCount !== null && topicCount !== null) {
                repliesCount = Math.max(0, totalPostCount - topicCount);
            }

            const trustLevelRaw = this.pickFirstValue(
                user && (user.trust_level ?? user.trustLevel),
                summary && (summary.trust_level ?? summary.trustLevel),
            );
            const trustLevel = this.normalizeTrustLevel(trustLevelRaw);

            const days = this.calcDays(createdAt);

            return {
                slug: normalizedSlug,
                createdAt,
                days,
                topicCount: typeof topicCount === 'number' && Number.isFinite(topicCount) ? topicCount : undefined,
                repliesCount: typeof repliesCount === 'number' && Number.isFinite(repliesCount) ? repliesCount : undefined,
                trustLevel
            };
        } catch (error) {
            console.error('获取用户信息失败:', slug, error);
            return null;
        }
    }

    async fetchFirstAvailable(builders, slug) {
        for (const builder of builders) {
            const url = builder(slug);
            const data = await this.safeFetchJson(url);
            if (data) {
                return data;
            }
        }
        return null;
    }

    async safeFetchJson(url) {
        try {
            const response = await fetch(url, { credentials: 'include' });
            if (!response.ok) {
                return null;
            }
            return await response.json();
        } catch (error) {
            return null;
        }
    }

    pickFirstNumber(...values) {
        for (const value of values) {
            const numberValue = Number(value);
            if (!Number.isNaN(numberValue)) {
                return numberValue;
            }
        }
        return null;
    }

    pickFirstValue(...values) {
        for (const value of values) {
            if (value !== undefined && value !== null) {
                return value;
            }
        }
        return null;
    }

    normalizeTrustLevel(raw) {
        if (raw === undefined || raw === null) {
            return undefined;
        }

        if (typeof raw === 'number' && Number.isFinite(raw)) {
            return raw;
        }

        if (typeof raw === 'string') {
            const TRUST_LEVEL_ALIAS = {
                newuser: 0,
                basic: 1,
                member: 2,
                regular: 3,
                leader: 4,
            };
            const alias = TRUST_LEVEL_ALIAS[raw.toLowerCase()];
            if (alias !== undefined) {
                return alias;
            }
            const numeric = Number(raw);
            if (!Number.isNaN(numeric)) {
                return numeric;
            }
        }

        return undefined;
    }

    pickCreatedAt(source) {
        if (!source) {
            return null;
        }
        return (
            source.created_at ||
            source.createdAt ||
            source.registration_date ||
            source.registrationDate ||
            source.joined ||
            source.joinedAt ||
            null
        );
    }

    calcDays(createdAt) {
        const createdTime = new Date(createdAt).getTime();
        if (Number.isNaN(createdTime)) {
            return 0;
        }
        const diff = Date.now() - createdTime;
        return Math.max(0, Math.floor(diff / this.DAY_IN_MS));
    }

    buildInfoNode(info, normalizedSlug) {
        const segments = [`注册 ${this.formatNumber(info.days)} 天`];

        if (typeof info.topicCount === 'number' && Number.isFinite(info.topicCount)) {
            segments.push(`发帖 ${this.formatNumber(info.topicCount)}`);
        }

        if (typeof info.repliesCount === 'number' && Number.isFinite(info.repliesCount)) {
            segments.push(`回帖 ${this.formatNumber(info.repliesCount)}`);
        }

        if (typeof info.trustLevel === 'number' && Number.isFinite(info.trustLevel)) {
            const FULL_TRUST_LEVEL_LABELS = {
                0: 'Lv0 新手',
                1: 'Lv1 入门',
                2: 'Lv2 成员',
                3: 'Lv3 常驻',
                4: 'Lv4 领袖',
            };
            const label = FULL_TRUST_LEVEL_LABELS[info.trustLevel] || `信任级别 Lv${info.trustLevel}`;
            segments.push(label);
        }

        if (!segments.length) {
            return null;
        }

        const span = document.createElement('span');
        span.className = 'user-reg-info';
        span.setAttribute('data-user', normalizedSlug);
        span.textContent = ` · ${segments.join(' · ')}`;
        span.style.cssText = `
            margin-left: 6px;
            font-size: 12px;
            color: #1a4c7c;
        `;

        return span;
    }

    formatNumber(value) {
        return Number(value).toLocaleString('zh-CN');
    }

    // 批量展示所有已加载的回复用户信息
    async revealAllVisibleReplies() {
        if (!this.isTopicPage()) return;
        if (this.revealInProgress) return;

        this.revealInProgress = true;

        try {
            const articles = document.querySelectorAll('.topic-post article');

            for (let index = 0; index < articles.length; index++) {
                const article = articles[index];

                // 跳过第一楼(楼主)
                const postWrapper = article.closest('.topic-post');
                const postNumber = postWrapper?.getAttribute('data-post-number');
                if (postNumber === '1') continue;

                const anchor = article.querySelector('.names a[data-user-card]');
                if (!anchor) continue;

                const slug = anchor.getAttribute('data-user-card');
                if (!slug) continue;

                const normalizedSlug = slug.trim().toLowerCase();
                const namesContainer = anchor.closest('.names');
                if (!namesContainer) continue;

                // 检查是否已经展示过
                const hasInfo = namesContainer.querySelector(`.user-reg-info[data-user="${normalizedSlug}"]`);
                if (hasInfo) {
                    // 移除可能残留的按钮
                    const button = namesContainer.querySelector(`.user-info-btn[data-user="${normalizedSlug}"]`);
                    if (button) button.remove();
                    continue;
                }

                // 加载并显示用户信息
                await this.loadAndDisplayUserInfo(anchor, slug, normalizedSlug);
            }
        } catch (error) {
            console.error('批量展示用户信息失败:', error);
        } finally {
            this.revealInProgress = false;
        }
    }
}

class BrowseController {
    constructor() {
        this.isScrolling = false;
        this.scrollInterval = null;
        this.pauseTimeout = null;
        this.trustLevelMonitorInterval = null; // 等级监控定时器
        this.navigationTimeout = null; // 导航超时定时器
        this.navigationGuardInterval = null; // 导航守护定时器

        // 使用 sessionStorage 存储窗口独立的状态
        this.accumulatedTime = this.getSessionStorage('accumulatedTime', 0);
        this.lastActionTime = Date.now();
        this.isTopicPage = window.location.href.includes("/t/topic/");
        this.autoRunning = this.getSessionStorage('autoRunning', false);
        this.topicList = this.getSessionStorage('topicList', []);

        // 使用 localStorage 存储全局共享的状态
        this.tabMode = Storage.get('tabMode', false); // 标签页切换模式
        // 如果正在自动阅读且是标签页模式,强制显示阅读标签页(标签3)
        if (this.autoRunning && this.tabMode) {
            this.activeTab = 3;
            console.log('[标签页] 自动阅读运行中,强制切换到阅读标签页');
        } else {
            this.activeTab = Storage.get('activeTab', 1); // 当前激活的标签页 (1, 2, 3, 4)
        }
        this.firstUseChecked = Storage.get('firstUseChecked', false);
        this.likesCount = Storage.get('likesCount', 0);
        this.selectedPost = Storage.get('selectedPost', null);
        this.autoLikeEnabled = Storage.get('autoLikeEnabled', false);
        this.quickLikeEnabled = Storage.get('quickLikeEnabled', false);
        this.cleanModeEnabled = Storage.get('cleanModeEnabled', false);
        this.grayscaleModeEnabled = Storage.get('grayscaleModeEnabled', false);
        this.readUnreadEnabled = Storage.get('readUnreadEnabled', false);
        this.likedTopics = Storage.get('likedTopics', []);
        this.quickLikedFloors = Storage.get('quickLikedFloors', {}); // 记录快速点赞过的楼层 {topicId: [floor1, floor2...]}
        this.panelMinimized = Storage.get('panelMinimized', false);
        this.panelPosition = Storage.get('panelPosition', { x: null, y: null });
        this.likeResumeTime = Storage.get('likeResumeTime', null);
        this.currentUsername = null; // 当前用户名
        this.lastDetectedUser = null; // 上次检测到的用户名(用于账号切换检测)
        this.readTopics = []; // 当前用户的已阅读帖子列表,初始化后会加载

        // 检查是否到达恢复点赞的时间
        this.checkLikeResumeTime();
        // 监听点赞限制弹窗
        this.observeLikeLimit();

        this.setupButton();
        this.loadUserTrustLevel(); // 加载用户信任等级
        this.loadUserReadHistory(); // 加载当前用户的阅读历史
        this.startUserSwitchMonitoring(); // 启动账号切换监控
        this.initFloorNumberDisplay();
        this.setupWindowResizeHandler(); // 设置窗口大小调整处理
        this.applyCleanModeStyles();
        this.applyGrayscaleModeStyles();
        this.initOnlyOwnerView();

        if (!this.firstUseChecked) {
            this.handleFirstUse();
        } else if (this.autoRunning) {
            if (this.isTopicPage) {
                this.startScrolling();
                if (this.autoLikeEnabled) {
                    this.autoLikeTopic();
                }
            } else {
                this.getLatestTopics().then(() => this.navigateNextTopic());
            }
        }

        // 启动导航守护程序 - 防止卡住
        this.startNavigationGuard();

        // 初始化用户信息助手 - 默认启用,让每个窗口独立工作
        this.userInfoHelper = new UserInfoHelper();

        // 启动等级监控(60秒刷新一次)- 默认启用
        this.startTrustLevelMonitor();
    }

    // 启动等级监控(60秒刷新一次)
    startTrustLevelMonitor() {
        // 如果已经有定时器在运行,先清除
        if (this.trustLevelMonitorInterval) {
            clearInterval(this.trustLevelMonitorInterval);
        }

        this.trustLevelMonitorInterval = setInterval(() => {
            console.log('自动刷新等级信息...');
            this.loadUserTrustLevel(false);
        }, 60000); // 60秒

        console.log('等级监控已启动(60秒刷新一次)');
    }

    // 停止等级监控
    stopTrustLevelMonitor() {
        if (this.trustLevelMonitorInterval) {
            clearInterval(this.trustLevelMonitorInterval);
            this.trustLevelMonitorInterval = null;
            console.log('等级监控已停止');
        }
    }

    // 启动导航守护程序 - 检测页面是否卡住
    startNavigationGuard() {
        if (this.navigationGuardInterval) {
            clearInterval(this.navigationGuardInterval);
        }

        // 记录页面加载时间
        this.pageLoadTime = Date.now();
        this.lastPageUrl = window.location.href;

        // 每5秒检查一次页面状态
        this.navigationGuardInterval = setInterval(() => {
            if (!this.autoRunning) return;

            const currentTime = Date.now();
            const timeOnPage = currentTime - this.pageLoadTime;
            const currentUrl = window.location.href;

            // 检测URL是否改变
            if (currentUrl !== this.lastPageUrl) {
                console.log('✅ 页面已跳转,重置守护定时器');
                this.pageLoadTime = currentTime;
                this.lastPageUrl = currentUrl;
                return;
            }

            // 如果在同一个文章页面停留超过60秒且正在自动运行,说明可能卡住了
            if (this.isTopicPage && timeOnPage > 60000 && !this.isScrolling) {
                console.warn('⚠️ 检测到页面可能卡住(60秒未跳转且未滚动),尝试恢复...');
                this.recoverFromStuck();
            }

            // 如果不是文章页且停留超过30秒,也可能卡住
            if (!this.isTopicPage && timeOnPage > 30000) {
                console.warn('⚠️ 检测到在非文章页卡住,尝试恢复...');
                this.recoverFromStuck();
            }
        }, 5000);

        console.log('🛡️ 导航守护程序已启动');
    }

    // 从卡住状态恢复
    async recoverFromStuck() {
        console.log('🔧 开始恢复流程...');

        // 停止当前滚动
        this.stopScrolling();

        await Utils.sleep(1000);

        // 尝试继续流程
        if (this.isTopicPage) {
            console.log('📖 在文章页,重新开始滚动');
            this.startScrolling();
        } else {
            console.log('📋 在列表页,尝试导航到下一篇');
            if (this.topicList.length === 0) {
                await this.getLatestTopics();
            }
            await this.navigateNextTopic();
        }

        // 重置页面加载时间
        this.pageLoadTime = Date.now();
    }

    // 停止导航守护
    stopNavigationGuard() {
        if (this.navigationGuardInterval) {
            clearInterval(this.navigationGuardInterval);
            this.navigationGuardInterval = null;
            console.log('🛡️ 导航守护程序已停止');
        }
    }

    // sessionStorage 辅助方法(用于窗口独立状态)
    getSessionStorage(key, defaultValue = null) {
        try {
            const value = sessionStorage.getItem(key);
            return value ? JSON.parse(value) : defaultValue;
        } catch {
            return defaultValue;
        }
    }

    setSessionStorage(key, value) {
        try {
            sessionStorage.setItem(key, JSON.stringify(value));
            return true;
        } catch (error) {
            console.error('SessionStorage error:', error);
            return false;
        }
    }

    addGlobalStyles() {
        const style = document.createElement('style');
        style.textContent = `
            :root {
                --panel-expanded-width: auto;
                --panel-minimized-size: 50px;
                --panel-edge-margin: 30px;
                --panel-border-radius: 16px;
            }

            /* Credit 积分区样式 */
            .credit-info-row {
                background: rgba(255, 255, 255, 0.15);
                padding: 8px 12px;
                border-radius: 10px;
            }

            .credit-main-stat {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 10px 12px;
                background: rgba(255, 255, 255, 0.2);
                border-radius: 8px;
                margin: 8px 0;
            }

            .credit-stat-label {
                font-size: 13px;
                color: rgba(255, 255, 255, 0.9);
            }

            .credit-stat-value {
                font-size: 20px;
                font-weight: 700;
                color: #ffd700;
                text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            }

            .credit-section-title {
                font-size: 11px;
                color: rgba(255, 255, 255, 0.7);
                margin: 10px 0 4px 0;
                padding-left: 2px;
            }

            .credit-footer {
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-top: 10px;
                padding-top: 8px;
                border-top: 1px solid rgba(255, 255, 255, 0.2);
            }

            .credit-link {
                color: rgba(255, 255, 255, 0.9) !important;
                text-decoration: none !important;
                font-size: 12px;
                transition: opacity 0.2s;
            }

            .credit-link:hover {
                opacity: 0.8;
            }

            .credit-update-time {
                font-size: 10px;
                color: rgba(255, 255, 255, 0.6);
            }

            .credit-login-btn {
                display: inline-block;
                padding: 6px 16px;
                background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
                color: white !important;
                text-decoration: none !important;
                border-radius: 6px;
                font-size: 12px;
                font-weight: 600;
                transition: all 0.2s;
                margin-top: 8px;
            }

            .credit-login-btn:hover {
                transform: translateY(-1px);
                box-shadow: 0 2px 8px rgba(72, 187, 120, 0.4);
            }

            .section-collapsible {
                cursor: pointer;
                user-select: none;
                display: flex;
                align-items: center;
                gap: 6px;
            }

            .section-collapsible .collapse-icon {
                transition: transform 0.3s;
                font-size: 10px;
            }

            .section-collapsible.collapsed .collapse-icon {
                transform: rotate(-90deg);
            }

            .section-collapsible-content {
                max-height: 1000px;
                overflow: hidden;
                transition: max-height 0.3s ease-out, opacity 0.3s ease-out;
                opacity: 1;
            }

            .section-collapsible-content.collapsed {
                max-height: 0;
                opacity: 0;
            }

            /* 当折叠区域收起时,隐藏其后的分隔线 */
            .section-collapsible.collapsed + .section-collapsible-content + .section-divider {
                display: none;
            }

            .linuxdo-helper-panel {
                position: fixed;
                right: 20px;
                top: 50%;
                transform: translateY(-50%);
                width: fit-content;
                min-width: 280px;
                max-width: 450px;
                max-height: calc(100vh - 40px);
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                border-radius: var(--panel-border-radius);
                box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
                z-index: 99999;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                overflow-y: auto;
                overflow-x: hidden;
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                backdrop-filter: blur(10px);
                will-change: transform;
            }

            /* 标签页切换布局模式 */
            .linuxdo-helper-panel.tab-mode {
                min-width: 280px;
                max-width: 320px;
            }

            /* 标签页导航栏 */
            .tab-nav {
                display: flex;
                gap: 4px;
                padding: 8px 12px;
                background: rgba(255, 255, 255, 0.1);
                border-bottom: 1px solid rgba(255, 255, 255, 0.15);
            }

            .tab-nav-btn {
                flex: 1;
                padding: 6px 10px;
                border: none;
                border-radius: 6px;
                background: rgba(255, 255, 255, 0.1);
                color: rgba(255, 255, 255, 0.7);
                font-size: 11px;
                font-weight: 500;
                cursor: pointer;
                transition: all 0.2s;
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 4px;
            }

            .tab-nav-btn:hover {
                background: rgba(255, 255, 255, 0.2);
                color: white;
            }

            .tab-nav-btn.active {
                background: rgba(255, 255, 255, 0.25);
                color: white;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
            }


            /* 标签页内容区 */
            .tab-content {
                display: none;
                padding: 12px;
                flex-direction: column;
                gap: 6px;
            }

            .tab-content.active {
                display: flex;
            }

            .tab-content-title {
                font-size: 13px;
                font-weight: 600;
                color: white;
                margin-bottom: 8px;
                padding-bottom: 6px;
                border-bottom: 1px solid rgba(255, 255, 255, 0.2);
                display: flex;
                align-items: center;
                gap: 6px;
            }

            /* 标签页模式下隐藏折叠标题和分隔线 */
            .linuxdo-helper-panel.tab-mode .section-divider,
            .linuxdo-helper-panel.tab-mode .section-collapsible {
                display: none;
            }

            /* 标签页模式下内容区始终显示 */
            .linuxdo-helper-panel.tab-mode .section-collapsible-content {
                max-height: none !important;
                opacity: 1 !important;
            }

            /* 标签页模式下隐藏默认的 panel-content */
            .linuxdo-helper-panel.tab-mode .panel-content {
                display: none;
            }

            /* 标签页容器 */
            .tab-container {
                transition: all 0.3s;
            }

            .tab-container.hidden {
                display: none !important;
            }

            /* 标签页模式下的子区域标题 */
            .tab-sub-section {
                margin-top: 10px;
                padding-top: 8px;
                border-top: 1px dashed rgba(255, 255, 255, 0.15);
            }

            .tab-sub-title {
                font-size: 11px;
                color: rgba(255, 255, 255, 0.7);
                margin-bottom: 6px;
                display: flex;
                align-items: center;
                gap: 4px;
            }

            /* 小屏幕适配 - 高度小于 800px */
            @media screen and (max-height: 800px) {
                .linuxdo-helper-panel .panel-content {
                    padding: 8px;
                    gap: 4px;
                }
                
                .linuxdo-helper-panel .toggle-row {
                    padding: 4px 8px;
                    min-height: 22px;
                }
                
                .linuxdo-helper-panel .toggle-label {
                    font-size: 11px;
                }
                
                .linuxdo-helper-panel .section-title {
                    font-size: 11px;
                    margin: 2px 0;
                }
                
                .linuxdo-helper-panel .trust-level-item {
                    font-size: 10px;
                    margin: 2px 0;
                    padding: 2px 0;
                }
                
                .linuxdo-helper-panel .main-action-btn {
                    padding: 5px 10px;
                    font-size: 12px;
                    min-height: 26px;
                }
                
                .linuxdo-helper-panel .random-floor-btn,
                .linuxdo-helper-panel .reveal-users-btn {
                    padding: 4px 8px;
                    font-size: 11px;
                    min-height: 22px;
                    margin-bottom: 3px;
                }
                
                .linuxdo-helper-panel .section-divider {
                    margin: 3px 0;
                }
                
                .linuxdo-helper-panel .trust-level-row,
                .linuxdo-helper-panel .credit-info-row {
                    padding: 5px 8px;
                    margin-top: 3px;
                }
                
                .linuxdo-helper-panel .trust-level-header {
                    font-size: 11px;
                    margin-bottom: 4px;
                }
                
                .linuxdo-helper-panel .panel-header {
                    padding: 8px 12px;
                }
                
                .linuxdo-helper-panel .panel-title {
                    font-size: 12px;
                }
                
                .linuxdo-helper-panel .toggle-switch {
                    width: 32px;
                    height: 18px;
                }
                
                .linuxdo-helper-panel .toggle-slider:before {
                    height: 12px;
                    width: 12px;
                }
                
                .linuxdo-helper-panel .toggle-switch input:checked + .toggle-slider:before {
                    transform: translateX(14px);
                }
            }

            /* 更小屏幕适配 - 高度小于 650px */
            @media screen and (max-height: 650px) {
                .linuxdo-helper-panel .panel-content {
                    padding: 6px;
                    gap: 3px;
                }
                
                .linuxdo-helper-panel .toggle-row {
                    padding: 3px 6px;
                    min-height: 20px;
                }
                
                .linuxdo-helper-panel .toggle-label {
                    font-size: 10px;
                }
                
                .linuxdo-helper-panel .section-title {
                    font-size: 10px;
                    margin: 1px 0;
                }
                
                .linuxdo-helper-panel .trust-level-item {
                    font-size: 9px;
                    margin: 1px 0;
                    padding: 1px 0;
                }
                
                .linuxdo-helper-panel .main-action-btn {
                    padding: 4px 8px;
                    font-size: 11px;
                    min-height: 24px;
                }
                
                .linuxdo-helper-panel .random-floor-btn,
                .linuxdo-helper-panel .reveal-users-btn {
                    padding: 3px 6px;
                    font-size: 10px;
                    min-height: 20px;
                    margin-bottom: 2px;
                }
                
                .linuxdo-helper-panel .section-divider {
                    margin: 2px 0;
                }
                
                .linuxdo-helper-panel .trust-level-row,
                .linuxdo-helper-panel .credit-info-row {
                    padding: 4px 6px;
                    margin-top: 2px;
                }
                
                .linuxdo-helper-panel .trust-level-header {
                    font-size: 10px;
                    margin-bottom: 3px;
                }
                
                .linuxdo-helper-panel .panel-header {
                    padding: 6px 10px;
                }
                
                .linuxdo-helper-panel .panel-title {
                    font-size: 11px;
                }
                
                .linuxdo-helper-panel .trust-level-bar {
                    width: 50px;
                    height: 5px;
                }
                
                .linuxdo-helper-panel .trust-level-value {
                    font-size: 9px;
                    min-width: 40px;
                }
                
                .linuxdo-helper-panel .toggle-switch {
                    width: 28px;
                    height: 16px;
                }
                
                .linuxdo-helper-panel .toggle-slider:before {
                    height: 10px;
                    width: 10px;
                }
                
                .linuxdo-helper-panel .toggle-switch input:checked + .toggle-slider:before {
                    transform: translateX(12px);
                }
            }

            /* 窄屏幕适配 - 宽度小于 400px */
            @media screen and (max-width: 400px) {
                .linuxdo-helper-panel {
                    min-width: 220px;
                    max-width: calc(100vw - 30px);
                    right: 10px;
                }
            }

            .linuxdo-helper-panel:hover {
                box-shadow: 0 15px 50px rgba(0, 0, 0, 0.4);
            }

            .linuxdo-helper-panel.minimized {
                width: var(--panel-minimized-size);
                height: var(--panel-minimized-size);
                min-width: var(--panel-minimized-size);
                border-radius: 50%;
                overflow: hidden;
                cursor: pointer;
                opacity: 0.7;
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            }

            .linuxdo-helper-panel.minimized:hover {
                transform: scale(1.15);
                box-shadow: 0 8px 25px rgba(102, 126, 234, 0.6);
                opacity: 1;
            }

            /* 左边展开:从左向右 */
            .linuxdo-helper-panel.on-left {
                transform-origin: left center;
            }

            /* 右边展开:从右向左 */
            .linuxdo-helper-panel.on-right {
                transform-origin: right center;
            }

            .panel-header {
                background: rgba(255, 255, 255, 0.15);
                padding: 12px 16px;
                cursor: move;
                display: flex;
                justify-content: space-between;
                align-items: center;
                user-select: none;
                border-bottom: 1px solid rgba(255, 255, 255, 0.2);
                transition: opacity 0.3s;
            }

            .linuxdo-helper-panel.minimized .panel-header {
                opacity: 0;
                pointer-events: none;
                padding: 0;
                height: 0;
                overflow: hidden;
            }

            .panel-header:active {
                cursor: grabbing;
            }

            .panel-title {
                color: white;
                font-weight: 600;
                font-size: 14px;
                text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            }

            .panel-controls {
                display: flex;
                gap: 8px;
            }

            .panel-control-btn {
                width: 24px;
                height: 24px;
                border-radius: 6px;
                border: none;
                background: rgba(255, 255, 255, 0.2);
                color: white;
                cursor: pointer;
                font-size: 14px;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.2s;
                padding: 0;
                line-height: 1;
            }

            .panel-control-btn:hover {
                background: rgba(255, 255, 255, 0.3);
                transform: scale(1.1);
            }

            .panel-control-btn:active {
                transform: scale(0.95);
            }

            .minimized-icon {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                display: none;
                align-items: center;
                justify-content: center;
                pointer-events: none;
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                font-size: 20px;
                font-weight: 700;
                color: white;
                text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
                letter-spacing: -1px;
            }

            .linuxdo-helper-panel.minimized .minimized-icon {
                display: flex;
            }

            .linuxdo-helper-panel.minimized:hover .minimized-icon {
                transform: scale(1.1);
                text-shadow: 0 3px 8px rgba(255, 255, 255, 0.6);
            }

            .panel-content {
                padding: 12px;
                display: flex;
                flex-direction: column;
                gap: 6px;
                transition: all 0.3s;
                overflow: hidden;
                width: 100%;
                box-sizing: border-box;
            }

            /* 布局切换按钮 */
            .layout-toggle-btn {
                width: 24px;
                height: 24px;
                border-radius: 6px;
                border: none;
                background: rgba(255, 255, 255, 0.2);
                color: white;
                cursor: pointer;
                font-size: 12px;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.2s;
                padding: 0;
                line-height: 1;
            }

            .layout-toggle-btn:hover {
                background: rgba(255, 255, 255, 0.3);
                transform: scale(1.1);
            }

            .layout-toggle-btn:active {
                transform: scale(0.95);
            }

            .panel-content.hidden {
                max-height: 0;
                padding: 0;
                opacity: 0;
            }

            .linuxdo-helper-panel.minimized .panel-content {
                display: none;
            }

            .main-action-btn {
                width: 100%;
                padding: 8px 12px;
                font-size: 13px;
                font-weight: 600;
                background: white;
                color: #667eea;
                border: none;
                border-radius: 8px;
                cursor: pointer;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 5px;
                white-space: nowrap;
                overflow: hidden;
                min-height: 32px;
                line-height: 1.1;
            }

            .main-action-btn .btn-text {
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                flex: 1;
                min-width: 0;
            }

            .main-action-btn .btn-icon {
                flex-shrink: 0;
                font-size: 14px;
            }

            .main-action-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
            }

            .main-action-btn:active {
                transform: translateY(0);
            }

            .main-action-btn.running {
                background: #ff6b6b;
                color: white;
            }

            .btn-icon {
                font-size: 18px;
            }

            .trust-level-row {
                background: rgba(255, 255, 255, 0.15);
                padding: 8px 12px;
                border-radius: 10px;
                margin-top: 8px;
            }

            .trust-level-header {
                color: white;
                font-size: 13px;
                font-weight: 600;
                margin-bottom: 6px;
                text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .trust-level-refresh {
                background: rgba(255, 255, 255, 0.2);
                border: none;
                color: white;
                padding: 4px 8px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 11px;
                transition: all 0.2s;
            }

            .trust-level-refresh:hover {
                background: rgba(255, 255, 255, 0.3);
                transform: scale(1.05);
            }

            .trust-level-refresh:disabled {
                opacity: 0.5;
                cursor: not-allowed;
            }

            .trust-level-item {
                display: flex;
                justify-content: space-between;
                align-items: center;
                color: rgba(255, 255, 255, 0.9);
                font-size: 11px;
                margin: 4px 0;
                padding: 3px 0;
                white-space: nowrap;
            }

            .trust-level-name {
                flex: 1;
                margin-right: 8px;
                white-space: nowrap;
            }

            .trust-level-progress {
                display: flex;
                align-items: center;
                gap: 6px;
            }

            .trust-level-bar {
                width: 60px;
                height: 6px;
                background: rgba(255, 255, 255, 0.2);
                border-radius: 3px;
                overflow: hidden;
            }

            .trust-level-bar-fill {
                height: 100%;
                background: linear-gradient(90deg, #48bb78 0%, #68d391 100%);
                transition: width 0.3s;
            }

            .trust-level-bar-fill.completed {
                background: linear-gradient(90deg, #4299e1 0%, #63b3ed 100%);
            }

            .trust-level-value {
                font-size: 10px;
                color: rgba(255, 255, 255, 0.8);
                min-width: 50px;
                text-align: right;
            }

            .trust-level-loading {
                color: rgba(255, 255, 255, 0.7);
                font-size: 11px;
                text-align: center;
                padding: 8px 0;
            }

            .random-floor-btn, .reveal-users-btn {
                width: 100%;
                padding: 7px 12px;
                font-size: 12px;
                font-weight: 600;
                background: rgba(255, 255, 255, 0.95);
                color: #667eea;
                border: none;
                border-radius: 8px;
                cursor: pointer;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 6px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                min-height: 28px;
                line-height: 1.2;
                margin-bottom: 6px;
            }

            .reveal-users-btn {
                margin-bottom: 0;
            }

            .random-floor-btn .btn-text,
            .reveal-users-btn .btn-text {
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                flex: 1;
                min-width: 0;
            }

            .random-floor-btn .btn-icon,
            .reveal-users-btn .btn-icon {
                flex-shrink: 0;
                font-size: 13px;
            }

            .random-floor-btn:hover, .reveal-users-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
                background: rgba(255, 255, 255, 1);
            }

            .random-floor-btn:active, .reveal-users-btn:active {
                transform: translateY(0);
            }

            .reveal-users-btn:disabled {
                opacity: 0.6;
                cursor: not-allowed;
                transform: none !important;
            }

            .toggle-row {
                background: rgba(255, 255, 255, 0.15);
                padding: 5px 10px;
                border-radius: 8px;
                display: flex;
                justify-content: space-between;
                align-items: center;
                transition: all 0.2s;
                min-height: 26px;
            }

            .toggle-row:hover {
                background: rgba(255, 255, 255, 0.22);
            }

            .toggle-label {
                color: white;
                font-size: 12px;
                font-weight: 500;
                text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
            }

            .toggle-switch {
                position: relative;
                width: 36px;
                height: 20px;
                flex-shrink: 0;
            }

            .toggle-switch input {
                opacity: 0;
                width: 0;
                height: 0;
            }

            .toggle-slider {
                position: absolute;
                cursor: pointer;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(255, 255, 255, 0.3);
                transition: 0.3s;
                border-radius: 26px;
            }

            .toggle-slider:before {
                position: absolute;
                content: "";
                height: 14px;
                width: 14px;
                left: 3px;
                bottom: 3px;
                background-color: white;
                transition: 0.3s;
                border-radius: 50%;
                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            }

            .toggle-switch input:checked + .toggle-slider {
                background-color: rgba(76, 175, 80, 0.8);
            }

            .toggle-switch input:checked + .toggle-slider:before {
                transform: translateX(16px);
            }

            .section-divider {
                height: 1px;
                background: rgba(255, 255, 255, 0.2);
                margin: 6px 0;
            }

            .section-title {
                color: rgba(255, 255, 255, 0.9);
                font-size: 12px;
                font-weight: 600;
                margin: 4px 0 4px 0;
                padding: 0 4px;
                text-transform: uppercase;
                letter-spacing: 0.5px;
            }

            @keyframes fadeIn {
                from {
                    opacity: 0;
                    transform: scale(0.8);
                }
                to {
                    opacity: 1;
                    transform: scale(1);
                }
            }

            .linuxdo-helper-panel {
                animation: fadeIn 0.3s ease-out;
            }
        `;
        document.head.appendChild(style);
    }

    setupButton() {
        this.addGlobalStyles();

        // 创建主容器
        this.container = document.createElement("div");
        this.container.className = "linuxdo-helper-panel";
        if (this.panelMinimized) {
            this.container.classList.add('minimized');
        }

        // 如果有保存的位置,使用保存的位置;否则默认右上角
        if (this.panelPosition.x !== null && this.panelPosition.y !== null) {
            this.applyPanelPosition(this.panelPosition.x, this.panelPosition.y);
        } else {
            // 默认位置:右上角
            const defaultX = window.innerWidth - 300; // 280px 宽度 + 20px 边距
            const defaultY = 20;
            this.applyPanelPosition(defaultX, defaultY);
        }

        // 创建最小化图标 - 使用简洁的文字标识
        const minimizedIcon = document.createElement("div");
        minimizedIcon.className = "minimized-icon";
        minimizedIcon.textContent = "助手";
        minimizedIcon.title = "点击展开控制面板";

        // 创建面板头部
        const header = document.createElement("div");
        header.className = "panel-header";
        // 根据当前布局模式显示不同的图标:标签页模式显示 ≡(切换到折叠),折叠模式显示 ⫼(切换到标签页)
        const layoutIcon = this.tabMode ? '≡' : '⫼';
        const layoutTitle = this.tabMode ? '切换到折叠布局' : '切换到标签页布局';
        header.innerHTML = `
            <span class="panel-title">📚 Linux.do 助手</span>
            <div class="panel-controls">
                <button class="panel-control-btn layout-toggle-btn" title="${layoutTitle}">${layoutIcon}</button>
                <button class="panel-control-btn minimize-btn" title="最小化">─</button>
            </div>
        `;

        // 创建面板内容区
        const content = document.createElement("div");
        content.className = "panel-content";
        if (this.panelMinimized) {
            content.classList.add('hidden');
        }

        // 应用标签页布局模式
        if (this.tabMode) {
            this.container.classList.add('tab-mode');
        }

        // 主按钮
        this.button = document.createElement("button");
        this.button.className = "main-action-btn" + (this.autoRunning ? " running" : "");
        this.button.innerHTML = this.autoRunning
            ? '<span class="btn-icon">⏸</span><span class="btn-text">停止阅读</span>'
            : '<span class="btn-icon">▶</span><span class="btn-text">开始阅读</span>';
        this.button.addEventListener("click", () => this.handleButtonClick());

        // 随机楼层按钮
        this.randomBtn = document.createElement("button");
        this.randomBtn.className = "random-floor-btn";
        this.randomBtn.innerHTML = '<span class="btn-icon">🎲</span><span class="btn-text">随机楼层</span>';
        this.randomBtn.addEventListener("click", () => this.randomJump());
        this.randomBtn.style.display = this.isTopicPage ? 'flex' : 'none';
        this.randomBtn.title = '随机跳转到某个楼层(抽奖用)';

        // 批量展示用户信息按钮
        this.revealUsersBtn = document.createElement("button");
        this.revealUsersBtn.className = "reveal-users-btn";
        this.revealUsersBtn.innerHTML = '<span class="btn-icon">📊</span><span class="btn-text">批量展示信息</span>';
        this.revealUsersBtn.addEventListener("click", () => this.handleRevealUsersClick());
        this.revealUsersBtn.style.display = this.isTopicPage ? 'flex' : 'none';
        this.revealUsersBtn.title = '批量展示当前页面所有已加载回复的用户信息';

        // 自动点赞开关
        const autoLikeRow = this.createToggleRow(
            "👍 自动点赞主题",
            this.autoLikeEnabled,
            (checked) => {
                // 检查是否在冷却期
                if (checked && this.likeResumeTime && Date.now() < this.likeResumeTime) {
                    const now = Date.now();
                    const remainingHours = Math.ceil((this.likeResumeTime - now) / (1000 * 60 * 60));
                    const resumeDate = new Date(this.likeResumeTime);
                    this.showNotification(`点赞功能冷却中,将在 ${resumeDate.toLocaleTimeString()} 恢复`);
                    console.log(`点赞冷却中,还需约 ${remainingHours} 小时,无法开启`);

                    // 恢复开关状态为关闭
                    setTimeout(() => {
                        const toggleRows = this.container.querySelectorAll('.toggle-row');
                        for (const row of toggleRows) {
                            const label = row.querySelector('.toggle-label');
                            if (label && label.textContent.includes('自动点赞')) {
                                const input = row.querySelector('input[type="checkbox"]');
                                if (input) {
                                    input.checked = false;
                                }
                                break;
                            }
                        }
                    }, 100);
                    return;
                }

                // 互斥逻辑:如果开启自动点赞,关闭快速点赞
                if (checked && this.quickLikeEnabled) {
                    this.quickLikeEnabled = false;
                    Storage.set('quickLikeEnabled', false);
                    // 更新快速点赞开关UI
                    const toggleRows = this.container.querySelectorAll('.toggle-row');
                    for (const row of toggleRows) {
                        const label = row.querySelector('.toggle-label');
                        if (label && label.textContent.includes('快速点赞')) {
                            const input = row.querySelector('input[type="checkbox"]');
                            if (input) {
                                input.checked = false;
                            }
                            break;
                        }
                    }
                }

                this.autoLikeEnabled = checked;
                Storage.set('autoLikeEnabled', this.autoLikeEnabled);
                console.log(`自动点赞主题: ${this.autoLikeEnabled ? '开启' : '关闭'}`);
                if (this.autoLikeEnabled && this.isTopicPage) {
                    this.autoLikeTopic();
                }
            }
        );

        // 快速点赞开关
        const quickLikeRow = this.createToggleRow(
            "⚡ 快速点赞回复",
            this.quickLikeEnabled,
            (checked) => {
                // 检查是否在冷却期
                if (checked && this.likeResumeTime && Date.now() < this.likeResumeTime) {
                    const resumeDate = new Date(this.likeResumeTime);
                    this.showNotification(`点赞功能冷却中,将在 ${resumeDate.toLocaleTimeString()} 恢复`);

                    // 恢复开关状态为关闭
                    setTimeout(() => {
                        const toggleRows = this.container.querySelectorAll('.toggle-row');
                        for (const row of toggleRows) {
                            const label = row.querySelector('.toggle-label');
                            if (label && label.textContent.includes('快速点赞')) {
                                const input = row.querySelector('input[type="checkbox"]');
                                if (input) {
                                    input.checked = false;
                                }
                                break;
                            }
                        }
                    }, 100);
                    return;
                }

                // 互斥逻辑:如果开启快速点赞,关闭自动点赞
                if (checked && this.autoLikeEnabled) {
                    this.autoLikeEnabled = false;
                    Storage.set('autoLikeEnabled', false);
                    // 更新自动点赞开关UI
                    const toggleRows = this.container.querySelectorAll('.toggle-row');
                    for (const row of toggleRows) {
                        const label = row.querySelector('.toggle-label');
                        if (label && label.textContent.includes('自动点赞主题')) {
                            const input = row.querySelector('input[type="checkbox"]');
                            if (input) {
                                input.checked = false;
                            }
                            break;
                        }
                    }
                }

                this.quickLikeEnabled = checked;
                Storage.set('quickLikeEnabled', this.quickLikeEnabled);
                console.log(`快速点赞回复: ${this.quickLikeEnabled ? '开启' : '关闭'}`);
                if (this.quickLikeEnabled && this.isTopicPage) {
                    console.log("[调试] 条件满足,准备调用 quickLikeReplies()");
                    this.quickLikeReplies();
                }
            }
        );

        // 清爽模式开关
        const cleanModeRow = this.createToggleRow(
            "✨ 清爽模式",
            this.cleanModeEnabled,
            (checked) => {
                this.cleanModeEnabled = checked;
                Storage.set('cleanModeEnabled', this.cleanModeEnabled);
                console.log(`清爽模式: ${this.cleanModeEnabled ? '开启' : '关闭'}`);
                this.toggleCleanMode();
            }
        );

        // 黑白灰模式开关
        const grayscaleModeRow = this.createToggleRow(
            "🎨 黑白灰模式",
            this.grayscaleModeEnabled,
            (checked) => {
                this.grayscaleModeEnabled = checked;
                Storage.set('grayscaleModeEnabled', this.grayscaleModeEnabled);
                console.log(`黑白灰模式: ${this.grayscaleModeEnabled ? '开启' : '关闭'}`);
                this.toggleGrayscaleMode();
            }
        );

        // 读取未读帖子开关
        const readUnreadRow = this.createToggleRow(
            "📬 读取未读帖子",
            this.readUnreadEnabled,
            (checked) => {
                this.readUnreadEnabled = checked;
                Storage.set('readUnreadEnabled', this.readUnreadEnabled);
                console.log(`读取未读帖子: ${this.readUnreadEnabled ? '开启' : '关闭'}`);

                // 切换模式时清空话题列表,强制重新获取
                this.topicList = [];
                this.setSessionStorage('topicList', []);
                console.log('已清空话题列表,下次将获取' + (this.readUnreadEnabled ? '未读' : '最新') + '帖子');
            }
        );

        // 清除点赞冷却按钮
        this.clearCooldownBtn = document.createElement("button");
        this.clearCooldownBtn.className = "reveal-users-btn";
        this.clearCooldownBtn.innerHTML = '<span class="btn-icon">🔥</span><span class="btn-text">清除冷却</span>';
        this.clearCooldownBtn.addEventListener("click", () => this.handleClearCooldown());
        this.clearCooldownBtn.title = '清除点赞冷却时间,立即恢复点赞功能';
        this.clearCooldownBtn.style.background = 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)';
        this.clearCooldownBtn.style.display = 'none'; // 默认隐藏
        
        // 按钮创建后立即更新冷却显示状态
        setTimeout(() => this.updateClearCooldownButton(), 0);

        // 信任等级显示容器
        this.trustLevelContainer = document.createElement("div");
        this.trustLevelContainer.className = "trust-level-row";
        this.trustLevelContainer.innerHTML = '<div class="trust-level-loading">加载等级信息...</div>';

        // 组装面板 - 根据布局模式选择不同的组装方式
        if (this.tabMode) {
            // ========== 标签页切换布局模式 ==========
            // 创建标签页容器(包含导航和内容)
            this.tabContainer = document.createElement("div");
            this.tabContainer.className = "tab-container";
            if (this.panelMinimized) {
                this.tabContainer.classList.add('hidden');
            }
            
            // 创建标签页导航栏
            const tabNav = document.createElement("div");
            tabNav.className = "tab-nav";
            
            // 标签1:账号信息
            const tab1Btn = document.createElement("button");
            tab1Btn.className = "tab-nav-btn" + (this.activeTab === 1 ? " active" : "");
            tab1Btn.innerHTML = '📊 账号';
            tab1Btn.addEventListener("click", () => this.switchTab(1));
            tabNav.appendChild(tab1Btn);
            
            // 标签2:积分
            const tab2Btn = document.createElement("button");
            tab2Btn.className = "tab-nav-btn" + (this.activeTab === 2 ? " active" : "");
            tab2Btn.innerHTML = '💰 积分';
            tab2Btn.addEventListener("click", () => this.switchTab(2));
            tabNav.appendChild(tab2Btn);
            
            // 标签3:自动阅读
            const tab3Btn = document.createElement("button");
            tab3Btn.className = "tab-nav-btn" + (this.activeTab === 3 ? " active" : "");
            tab3Btn.innerHTML = '📖 阅读';
            tab3Btn.addEventListener("click", () => this.switchTab(3));
            tabNav.appendChild(tab3Btn);
            
            // 标签4:功能(模式设置 + 文章页功能)
            const tab4Btn = document.createElement("button");
            tab4Btn.className = "tab-nav-btn" + (this.activeTab === 4 ? " active" : "");
            tab4Btn.innerHTML = '⚙️ 功能';
            tab4Btn.addEventListener("click", () => this.switchTab(4));
            tabNav.appendChild(tab4Btn);
            
            this.tabContainer.appendChild(tabNav);
            this.tabNav = tabNav;
            
            // ========== 标签页1内容:账号信息 ==========
            const tab1Content = document.createElement("div");
            tab1Content.className = "tab-content" + (this.activeTab === 1 ? " active" : "");
            tab1Content.setAttribute("data-tab", "1");
            tab1Content.innerHTML = '<div class="tab-content-title">📊 账号信息</div>';
            tab1Content.appendChild(this.trustLevelContainer);
            this.tabContainer.appendChild(tab1Content);
            
            // ========== 标签页2内容:积分 ==========
            const tab2Content = document.createElement("div");
            tab2Content.className = "tab-content" + (this.activeTab === 2 ? " active" : "");
            tab2Content.setAttribute("data-tab", "2");
            
            if (CURRENT_DOMAIN === 'linux.do') {
                tab2Content.innerHTML = '<div class="tab-content-title">💰 Credit 积分</div>';
                // Credit 容器
                this.creditContainer = document.createElement("div");
                this.creditContainer.className = "credit-info-row";
                this.creditContainer.innerHTML = '<div class="trust-level-loading">加载积分...</div>';
                tab2Content.appendChild(this.creditContainer);
                // 标签页模式下,切换到该标签时加载积分
                if (this.activeTab === 2) {
                    setTimeout(() => this.loadCreditInfo(), 500);
                }
            } else {
                // 非 linux.do 站点,显示提示
                tab2Content.innerHTML = '<div class="tab-content-title">💰 积分</div>';
                tab2Content.innerHTML += '<div style="color: rgba(255,255,255,0.7); font-size: 12px; padding: 10px;">当前站点不支持积分功能</div>';
            }
            this.tabContainer.appendChild(tab2Content);
            
            // ========== 标签页3内容:自动阅读 ==========
            const tab3Content = document.createElement("div");
            tab3Content.className = "tab-content" + (this.activeTab === 3 ? " active" : "");
            tab3Content.setAttribute("data-tab", "3");
            tab3Content.innerHTML = '<div class="tab-content-title">📖 自动阅读</div>';
            tab3Content.appendChild(this.button);
            tab3Content.appendChild(autoLikeRow);
            tab3Content.appendChild(quickLikeRow);
            tab3Content.appendChild(this.clearCooldownBtn);
            tab3Content.appendChild(readUnreadRow);
            this.tabContainer.appendChild(tab3Content);
            
            // ========== 标签页4内容:功能(模式设置 + 文章页功能) ==========
            const tab4Content = document.createElement("div");
            tab4Content.className = "tab-content" + (this.activeTab === 4 ? " active" : "");
            tab4Content.setAttribute("data-tab", "4");
            tab4Content.innerHTML = '<div class="tab-content-title">⚙️ 功能设置</div>';
            
            // 模式设置
            const settingsSubSection = document.createElement("div");
            settingsSubSection.innerHTML = '<div class="tab-sub-title">🎨 模式设置</div>';
            settingsSubSection.appendChild(cleanModeRow);
            settingsSubSection.appendChild(grayscaleModeRow);
            tab4Content.appendChild(settingsSubSection);
            
            // 文章页功能(仅在文章页显示)
            if (this.isTopicPage) {
                const toolSubSection = document.createElement("div");
                toolSubSection.className = "tab-sub-section";
                toolSubSection.innerHTML = '<div class="tab-sub-title">📖 文章页功能</div>';
                toolSubSection.appendChild(this.randomBtn);
                toolSubSection.appendChild(this.revealUsersBtn);
                tab4Content.appendChild(toolSubSection);
            }
            
            this.tabContainer.appendChild(tab4Content);
            
            // 保存标签页内容引用
            this.tab1Content = tab1Content;
            this.tab2Content = tab2Content;
            this.tab3Content = tab3Content;
            this.tab4Content = tab4Content;
        } else {
            // ========== 单列折叠布局模式(默认) ==========
            // 📖 自动阅读区(包含阅读按钮和相关设置)
            const autoSection = document.createElement("div");
            autoSection.className = "section-collapsible";
            autoSection.innerHTML = '<div class="section-title"><span class="collapse-icon">▼</span> 📖 自动阅读</div>';
            content.appendChild(autoSection);

            // 自动阅读内容区
            this.autoSectionContent = document.createElement("div");
            this.autoSectionContent.className = "section-collapsible-content";
            // 根据运行状态决定初始折叠状态:停止时折叠,运行时展开
            if (!this.autoRunning) {
                autoSection.classList.add('collapsed');
                this.autoSectionContent.classList.add('collapsed');
            }

            this.autoSectionContent.appendChild(this.button);
            this.autoSectionContent.appendChild(autoLikeRow);
            this.autoSectionContent.appendChild(quickLikeRow);
            this.autoSectionContent.appendChild(this.clearCooldownBtn);
            this.autoSectionContent.appendChild(readUnreadRow);
            content.appendChild(this.autoSectionContent);

            // 自动阅读区折叠点击事件
            autoSection.addEventListener('click', () => {
                autoSection.classList.toggle('collapsed');
                this.autoSectionContent.classList.toggle('collapsed');
            });

            // 分隔线1
            this.divider1 = document.createElement("div");
            this.divider1.className = "section-divider";
            content.appendChild(this.divider1);

            // ⚙️ 模式设置区(清爽模式、黑白灰模式,默认折叠)
            const settingsSection = document.createElement("div");
            settingsSection.className = "section-collapsible collapsed";
            settingsSection.innerHTML = '<div class="section-title"><span class="collapse-icon">▼</span> ⚙️ 模式设置</div>';
            content.appendChild(settingsSection);

            // 设置内容区(默认折叠)
            this.settingsSectionContent = document.createElement("div");
            this.settingsSectionContent.className = "section-collapsible-content collapsed";
            this.settingsSectionContent.appendChild(cleanModeRow);
            this.settingsSectionContent.appendChild(grayscaleModeRow);
            content.appendChild(this.settingsSectionContent);

            // 设置区折叠点击事件
            settingsSection.addEventListener('click', () => {
                settingsSection.classList.toggle('collapsed');
                this.settingsSectionContent.classList.toggle('collapsed');
            });

            // 分隔线2
            this.divider2 = document.createElement("div");
            this.divider2.className = "section-divider";
            content.appendChild(this.divider2);

            // 📖 文章页功能区(只在文章页显示,默认折叠)
            this.toolSectionContainer = document.createElement("div");
            this.toolSectionContainer.className = "tool-section-container";

            const toolSection = document.createElement("div");
            toolSection.className = "section-collapsible collapsed";
            toolSection.innerHTML = '<div class="section-title"><span class="collapse-icon">▼</span> 📖 文章页功能</div>';
            this.toolSectionContainer.appendChild(toolSection);

            // 文章页功能内容区(默认折叠)
            this.toolSectionContent = document.createElement("div");
            this.toolSectionContent.className = "section-collapsible-content collapsed";
            this.toolSectionContent.appendChild(this.randomBtn);
            this.toolSectionContent.appendChild(this.revealUsersBtn);
            this.toolSectionContainer.appendChild(this.toolSectionContent);

            // 文章页功能区折叠点击事件
            toolSection.addEventListener('click', () => {
                toolSection.classList.toggle('collapsed');
                this.toolSectionContent.classList.toggle('collapsed');
            });

            content.appendChild(this.toolSectionContainer);

            // 分隔线3
            this.divider3 = document.createElement("div");
            this.divider3.className = "section-divider";
            content.appendChild(this.divider3);

            // 📊 账号信息区
            this.accountSection = document.createElement("div");
            this.accountSection.className = "section-collapsible";
            // 如果正在自动阅读,默认折叠账号信息区
            if (this.autoRunning) {
                this.accountSection.classList.add('collapsed');
            }
            this.accountSection.innerHTML = '<div class="section-title"><span class="collapse-icon">▼</span> 📊 账号信息</div>';
            content.appendChild(this.accountSection);

            // 账号信息内容区(根据自动阅读状态决定是否折叠)
            this.accountSectionContent = document.createElement("div");
            this.accountSectionContent.className = "section-collapsible-content";
            if (this.autoRunning) {
                this.accountSectionContent.classList.add('collapsed');
            }
            this.accountSectionContent.appendChild(this.trustLevelContainer);
            content.appendChild(this.accountSectionContent);

            // 账号信息区折叠点击事件
            this.accountSection.addEventListener('click', () => {
                this.accountSection.classList.toggle('collapsed');
                this.accountSectionContent.classList.toggle('collapsed');
            });

            // 💰 Credit 积分区(仅 linux.do 显示)
            if (CURRENT_DOMAIN === 'linux.do') {
                // 分隔线4
                this.divider4 = document.createElement("div");
                this.divider4.className = "section-divider";
                content.appendChild(this.divider4);

                const creditSection = document.createElement("div");
                creditSection.className = "section-collapsible collapsed";
                creditSection.innerHTML = '<div class="section-title"><span class="collapse-icon">▼</span> 💰 Credit 积分</div>';
                content.appendChild(creditSection);

                // Credit 内容区(默认折叠)
                this.creditSectionContent = document.createElement("div");
                this.creditSectionContent.className = "section-collapsible-content collapsed";

                // Credit 容器
                this.creditContainer = document.createElement("div");
                this.creditContainer.className = "credit-info-row";
                this.creditContainer.innerHTML = '<div class="trust-level-loading">点击展开加载积分...</div>';
                this.creditSectionContent.appendChild(this.creditContainer);
                content.appendChild(this.creditSectionContent);

                // Credit 区折叠点击事件
                creditSection.addEventListener('click', () => {
                    creditSection.classList.toggle('collapsed');
                    this.creditSectionContent.classList.toggle('collapsed');
                    // 展开时加载数据
                    if (!creditSection.classList.contains('collapsed')) {
                        this.loadCreditInfo();
                    }
                });
            }
        }

        this.container.appendChild(minimizedIcon);
        this.container.appendChild(header);
        // 根据布局模式添加不同的内容容器
        if (this.tabMode) {
            this.container.appendChild(this.tabContainer);
        } else {
            this.container.appendChild(content);
        }
        document.body.appendChild(this.container);

        // 添加拖动功能(只在展开状态可拖动)
        this.makeDraggable(header);

        // 添加布局切换功能
        header.querySelector('.layout-toggle-btn').addEventListener('click', (e) => {
            e.stopPropagation();
            this.toggleLayout();
        });

        // 添加最小化功能
        header.querySelector('.minimize-btn').addEventListener('click', (e) => {
            e.stopPropagation();
            this.toggleMinimize();
        });

        // 点击最小化图标展开
        minimizedIcon.addEventListener('click', (e) => {
            e.stopPropagation();
            if (this.panelMinimized) {
                this.toggleMinimize();
            }
        });

        // 点击最小化的面板也可以展开
        this.container.addEventListener('click', (e) => {
            if (this.panelMinimized && e.target === this.container) {
                this.toggleMinimize();
            }
        });

        // 给最小化面板添加拖动功能
        this.makeMinimizedDraggable();
    }

    createToggleRow(label, checked, onChange) {
        const row = document.createElement("div");
        row.className = "toggle-row";

        const labelEl = document.createElement("span");
        labelEl.className = "toggle-label";
        labelEl.textContent = label;

        const toggleSwitch = document.createElement("label");
        toggleSwitch.className = "toggle-switch";

        const input = document.createElement("input");
        input.type = "checkbox";
        input.checked = checked;
        input.addEventListener("change", (e) => {
            onChange(e.target.checked);
        });

        const slider = document.createElement("span");
        slider.className = "toggle-slider";

        toggleSwitch.appendChild(input);
        toggleSwitch.appendChild(slider);

        row.appendChild(labelEl);
        row.appendChild(toggleSwitch);

        return row;
    }

    // 应用面板位置(带吸附效果)
    applyPanelPosition(x, y, snap = false) {
        let finalX = x;
        let finalY = y;

        if (snap) {
            // 吸附逻辑:判断靠近哪一边
            const windowWidth = window.innerWidth;
            const edgeMargin = 30; // 使用统一的边距变量
            const panelWidth = this.panelMinimized ? 50 : (this.container.offsetWidth || 280);
            const centerX = windowWidth / 2;

            // 判断在左边还是右边
            const isOnLeft = x < centerX;

            // 如果在左半边,吸附到左边;否则吸附到右边
            if (isOnLeft) {
                finalX = edgeMargin;
                this.container.classList.add('on-left');
                this.container.classList.remove('on-right');
            } else {
                finalX = windowWidth - panelWidth - edgeMargin;
                this.container.classList.add('on-right');
                this.container.classList.remove('on-left');
            }

            // Y 轴始终吸附到顶部
            finalY = 70;
        }

        // 应用位置
        this.container.style.position = 'fixed';
        this.container.style.left = finalX + 'px';
        this.container.style.top = finalY + 'px';
        this.container.style.right = 'auto';
        this.container.style.bottom = 'auto';
        this.container.style.transform = 'none';

        // 保存当前位置
        this.currentTranslateX = finalX;
        this.currentTranslateY = finalY;

        return { x: finalX, y: finalY };
    }

    makeDraggable(header) {
        let isDragging = false;
        let hasMoved = false;
        let currentX;
        let currentY;
        let initialX;
        let initialY;
        let rafId = null;

        // 禁用过渡效果以提高拖动流畅度
        const disableTransition = () => {
            this.container.style.transition = 'none';
        };

        const enableTransition = () => {
            this.container.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
        };

        header.addEventListener('mousedown', (e) => {
            if (e.target.classList.contains('panel-control-btn') ||
                e.target.closest('.panel-control-btn')) {
                return;
            }

            isDragging = true;
            hasMoved = false;
            disableTransition();

            const rect = this.container.getBoundingClientRect();
            initialX = e.clientX - rect.left;
            initialY = e.clientY - rect.top;

            // 使用捕获阶段,提高响应速度
            document.addEventListener('mousemove', onMouseMove, true);
            document.addEventListener('mouseup', onMouseUp, true);

            // 防止文本选择
            e.preventDefault();
        });

        const updatePosition = () => {
            // 限制在视窗内
            const maxX = window.innerWidth - this.container.offsetWidth;
            const maxY = window.innerHeight - this.container.offsetHeight;

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

            // 实时更新位置(拖动时不吸附)
            this.container.style.position = 'fixed';
            this.container.style.left = currentX + 'px';
            this.container.style.top = currentY + 'px';
            this.container.style.right = 'auto';
            this.container.style.bottom = 'auto';
            this.container.style.transform = 'none';
        };

        const onMouseMove = (e) => {
            if (!isDragging) return;

            e.preventDefault();
            e.stopPropagation();

            hasMoved = true;
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;

            // 使用 requestAnimationFrame 确保流畅渲染
            if (rafId) {
                cancelAnimationFrame(rafId);
            }
            rafId = requestAnimationFrame(updatePosition);
        };

        const onMouseUp = () => {
            if (isDragging) {
                isDragging = false;
                enableTransition();

                // 取消未完成的动画帧
                if (rafId) {
                    cancelAnimationFrame(rafId);
                    rafId = null;
                }

                // 只有在真正移动过才吸附
                if (hasMoved) {
                    // 松开鼠标时吸附到最近的边角
                    const snappedPos = this.applyPanelPosition(currentX, currentY, true);

                    // 保存吸附后的位置
                    this.panelPosition = snappedPos;
                    Storage.set('panelPosition', this.panelPosition);
                }
            }
            document.removeEventListener('mousemove', onMouseMove, true);
            document.removeEventListener('mouseup', onMouseUp, true);
        };
    }

    makeMinimizedDraggable() {
        let isDragging = false;
        let hasMoved = false;
        let currentX;
        let currentY;
        let initialX;
        let initialY;
        let rafId = null;

        this.container.addEventListener('mousedown', (e) => {
            // 只在最小化状态下才能拖动整个容器
            if (!this.panelMinimized) return;

            isDragging = true;
            hasMoved = false;
            this.container.style.transition = 'none';

            const rect = this.container.getBoundingClientRect();
            initialX = e.clientX - rect.left;
            initialY = e.clientY - rect.top;

            document.addEventListener('mousemove', onMouseMove, true);
            document.addEventListener('mouseup', onMouseUp, true);

            e.preventDefault();
            e.stopPropagation();
        });

        const updatePosition = () => {
            const maxX = window.innerWidth - 50;
            const maxY = window.innerHeight - 50;

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

            this.container.style.position = 'fixed';
            this.container.style.left = currentX + 'px';
            this.container.style.top = currentY + 'px';
            this.container.style.right = 'auto';
            this.container.style.bottom = 'auto';
            this.container.style.transform = 'none';
        };

        const onMouseMove = (e) => {
            if (!isDragging) return;

            e.preventDefault();
            e.stopPropagation();

            hasMoved = true;
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;

            if (rafId) {
                cancelAnimationFrame(rafId);
            }
            rafId = requestAnimationFrame(updatePosition);
        };

        const onMouseUp = (e) => {
            if (isDragging) {
                isDragging = false;
                this.container.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';

                if (rafId) {
                    cancelAnimationFrame(rafId);
                    rafId = null;
                }

                if (hasMoved) {
                    // 松开鼠标时吸附
                    const snappedPos = this.applyPanelPosition(currentX, currentY, true);
                    this.panelPosition = snappedPos;
                    Storage.set('panelPosition', this.panelPosition);

                    // 阻止点击事件触发展开
                    e.stopPropagation();
                } else {
                    // 没有移动,触发展开
                    // 不阻止事件,让点击事件继续冒泡
                }
            }
            document.removeEventListener('mousemove', onMouseMove, true);
            document.removeEventListener('mouseup', onMouseUp, true);
        };
    }

    // 切换布局模式(单列折叠 <-> 标签页切换)
    toggleLayout() {
        this.tabMode = !this.tabMode;
        Storage.set('tabMode', this.tabMode);
        
        // 重新加载面板以应用新布局
        // 保存当前位置
        const currentPos = { ...this.panelPosition };
        
        // 移除旧面板
        if (this.container && this.container.parentNode) {
            this.container.parentNode.removeChild(this.container);
        }
        
        // 重新创建面板
        this.setupButton();
        
        // 恢复位置(需要重新计算以适应新宽度)
        setTimeout(() => {
            const snappedPos = this.applyPanelPosition(currentPos.x, currentPos.y, true);
            this.panelPosition = snappedPos;
            Storage.set('panelPosition', this.panelPosition);
        }, 100);
        
        // 显示切换提示
        const modeText = this.tabMode ? '标签页布局' : '折叠布局';
        this.showNotification(`已切换到${modeText}`);
        
        console.log(`布局模式切换: ${modeText}`);
    }

    // 切换标签页
    switchTab(tabNum) {
        if (!this.tabMode) return;
        if (this.activeTab === tabNum) return;
        
        this.activeTab = tabNum;
        Storage.set('activeTab', this.activeTab);
        
        // 更新标签按钮状态
        const tabBtns = this.container.querySelectorAll('.tab-nav-btn');
        tabBtns.forEach((btn, index) => {
            if (index + 1 === tabNum) {
                btn.classList.add('active');
            } else {
                btn.classList.remove('active');
            }
        });
        
        // 更新标签内容显示
        const tabContents = this.container.querySelectorAll('.tab-content');
        tabContents.forEach(content => {
            const contentTab = parseInt(content.getAttribute('data-tab'));
            if (contentTab === tabNum) {
                content.classList.add('active');
            } else {
                content.classList.remove('active');
            }
        });
        
        // 如果切换到积分标签,加载积分数据
        if (tabNum === 2 && CURRENT_DOMAIN === 'linux.do' && this.creditContainer) {
            this.loadCreditInfo();
        }
        
        console.log(`切换到标签页 ${tabNum}`);
    }

    toggleMinimize() {
        const wasMinimized = this.panelMinimized;
        this.panelMinimized = !this.panelMinimized;
        Storage.set('panelMinimized', this.panelMinimized);

        // 根据布局模式获取内容容器
        const content = this.tabMode
            ? this.container.querySelector('.tab-container')
            : this.container.querySelector('.panel-content');

        // 判断当前在左边还是右边
        const windowWidth = window.innerWidth;
        const isOnRight = this.container.classList.contains('on-right');

        if (this.panelMinimized) {
            // 缩小:从 280px -> 50px
            if (content) content.classList.add('hidden');
            this.container.classList.add('minimized');

            // 如果在右边,需要调整 left 值以保持右边缘位置不变
            if (isOnRight) {
                const currentLeft = parseInt(this.container.style.left);
                // 280px 变成 50px,差值是 230px,需要向右移动 230px
                this.container.style.left = (currentLeft + 230) + 'px';
                this.currentTranslateX = currentLeft + 230;
            }

            setTimeout(() => {
                const snappedPos = this.applyPanelPosition(this.currentTranslateX, this.currentTranslateY, true);
                this.panelPosition = snappedPos;
                Storage.set('panelPosition', this.panelPosition);
            }, 100);
        } else {
            // 展开:从 50px -> 280px
            if (content) content.classList.remove('hidden');
            this.container.classList.remove('minimized');

            // 如果在右边,需要调整 left 值以保持右边缘位置不变
            if (isOnRight) {
                const currentLeft = parseInt(this.container.style.left);
                // 50px 变成 280px,差值是 230px,需要向左移动 230px
                this.container.style.left = (currentLeft - 230) + 'px';
                this.currentTranslateX = currentLeft - 230;
            }

            setTimeout(() => {
                // 强制浏览器重排
                void this.container.offsetWidth;

                const snappedPos = this.applyPanelPosition(this.currentTranslateX, this.currentTranslateY, true);
                this.panelPosition = snappedPos;
                Storage.set('panelPosition', this.panelPosition);
            }, 350);
        }
    }

    setupWindowResizeHandler() {
        // 监听窗口大小变化,确保面板始终在可见区域内
        let resizeTimer;

        const adjustPosition = () => {
            if (this.currentTranslateX !== null && this.currentTranslateY !== null) {
                // 重新应用吸附位置(窗口大小变化时重新计算)
                const snappedPos = this.applyPanelPosition(this.currentTranslateX, this.currentTranslateY, true);

                // 保存新位置
                this.panelPosition = snappedPos;
                Storage.set('panelPosition', this.panelPosition);
            }
            
            // 根据屏幕高度自动折叠区域
            this.autoCollapseForSmallScreen();
        };

        window.addEventListener('resize', () => {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(adjustPosition, 100);
        });

        // 初始调整一次
        setTimeout(adjustPosition, 500);
    }

    // 根据屏幕高度自动折叠区域
    autoCollapseForSmallScreen() {
        const screenHeight = window.innerHeight;
        
        // 如果屏幕高度小于 700px,自动折叠一些区域以确保内容能完整显示
        if (screenHeight < 700) {
            // 折叠模式设置区(如果未折叠)
            const allSections = this.container.querySelectorAll('.section-collapsible');
            for (const section of allSections) {
                const title = section.querySelector('.section-title');
                if (title && title.textContent.includes('模式设置')) {
                    if (!section.classList.contains('collapsed')) {
                        section.classList.add('collapsed');
                        if (this.settingsSectionContent) {
                            this.settingsSectionContent.classList.add('collapsed');
                        }
                    }
                    break;
                }
            }
            
            // 折叠文章页功能区(如果未折叠)
            const toolSection = this.toolSectionContainer?.querySelector('.section-collapsible');
            if (toolSection && !toolSection.classList.contains('collapsed')) {
                toolSection.classList.add('collapsed');
                if (this.toolSectionContent) {
                    this.toolSectionContent.classList.add('collapsed');
                }
            }
            
            // 如果屏幕高度小于 600px,还要折叠账号信息区(除非正在自动阅读)
            if (screenHeight < 600 && !this.autoRunning) {
                if (this.accountSection && !this.accountSection.classList.contains('collapsed')) {
                    this.accountSection.classList.add('collapsed');
                    if (this.accountSectionContent) {
                        this.accountSectionContent.classList.add('collapsed');
                    }
                }
            }
            
            // 如果屏幕高度小于 500px,折叠自动阅读区(除非正在运行)
            if (screenHeight < 500 && !this.autoRunning) {
                const autoSection = this.container.querySelector('.section-collapsible');
                if (autoSection && !autoSection.classList.contains('collapsed')) {
                    autoSection.classList.add('collapsed');
                    if (this.autoSectionContent) {
                        this.autoSectionContent.classList.add('collapsed');
                    }
                }
            }
        }
    }

    checkLikeResumeTime() {
        if (this.likeResumeTime) {
            const now = Date.now();
            if (now >= this.likeResumeTime) {
                // 时间到了,清除冷却时间
                console.log('点赞冷却时间已过,可以正常使用点赞功能');
                this.likeResumeTime = null;
                Storage.set('likeResumeTime', null);
                this.updateClearCooldownButton();
                // 不自动开启点赞,由用户决定
            } else {
                // 还在冷却期,记录状态但不修改开关
                const remainingHours = Math.ceil((this.likeResumeTime - now) / (1000 * 60 * 60));
                const resumeDate = new Date(this.likeResumeTime);
                console.log(`点赞功能冷却中,将在 ${resumeDate.toLocaleString()} (还需约 ${remainingHours} 小时) 后恢复`);
                console.log(`提示:可以点击"清除点赞冷却"按钮立即恢复点赞功能`);
                this.updateClearCooldownButton();
            }
        } else {
            this.updateClearCooldownButton();
        }
    }

    updateClearCooldownButton() {
        if (!this.clearCooldownBtn) return;

        // 清除之前的定时器
        if (this.cooldownUpdateTimer) {
            clearInterval(this.cooldownUpdateTimer);
            this.cooldownUpdateTimer = null;
        }

        if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
            // 更新显示的函数
            const updateDisplay = () => {
                const now = Date.now();
                if (now >= this.likeResumeTime) {
                    // 冷却结束
                    this.clearCooldownBtn.style.display = 'none';
                    if (this.cooldownUpdateTimer) {
                        clearInterval(this.cooldownUpdateTimer);
                        this.cooldownUpdateTimer = null;
                    }
                    // 清除冷却时间
                    this.likeResumeTime = null;
                    Storage.set('likeResumeTime', null);
                    this.showNotification('✅ 点赞冷却已结束,可以正常点赞了!');
                    return;
                }

                const remaining = this.likeResumeTime - now;
                const hours = Math.floor(remaining / (1000 * 60 * 60));
                const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
                const seconds = Math.floor((remaining % (1000 * 60)) / 1000);

                // 构建显示文本
                let timeText = '剩余';
                if (hours > 0) {
                    timeText += `${hours}小时`;
                }
                if (minutes > 0 || hours > 0) {
                    timeText += `${minutes}分`;
                }
                timeText += `${seconds}秒`;

                this.clearCooldownBtn.innerHTML = `<span class="btn-icon">🔥</span><span class="btn-text">清除冷却 (${timeText})</span>`;
            };

            // 立即更新一次
            updateDisplay();
            this.clearCooldownBtn.style.display = 'flex';

            // 每秒更新一次
            this.cooldownUpdateTimer = setInterval(updateDisplay, 1000);
        } else {
            this.clearCooldownBtn.style.display = 'none';
        }
    }

    handleClearCooldown() {
        if (!this.likeResumeTime) {
            this.showNotification('当前没有点赞冷却');
            return;
        }

        // 清除冷却时间
        this.likeResumeTime = null;
        Storage.set('likeResumeTime', null);

        // 更新按钮显示
        this.updateClearCooldownButton();

        // 显示成功提示
        this.showNotification('✅ 点赞冷却已清除,可以正常点赞了!');
        console.log('[清除冷却] 点赞冷却时间已清除');
    }

    observeLikeLimit() {
        // 标志:是否已经通过 API 处理过点赞限制
        this._likeLimitHandledByAPI = false;
        this._lastLikeLimitTime = 0;
        // 标志:防止 DOM 监听器在短时间内重复触发(防抖)
        this._likeLimitPopupLastTime = 0;
        this._likeLimitPopupTimeout = null;
        
        // 优先:拦截 XHR 请求,捕获 429 错误响应(精确获取等待时间)
        this.interceptFetchForLikeLimit();
        
        // 备用:监听 DOM 变化,检测点赞限制弹窗
        // 只有当 XHR 拦截器未能处理时,才使用 DOM 解析的时间
        const self = this;
        const observer = new MutationObserver((mutations) => {
            // 防抖:500ms 内不重复处理
            const now = Date.now();
            if (now - self._likeLimitPopupLastTime < 500) {
                return;
            }
            
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === 1) {
                        const text = node.textContent || '';

                        // 检测点赞限制弹窗
                        const isLikeLimit = (
                            (text.includes('点赞上限') ||
                             text.includes('分享很多爱') ||
                             text.includes('点赞') && text.includes('小时后再次点赞')) &&
                            !text.includes('回复') &&
                            !text.includes('创建更多新回复')
                        );

                        if (isLikeLimit) {
                            // 更新最后处理时间
                            self._likeLimitPopupLastTime = now;
                            
                            // 清除之前的超时
                            if (self._likeLimitPopupTimeout) {
                                clearTimeout(self._likeLimitPopupTimeout);
                            }
                            
                            // 等待 XHR 拦截器处理(XHR load 事件通常在 DOM 更新后触发)
                            self._likeLimitPopupTimeout = setTimeout(() => {
                                const currentTime = Date.now();
                                // 检查 XHR 是否已经处理过(2秒内)
                                if (self._likeLimitHandledByAPI && (currentTime - self._lastLikeLimitTime) < 2000) {
                                    console.log('[点赞限制] XHR 已处理,DOM 监听器仅关闭弹窗');
                                } else {
                                    // XHR 未处理,使用 DOM 解析作为备用方案
                                    console.log('[点赞限制] XHR 未处理,使用 DOM 解析作为备用');
                                    self.handleLikeLimit(text);
                                }
                                
                                // 无论如何都自动关闭弹窗
                                self.closeLikeLimitPopup();
                            }, 300); // 等待 300ms,让 XHR 拦截器有时间处理
                            
                            return; // 找到后立即返回,不再继续遍历
                        }
                    }
                }
            }
        });

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

    // 拦截 fetch 和 XMLHttpRequest 请求,捕获点赞 API 的 429 错误
    interceptFetchForLikeLimit() {
        const self = this;
        
        // 拦截 fetch
        const originalFetch = window.fetch;
        window.fetch = async function(...args) {
            const response = await originalFetch.apply(this, args);
            
            // 检查是否是点赞相关的 API 请求
            const url = args[0]?.toString() || '';
            const isLikeRequest = url.includes('/discourse-reactions/') ||
                                  url.includes('/toggle.json') ||
                                  url.includes('/like');
            
            // 如果是 429 错误且是点赞请求
            if (response.status === 429 && isLikeRequest) {
                try {
                    // 克隆响应以便读取内容(原响应只能读取一次)
                    const clonedResponse = response.clone();
                    const data = await clonedResponse.json();
                    
                    console.log('[点赞限制] fetch 检测到 429 错误:', data);
                    
                    // 检查是否是点赞限制(而不是其他类型的限制)
                    if (data.error_type === 'rate_limit' && data.extras) {
                        const waitSeconds = data.extras.wait_seconds;
                        const timeLeft = data.extras.time_left;
                        
                        if (waitSeconds && waitSeconds > 0) {
                            console.log(`[点赞限制] 从 fetch API 获取精确等待时间: ${waitSeconds} 秒 (${timeLeft})`);
                            self.handleLikeLimitFromAPI(waitSeconds, timeLeft);
                        }
                    }
                } catch (e) {
                    console.error('[点赞限制] 解析 fetch 429 响应失败:', e);
                }
            }
            
            return response;
        };
        
        // 拦截 XMLHttpRequest(jQuery ajax 使用的是 XHR)
        const originalXHROpen = XMLHttpRequest.prototype.open;
        const originalXHRSend = XMLHttpRequest.prototype.send;
        
        XMLHttpRequest.prototype.open = function(method, url, ...rest) {
            this._url = url;
            this._method = method;
            return originalXHROpen.apply(this, [method, url, ...rest]);
        };
        
        XMLHttpRequest.prototype.send = function(body) {
            const xhr = this;
            const url = xhr._url || '';
            
            // 检查是否是点赞相关的 API 请求
            const isLikeRequest = url.includes('/discourse-reactions/') ||
                                  url.includes('/toggle.json') ||
                                  url.includes('/like');
            
            if (isLikeRequest) {
                xhr.addEventListener('load', function() {
                    if (xhr.status === 429) {
                        try {
                            const data = JSON.parse(xhr.responseText);
                            console.log('[点赞限制] XHR 检测到 429 错误:', data);
                            
                            // 检查是否是点赞限制
                            if (data.error_type === 'rate_limit' && data.extras) {
                                const waitSeconds = data.extras.wait_seconds;
                                const timeLeft = data.extras.time_left;
                                
                                if (waitSeconds && waitSeconds > 0) {
                                    console.log(`[点赞限制] 从 XHR API 获取精确等待时间: ${waitSeconds} 秒 (${timeLeft})`);
                                    self.handleLikeLimitFromAPI(waitSeconds, timeLeft);
                                }
                            }
                        } catch (e) {
                            console.error('[点赞限制] 解析 XHR 429 响应失败:', e);
                        }
                    }
                });
            }
            
            return originalXHRSend.apply(this, [body]);
        };
        
        console.log('[点赞限制] 已启用 fetch 和 XHR 拦截器');
    }

    // 处理从 API 获取的点赞限制
    handleLikeLimitFromAPI(waitSeconds, timeLeft) {
        console.log(`[点赞限制] 处理 API 返回的限制: ${waitSeconds} 秒`);
        
        // 标记已通过 API 处理,防止 DOM 监听器重复处理
        this._likeLimitHandledByAPI = true;
        this._lastLikeLimitTime = Date.now();
        
        // 计算恢复时间(使用精确的秒数)
        const resumeTime = Date.now() + (waitSeconds * 1000);
        this.likeResumeTime = resumeTime;
        Storage.set('likeResumeTime', resumeTime);

        // 关闭自动点赞和快速点赞
        this.autoLikeEnabled = false;
        this.quickLikeEnabled = false;
        Storage.set('autoLikeEnabled', false);
        Storage.set('quickLikeEnabled', false);

        // 更新UI - 更精确地定位到点赞开关
        const toggleRows = this.container.querySelectorAll('.toggle-row');
        for (const row of toggleRows) {
            const label = row.querySelector('.toggle-label');
            if (label && (label.textContent.includes('自动点赞') || label.textContent.includes('快速点赞'))) {
                const input = row.querySelector('input[type="checkbox"]');
                if (input) {
                    input.checked = false;
                }
            }
        }

        // 更新冷却按钮显示
        this.updateClearCooldownButton();

        const resumeDate = new Date(resumeTime);
        console.log(`[点赞限制] 已达到点赞上限,将在 ${resumeDate.toLocaleString()} (${timeLeft}) 后恢复`);

        // 显示提示
        this.showNotification(`点赞已达上限,将在 ${timeLeft} 后自动恢复`);
    }

    handleLikeLimit(text) {
        console.log('检测到点赞限制提示:', text);

        let waitMinutes = 0; // 等待时间(分钟)

        // 优先匹配 "在 X 分钟后" 格式
        const minuteMatch = text.match(/[在|可以在]\s*(\d+)\s*分钟后/);
        if (minuteMatch) {
            waitMinutes = parseInt(minuteMatch[1]);
            console.log(`从 "X分钟后" 提取到等待时间: ${waitMinutes} 分钟`);
        } else {
            // 匹配 "在 X 小时后" 格式
            const hourMatch = text.match(/[在|可以在]\s*(\d+)\s*小时后/);
            if (hourMatch) {
                waitMinutes = parseInt(hourMatch[1]) * 60;
                console.log(`从 "X小时后" 提取到等待时间: ${hourMatch[1]} 小时 = ${waitMinutes} 分钟`);
            } else {
                // 尝试匹配最后一个数字+单位的组合
                const allMinuteMatches = text.match(/(\d+)\s*分钟/g);
                const allHourMatches = text.match(/(\d+)\s*小时/g);

                if (allMinuteMatches && allMinuteMatches.length > 0) {
                    // 取最后一个分钟匹配
                    const lastMatch = allMinuteMatches[allMinuteMatches.length - 1].match(/(\d+)/);
                    if (lastMatch) {
                        waitMinutes = parseInt(lastMatch[1]);
                        console.log(`从最后一个匹配提取到等待时间: ${waitMinutes} 分钟`);
                    }
                } else if (allHourMatches && allHourMatches.length > 0) {
                    // 取最后一个小时匹配
                    const lastMatch = allHourMatches[allHourMatches.length - 1].match(/(\d+)/);
                    if (lastMatch) {
                        waitMinutes = parseInt(lastMatch[1]) * 60;
                        console.log(`从最后一个匹配提取到等待时间: ${lastMatch[1]} 小时 = ${waitMinutes} 分钟`);
                    }
                } else {
                    // 默认10小时
                    waitMinutes = 10 * 60;
                    console.log(`未能提取等待时间,使用默认值: 10 小时 = ${waitMinutes} 分钟`);
                }
            }
        }

        // 计算恢复时间
        const resumeTime = Date.now() + (waitMinutes * 60 * 1000);
        this.likeResumeTime = resumeTime;
        Storage.set('likeResumeTime', resumeTime);

        // 关闭自动点赞和快速点赞
        this.autoLikeEnabled = false;
        this.quickLikeEnabled = false;
        Storage.set('autoLikeEnabled', false);
        Storage.set('quickLikeEnabled', false);

        // 更新UI - 更精确地定位到点赞开关
        const toggleRows = this.container.querySelectorAll('.toggle-row');
        for (const row of toggleRows) {
            const label = row.querySelector('.toggle-label');
            if (label && (label.textContent.includes('自动点赞') || label.textContent.includes('快速点赞'))) {
                const input = row.querySelector('input[type="checkbox"]');
                if (input) {
                    input.checked = false;
                }
            }
        }

        const resumeDate = new Date(resumeTime);
        const displayTime = waitMinutes >= 60
            ? `${Math.floor(waitMinutes / 60)} 小时 ${waitMinutes % 60 > 0 ? (waitMinutes % 60) + ' 分钟' : ''}`.trim()
            : `${waitMinutes} 分钟`;

        console.log(`已达到点赞上限,自动关闭点赞功能,将在 ${resumeDate.toLocaleString()} (${displayTime}后) 恢复`);

        // 显示提示 - 使用提取到的实际时间
        this.showNotification(`点赞已达上限,将在 ${displayTime}后自动恢复`);
    }

    // 关闭点赞限制弹窗
    closeLikeLimitPopup() {
        console.log('[点赞限制] 尝试关闭弹窗...');
        
        // 方法1:直接查找并点击确定/关闭按钮
        const buttonSelectors = [
            // Discourse 标准弹窗按钮
            '.dialog-footer .btn-primary',
            '.modal-footer .btn-primary',
            '.d-modal__footer .btn-primary',
            '.bootbox .btn-primary',
            // 通用按钮
            'button.btn-primary',
            'button.btn-default',
            // 关闭按钮
            '.modal-close',
            '.close-modal',
            '.d-modal__dismiss',
            'button[aria-label="关闭"]',
            'button[aria-label="Close"]',
            '.dialog-close',
            // Discourse 特定
            '.d-modal__dismiss-icon',
            '.modal-header .close'
        ];
        
        for (const selector of buttonSelectors) {
            const elements = document.querySelectorAll(selector);
            for (const element of elements) {
                // 检查元素是否可见
                if (element.offsetParent === null) continue;
                
                const text = (element.textContent || '').trim();
                // 对于 btn-primary,直接点击(通常是确定按钮)
                if (selector.includes('btn-primary') ||
                    text.includes('确定') || text.includes('OK') || text.includes('关闭') || text.includes('好') ||
                    element.classList.contains('modal-close') ||
                    element.classList.contains('close-modal') ||
                    element.classList.contains('d-modal__dismiss')) {
                    console.log(`[点赞限制] 找到关闭按钮: ${selector}, 文本: "${text}"`);
                    try {
                        element.click();
                        console.log('[点赞限制] 已点击关闭按钮');
                        return;
                    } catch (e) {
                        console.error('[点赞限制] 点击按钮失败:', e);
                    }
                }
            }
        }
        
        // 方法2:查找所有可见的弹窗,尝试点击其中的按钮
        const modalSelectors = ['.modal', '.d-modal', '.bootbox', '.dialog-body', '[role="dialog"]'];
        for (const modalSelector of modalSelectors) {
            const modal = document.querySelector(modalSelector);
            if (modal && modal.offsetParent !== null) {
                // 在弹窗内查找按钮
                const buttons = modal.querySelectorAll('button');
                for (const btn of buttons) {
                    const text = (btn.textContent || '').trim();
                    if (text.includes('确定') || text.includes('OK') || text.includes('关闭') || text.includes('好') ||
                        btn.classList.contains('btn-primary')) {
                        console.log(`[点赞限制] 在弹窗内找到按钮: "${text}"`);
                        try {
                            btn.click();
                            console.log('[点赞限制] 已点击弹窗内按钮');
                            return;
                        } catch (e) {
                            console.error('[点赞限制] 点击弹窗内按钮失败:', e);
                        }
                    }
                }
            }
        }
        
        // 方法3:尝试按 Escape 键关闭
        console.log('[点赞限制] 未找到关闭按钮,尝试按 Escape 键');
        document.dispatchEvent(new KeyboardEvent('keydown', {
            key: 'Escape',
            code: 'Escape',
            keyCode: 27,
            which: 27,
            bubbles: true
        }));
        
        // 方法4:延迟后再次尝试(有时弹窗需要时间渲染)
        setTimeout(() => {
            const visibleButtons = document.querySelectorAll('.dialog-footer button, .modal-footer button');
            for (const btn of visibleButtons) {
                if (btn.offsetParent !== null) {
                    console.log(`[点赞限制] 延迟后找到按钮: "${btn.textContent}"`);
                    btn.click();
                    return;
                }
            }
        }, 500);
    }

    showNotification(message) {
        const notification = document.createElement('div');
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 15px 20px;
            border-radius: 10px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            z-index: 100000;
            font-size: 14px;
            max-width: 300px;
            animation: slideIn 0.3s ease-out;
        `;
        notification.textContent = message;

        // 添加动画样式
        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideIn {
                from {
                    transform: translateX(400px);
                    opacity: 0;
                }
                to {
                    transform: translateX(0);
                    opacity: 1;
                }
            }
        `;
        document.head.appendChild(style);

        document.body.appendChild(notification);

        // 3秒后自动消失
        setTimeout(() => {
            notification.style.transition = 'all 0.3s';
            notification.style.opacity = '0';
            notification.style.transform = 'translateX(400px)';
            setTimeout(() => notification.remove(), 300);
        }, 3000);
    }

    // 获取当前用户名
    async getCurrentUsername() {
        if (this.currentUsername) return this.currentUsername;

        try {
            // 方法1:从用户菜单获取
            const userMenuBtn = document.querySelector('.header-dropdown-toggle.current-user');
            if (userMenuBtn) {
                const img = userMenuBtn.querySelector('img[alt]');
                if (img && img.alt) {
                    this.currentUsername = img.alt;
                    return this.currentUsername;
                }
            }

            // 方法2:从 API 获取
            const response = await fetch(`${BASE_URL}/session/current.json`);
            if (response.ok) {
                const data = await response.json();
                if (data.current_user && data.current_user.username) {
                    this.currentUsername = data.current_user.username;
                    return this.currentUsername;
                }
            }
        } catch (error) {
            console.error('获取用户名失败:', error);
        }
        return null;
    }

    // 加载用户信任等级
    async loadUserTrustLevel(isManualRefresh = false) {
        const username = await this.getCurrentUsername();
        if (!username) {
            this.trustLevelContainer.innerHTML = '<div class="trust-level-loading">未登录</div>';
            return;
        }

        // 如果不是手动刷新,显示加载状态
        if (isManualRefresh) {
            const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
            if (refreshBtn) {
                refreshBtn.textContent = '刷新中...';
                refreshBtn.disabled = true;
            }
        }

        try {
            // 域名判断:idcflare.com 使用原逻辑,linux.do 使用新逻辑
            if (CURRENT_DOMAIN === 'idcflare.com') {
                // idcflare.com 使用原来的 summary.json 逻辑
                const summaryResponse = await fetch(`${BASE_URL}/u/${username}/summary.json`);
                if (summaryResponse.ok) {
                    const data = await summaryResponse.json();
                    if (data.user_summary) {
                        this.renderTrustLevel(data, username);
                        return;
                    }
                }
                throw new Error('无法获取等级数据');
            } else if (CURRENT_DOMAIN === 'linux.do') {
                // linux.do: 完全使用 1.js 的逻辑(使用GM_xmlhttpRequest跨域请求)
                await this.fetchLinuxDoDataWithGM(username);
            }
        } catch (error) {
            console.error('加载信任等级失败:', error);
            this.trustLevelContainer.innerHTML = `
                <div class="trust-level-header">
                    📊 信任等级
                    <button class="trust-level-refresh" onclick="window.browseController.loadUserTrustLevel(true)">🔄 刷新</button>
                </div>
                <div class="trust-level-loading">加载失败,请点击刷新重试</div>
            `;
        } finally {
            // 恢复刷新按钮状态
            if (isManualRefresh) {
                setTimeout(() => {
                    const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
                    if (refreshBtn) {
                        refreshBtn.textContent = '🔄 刷新';
                        refreshBtn.disabled = false;
                    }
                }, 1000);
            }
        }
    }

    // 使用 GM_xmlhttpRequest 获取 linux.do 数据(完全按照1.js的逻辑)
    async fetchLinuxDoDataWithGM(username) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: "https://connect.linux.do/",
                timeout: 15000,
                onload: (response) => {
                    if (response.status === 200) {
                        const responseText = response.responseText;
                        const tempDiv = document.createElement('div');
                        tempDiv.innerHTML = responseText;

                        // 1. 解析全局用户名和当前等级 (从 <h1>)
                        let globalUsername = username;
                        let currentLevel = '未知';
                        const h1 = tempDiv.querySelector('h1');
                        if (h1) {
                            const h1Text = h1.textContent.trim();
                            // 例如: "你好,一剑万生 (YY_WD) 2级用户" 或 "你好, (yy2025) 0级用户"
                            const welcomeMatch = h1Text.match(/你好,\s*([^(\s]*)\s*\(?([^)]*)\)?\s*(\d+)级用户/i);
                            if (welcomeMatch) {
                                // 优先使用括号内的用户名,如果没有则使用前面的
                                globalUsername = welcomeMatch[2] || welcomeMatch[1] || username;
                                currentLevel = welcomeMatch[3];
                                console.log(`从<h1>解析: 用户名='${globalUsername}', 当前等级='${currentLevel}'`);
                            }
                        }

                        // 检查用户等级,决定使用哪种数据获取方式
                        const userLevel = parseInt(currentLevel);
                        if (userLevel === 0 || userLevel === 1) {
                            console.log(`检测到${userLevel}级用户,使用summary.json获取数据`);
                            this.fetchLowLevelUserData(username, userLevel).then(resolve).catch(reject);
                        } else if (userLevel >= 2) {
                            console.log(`检测到${userLevel}级用户,使用connect.linux.do页面数据`);
                            this.processHighLevelUserData(tempDiv, globalUsername, currentLevel);
                            resolve();
                        } else {
                            reject(new Error('无法确定用户等级'));
                        }
                    } else {
                        reject(new Error(`请求失败,状态码: ${response.status}`));
                    }
                },
                onerror: (error) => {
                    console.error('GM_xmlhttpRequest 错误:', error);
                    reject(new Error('网络请求错误'));
                },
                ontimeout: () => {
                    console.error('GM_xmlhttpRequest 超时');
                    reject(new Error('请求超时'));
                }
            });
        });
    }

    // 处理0级和1级用户数据
    async fetchLowLevelUserData(username, currentLevel) {
        const summaryResponse = await fetch(`${BASE_URL}/u/${username}/summary.json`);
        if (summaryResponse.ok) {
            const data = await summaryResponse.json();
            const userSummary = data.user_summary;
            this.renderTrustLevelNew(username, currentLevel, userSummary);
        } else {
            throw new Error('无法获取用户summary数据');
        }
    }

    // 处理2级及以上用户数据
    processHighLevelUserData(tempDiv, globalUsername, currentLevel) {
        let targetInfoDiv = null;
        const potentialDivs = tempDiv.querySelectorAll('div.bg-white.p-6.rounded-lg');

        for (let i = 0; i < potentialDivs.length; i++) {
            const div = potentialDivs[i];
            const h2 = div.querySelector('h2');
            if (h2 && h2.textContent.includes('信任级别')) {
                targetInfoDiv = div;
                break;
            }
        }

        if (!targetInfoDiv) {
            throw new Error('未找到信任级别数据块');
        }

        // 解析标题获取目标等级
        const h2 = targetInfoDiv.querySelector('h2');
        const titleMatch = h2.textContent.match(/信任级别\s*(\d+)\s*的要求/);
        const targetLevel = titleMatch ? titleMatch[1] : '未知';

        // 解析表格数据
        const tableRows = targetInfoDiv.querySelectorAll('table tbody tr');
        const requirements = [];

        tableRows.forEach((row, index) => {
            if (index === 0) return; // 跳过表头

            const cells = row.querySelectorAll('td');
            if (cells.length >= 3) {
                const name = cells[0].textContent.trim();
                const current = cells[1].textContent.trim();
                const required = cells[2].textContent.trim();
                const isMet = cells[1].classList.contains('text-green-500');

                requirements.push({ name, current, required, isMet });
            }
        });

        // 渲染高级等级信息
        this.renderAdvancedTrustLevel(globalUsername, targetLevel, requirements);
    }

    // 新的渲染方法(基于1.js的逻辑,用于0级和1级用户)
    renderTrustLevelNew(username, currentLevel, userSummary) {
        const targetLevel = currentLevel + 1;
        const requirements = CONFIG.levelRequirements[currentLevel];

        if (!requirements) {
            this.trustLevelContainer.innerHTML = '<div class="trust-level-loading">无配置数据</div>';
            return;
        }

        const trustLevelDetails = {
            items: [],
            achievedCount: 0,
            totalCount: 0
        };

        // 检查各项要求
        Object.entries(requirements).forEach(([key, requiredValue]) => {
            let currentValue = 0;
            let label = '';
            let isMet = false;

            switch (key) {
                case 'topics_entered':
                    currentValue = userSummary.topics_entered || 0;
                    label = '浏览的话题';
                    isMet = currentValue >= requiredValue;
                    break;
                case 'posts_read_count':
                    currentValue = userSummary.posts_read_count || 0;
                    label = '已读帖子';
                    isMet = currentValue >= requiredValue;
                    break;
                case 'time_read':
                    currentValue = Math.floor((userSummary.time_read || 0) / 60);
                    label = '阅读时长(分)';
                    isMet = (userSummary.time_read || 0) >= requiredValue;
                    requiredValue = Math.floor(requiredValue / 60);
                    break;
                case 'days_visited':
                    currentValue = userSummary.days_visited || 0;
                    label = '访问天数';
                    isMet = currentValue >= requiredValue;
                    break;
                case 'likes_given':
                    currentValue = userSummary.likes_given || 0;
                    label = '给出的赞';
                    isMet = currentValue >= requiredValue;
                    break;
                case 'likes_received':
                    currentValue = userSummary.likes_received || 0;
                    label = '收到的赞';
                    isMet = currentValue >= requiredValue;
                    break;
                case 'post_count':
                    currentValue = userSummary.post_count || 0;
                    label = '帖子数量';
                    isMet = currentValue >= requiredValue;
                    break;
            }

            if (label) {
                trustLevelDetails.items.push({
                    name: label,
                    current: currentValue,
                    required: requiredValue,
                    isMet: isMet
                });

                if (isMet) {
                    trustLevelDetails.achievedCount++;
                }
                trustLevelDetails.totalCount++;
            }
        });

        const achievedCount = trustLevelDetails.achievedCount;
        const totalCount = trustLevelDetails.totalCount;
        const allMet = achievedCount === totalCount;

        const levelNames = {
            0: 'Lv0 → Lv1',
            1: 'Lv1 → Lv2'
        };

        let html = `
            <div class="trust-level-header">
                <span>📊 ${levelNames[currentLevel] || `Lv${currentLevel} → Lv${targetLevel}`} (${username})</span>
                <button class="trust-level-refresh" data-action="refresh">🔄 刷新</button>
            </div>
        `;

        trustLevelDetails.items.forEach(req => {
            const progress = Math.min((req.current / req.required) * 100, 100);
            const isCompleted = req.isMet;
            const fillClass = isCompleted ? 'completed' : '';

            html += `
                <div class="trust-level-item">
                    <span class="trust-level-name">${req.name}</span>
                    <div class="trust-level-progress">
                        <div class="trust-level-bar">
                            <div class="trust-level-bar-fill ${fillClass}" style="width: ${progress}%"></div>
                        </div>
                        <span class="trust-level-value">${req.current}/${req.required}</span>
                    </div>
                </div>
            `;
        });

        if (allMet) {
            html += `
                <div style="background: rgba(255, 255, 255, 0.25); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: #fff; font-size: 11px; font-weight: 600; text-align: center;">
                        ✅ 已满足 Lv${targetLevel} 要求
                    </div>
                </div>
            `;
        } else {
            const unmetCount = totalCount - achievedCount;
            html += `
                <div style="background: rgba(255, 255, 255, 0.15); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: rgba(255, 255, 255, 0.9); font-size: 11px; font-weight: 500; text-align: center;">
                        还需完成 ${unmetCount} 项升级到 Lv${targetLevel}
                    </div>
                </div>
            `;
        }

        this.trustLevelContainer.innerHTML = html;

        setTimeout(() => {
            const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', () => this.loadUserTrustLevel(true));
            }
        }, 100);
    }

    // 从 connect.linux.do 加载等级信息(适用于TL2+)
    async loadTrustLevelFromConnect(username) {
        try {
            const response = await fetch('https://connect.linux.do/');
            if (!response.ok) {
                throw new Error('无法访问 connect.linux.do');
            }

            const html = await response.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');

            // 查找包含"信任级别"的区块
            const trustLevelSection = Array.from(doc.querySelectorAll('div.bg-white.p-6.rounded-lg')).find(div => {
                const h2 = div.querySelector('h2');
                return h2 && h2.textContent.includes('信任级别');
            });

            if (!trustLevelSection) {
                throw new Error('未找到信任级别数据');
            }

            // 解析标题获取目标等级
            const h2 = trustLevelSection.querySelector('h2');
            const titleMatch = h2.textContent.match(/信任级别\s*(\d+)\s*的要求/);
            const targetLevel = titleMatch ? titleMatch[1] : '未知';

            // 解析表格数据
            const tableRows = trustLevelSection.querySelectorAll('table tbody tr');
            const requirements = [];

            tableRows.forEach((row, index) => {
                if (index === 0) return; // 跳过表头

                const cells = row.querySelectorAll('td');
                if (cells.length >= 3) {
                    const name = cells[0].textContent.trim();
                    const current = cells[1].textContent.trim();
                    const required = cells[2].textContent.trim();
                    const isMet = cells[1].classList.contains('text-green-500');

                    requirements.push({ name, current, required, isMet });
                }
            });

            // 渲染高级等级信息
            this.renderAdvancedTrustLevel(username, targetLevel, requirements);

        } catch (error) {
            console.error('从 connect.linux.do 加载失败:', error);
            throw error;
        }
    }

    // 渲染信任等级信息(支持 TL0->TL1 和 TL1->TL2 - 基于 summary.json)
    renderTrustLevel(data, username) {
        const summary = data.user_summary;
        if (!summary) {
            this.trustLevelContainer.innerHTML = '<div class="trust-level-loading">无数据</div>';
            return;
        }

        // 获取当前信任等级
        // 优先从 user_summary 中获取,如果没有则从外层获取
        const currentLevel = summary.trust_level !== undefined ? summary.trust_level :
                           (data.user && data.user.trust_level !== undefined ? data.user.trust_level : 1);
        const targetLevel = currentLevel + 1;

        // 根据当前等级获取对应的升级要求
        const levelConfig = CONFIG.levelRequirements[currentLevel];

        if (!levelConfig) {
            // 如果没有配置(比如已经是最高等级),使用原来的逻辑
            this.renderDefaultTrustLevel(summary, username);
            return;
        }

        const requirements = [];

        // 根据配置动态构建要求列表
        Object.entries(levelConfig).forEach(([key, requiredValue]) => {
            let currentValue = 0;
            let label = '';

            switch (key) {
                case 'topics_entered':
                    currentValue = summary.topics_entered || 0;
                    label = '浏览的话题';
                    break;
                case 'posts_read_count':
                    currentValue = summary.posts_read_count || 0;
                    label = '已读帖子';
                    break;
                case 'time_read':
                    currentValue = Math.floor((summary.time_read || 0) / 60);
                    label = '阅读时长(分)';
                    requiredValue = Math.floor(requiredValue / 60);
                    break;
                case 'days_visited':
                    currentValue = summary.days_visited || 0;
                    label = '访问天数';
                    break;
                case 'likes_given':
                    currentValue = summary.likes_given || 0;
                    label = '给出的赞';
                    break;
                case 'likes_received':
                    currentValue = summary.likes_received || 0;
                    label = '收到的赞';
                    break;
                case 'post_count':
                    currentValue = summary.post_count || 0;
                    label = '帖子数量';
                    break;
            }

            if (label) {
                requirements.push({
                    name: label,
                    current: currentValue,
                    required: requiredValue
                });
            }
        });

        // 计算达标数量
        const achievedCount = requirements.filter(req => req.current >= req.required).length;
        const totalCount = requirements.length;
        const allMet = achievedCount === totalCount;

        const levelNames = {
            0: 'Lv0 → Lv1',
            1: 'Lv1 → Lv2',
            2: 'Lv2 → Lv3',
            3: 'Lv3 → Lv4'
        };

        let html = `
            <div class="trust-level-header">
                <span>📊 ${levelNames[currentLevel] || `Lv${currentLevel} → Lv${targetLevel}`} (${username})</span>
                <button class="trust-level-refresh" data-action="refresh">🔄 刷新</button>
            </div>
        `;

        requirements.forEach(req => {
            const progress = Math.min((req.current / req.required) * 100, 100);
            const isCompleted = req.current >= req.required;
            const fillClass = isCompleted ? 'completed' : '';

            html += `
                <div class="trust-level-item">
                    <span class="trust-level-name">${req.name}</span>
                    <div class="trust-level-progress">
                        <div class="trust-level-bar">
                            <div class="trust-level-bar-fill ${fillClass}" style="width: ${progress}%"></div>
                        </div>
                        <span class="trust-level-value">${req.current}/${req.required}</span>
                    </div>
                </div>
            `;
        });

        // 在数据下方添加总结信息
        if (allMet) {
            html += `
                <div style="background: rgba(255, 255, 255, 0.25); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: #fff; font-size: 11px; font-weight: 600; text-align: center;">
                        ✅ 已满足 Lv${targetLevel} 要求
                    </div>
                </div>
            `;
        } else {
            const unmetCount = totalCount - achievedCount;
            html += `
                <div style="background: rgba(255, 255, 255, 0.15); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: rgba(255, 255, 255, 0.9); font-size: 11px; font-weight: 500; text-align: center;">
                        还需完成 ${unmetCount} 项升级到 Lv${targetLevel}
                    </div>
                </div>
            `;
        }

        this.trustLevelContainer.innerHTML = html;

        // 添加刷新按钮事件监听
        setTimeout(() => {
            const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', () => this.loadUserTrustLevel(true));
            }
        }, 100);
    }

    // 默认渲染方法(用于没有配置的等级)
    renderDefaultTrustLevel(summary, username) {
        const requirements = [
            { name: '访问天数', current: summary.days_visited, required: 15 },
            { name: '给出的赞', current: summary.likes_given, required: 1 },
            { name: '收到的赞', current: summary.likes_received, required: 1 },
            { name: '帖子数量', current: summary.post_count, required: 3 },
            { name: '进入主题', current: summary.topics_entered, required: 20 },
            { name: '阅读帖子', current: summary.posts_read_count, required: 100 },
            { name: '阅读时长(分)', current: Math.floor(summary.time_read / 60), required: 60 }
        ];

        // 计算达标数量
        const achievedCount = requirements.filter(req => req.current >= req.required).length;
        const totalCount = requirements.length;
        const allMet = achievedCount === totalCount;

        let html = `
            <div class="trust-level-header">
                <span>📊 等级 (L2+) (${username || ''})</span>
                <button class="trust-level-refresh" data-action="refresh">🔄 刷新</button>
            </div>
        `;

        // 添加总结信息
        if (allMet) {
            html += `
                <div style="background: rgba(16, 185, 129, 0.2); padding: 6px 8px; border-radius: 6px; margin: 6px 0;">
                    <div style="color: #10b981; font-size: 11px; font-weight: 600; text-align: center;">
                        🎉 所有要求已达标!
                    </div>
                </div>
            `;
        } else {
            const unmetCount = totalCount - achievedCount;
            html += `
                <div style="background: rgba(251, 146, 60, 0.2); padding: 6px 8px; border-radius: 6px; margin: 6px 0;">
                    <div style="color: #ea580c; font-size: 11px; font-weight: 600; text-align: center;">
                        还需完成 ${unmetCount} 项要求
                    </div>
                </div>
            `;
        }

        requirements.forEach(req => {
            const progress = Math.min((req.current / req.required) * 100, 100);
            const isCompleted = req.current >= req.required;
            const fillClass = isCompleted ? 'completed' : '';

            html += `
                <div class="trust-level-item">
                    <span class="trust-level-name">${req.name}</span>
                    <div class="trust-level-progress">
                        <div class="trust-level-bar">
                            <div class="trust-level-bar-fill ${fillClass}" style="width: ${progress}%"></div>
                        </div>
                        <span class="trust-level-value">${req.current}/${req.required}</span>
                    </div>
                </div>
            `;
        });

        this.trustLevelContainer.innerHTML = html;

        setTimeout(() => {
            const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', () => this.loadUserTrustLevel(true));
            }
        }, 100);
    }

    // 渲染高级信任等级信息(从 connect.linux.do 获取的TL2+数据)
    renderAdvancedTrustLevel(username, targetLevel, requirements) {
        const achievedCount = requirements.filter(r => r.isMet).length;
        const totalCount = requirements.length;

        // 计算当前等级
        const currentLevel = parseInt(targetLevel) - 1;

        // 等级名称映射(简化显示)
        const levelNames = {
            2: 'Lv1 → Lv2',
            3: 'Lv2 → Lv3',
            4: 'Lv3 → Lv4'
        };

        let html = `
            <div class="trust-level-header">
                <span>📊 ${levelNames[targetLevel] || `Lv${currentLevel} → Lv${targetLevel}`} (${username})</span>
                <button class="trust-level-refresh" data-action="refresh">🔄 刷新</button>
            </div>
        `;

        requirements.forEach(req => {
            // 尝试从文本中提取数字
            const currentMatch = req.current.match(/(\d+)/);
            const requiredMatch = req.required.match(/(\d+)/);

            const currentNum = currentMatch ? parseInt(currentMatch[1]) : 0;
            const requiredNum = requiredMatch ? parseInt(requiredMatch[1]) : 1;

            const progress = Math.min((currentNum / requiredNum) * 100, 100);
            const isCompleted = req.isMet;
            const fillClass = isCompleted ? 'completed' : '';

            // 简化标签名称
            let simpleName = req.name
                .replace('已读帖子(所有时间)', '已读帖子')
                .replace('浏览的话题(所有时间)', '浏览话题')
                .replace('获赞:点赞用户数量', '点赞用户')
                .replace('被禁言(过去 6 个月)', '被禁言')
                .replace('被封禁(过去 6 个月)', '被封禁')
                .replace('访问次数(过去', '访问次数(')
                .replace('个月)', '月)')
                .replace('回复次数(最近', '回复(近')
                .replace('天内)', '天)');

            html += `
                <div class="trust-level-item">
                    <span class="trust-level-name">${simpleName}</span>
                    <div class="trust-level-progress">
                        <div class="trust-level-bar">
                            <div class="trust-level-bar-fill ${fillClass}" style="width: ${progress}%"></div>
                        </div>
                        <span class="trust-level-value">${req.current}/${req.required}</span>
                    </div>
                </div>
            `;
        });

        // 在数据下方添加总结信息
        if (achievedCount === totalCount) {
            html += `
                <div style="background: rgba(255, 255, 255, 0.25); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: #fff; font-size: 11px; font-weight: 600; text-align: center;">
                        ✅ 已满足 Lv${targetLevel} 要求
                    </div>
                </div>
            `;
        } else {
            const unmetCount = totalCount - achievedCount;
            html += `
                <div style="background: rgba(255, 255, 255, 0.15); padding: 6px 8px; border-radius: 6px; margin: 6px 0 0 0;">
                    <div style="color: rgba(255, 255, 255, 0.9); font-size: 11px; font-weight: 500; text-align: center;">
                        还需完成 ${unmetCount} 项升级到 Lv${targetLevel}
                    </div>
                </div>
            `;
        }

        this.trustLevelContainer.innerHTML = html;

        // 添加刷新按钮事件监听
        setTimeout(() => {
            const refreshBtn = this.trustLevelContainer.querySelector('.trust-level-refresh');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', () => this.loadUserTrustLevel(true));
            }
        }, 100);
    }

    // 加载用户阅读历史
    async loadUserReadHistory() {
        const username = await this.getCurrentUsername();
        if (!username) {
            console.log('未获取到用户名,无法加载阅读历史');
            this.readTopics = [];
            return;
        }

        // 从 localStorage 加载该用户的阅读历史
        const storageKey = `readTopics_${username}`;
        this.readTopics = Storage.get(storageKey, []);
        console.log(`已加载用户 ${username} 的阅读历史,共 ${this.readTopics.length} 篇帖子`);
    }

    // 保存用户阅读历史
    async saveUserReadHistory(topicId) {
        const username = await this.getCurrentUsername();
        if (!username) {
            console.log('未获取到用户名,无法保存阅读历史');
            return;
        }

        // 添加到已读列表(避免重复)
        if (!this.readTopics.includes(topicId)) {
            this.readTopics.push(topicId);

            // 限制列表大小(最多保存1000篇)
            if (this.readTopics.length > 1000) {
                this.readTopics = this.readTopics.slice(-1000);
            }

            // 保存到 localStorage
            const storageKey = `readTopics_${username}`;
            Storage.set(storageKey, this.readTopics);
            console.log(`已保存帖子 ${topicId} 到用户 ${username} 的阅读历史`);
        }
    }

    // 检查帖子是否已读
    isTopicRead(topicId) {
        return this.readTopics.includes(topicId);
    }

    // 启动账号切换监控
    startUserSwitchMonitoring() {
        // 初始化当前用户
        this.getCurrentUsername().then(username => {
            this.lastDetectedUser = username;
        });

        // 每5秒检查一次是否切换账号
        setInterval(async () => {
            const currentDetectedUser = await this.getCurrentUsername();

            if (currentDetectedUser && this.lastDetectedUser &&
                currentDetectedUser !== this.lastDetectedUser) {
                console.log(`检测到账号切换: ${this.lastDetectedUser} -> ${currentDetectedUser}`);
                this.lastDetectedUser = currentDetectedUser;
                this.currentUsername = currentDetectedUser;

                // 延迟一点时间再刷新,确保页面稳定
                setTimeout(() => {
                    console.log('账号切换后重新加载等级信息');
                    this.loadUserTrustLevel(true);
                }, 1000);
            } else if (currentDetectedUser) {
                this.lastDetectedUser = currentDetectedUser;
            }
        }, 5000);
    }

    toggleCleanMode() {
        const sidebarToggle = document.querySelector('button.btn-sidebar-toggle');
        if (sidebarToggle && this.cleanModeEnabled) {
            if (sidebarToggle.getAttribute('aria-expanded') === 'true') {
                console.log('清爽模式启用,收起边栏');
                sidebarToggle.click();
            }
        }
        this.applyCleanModeStyles();
    }

    applyCleanModeStyles() {
        let styleElement = document.getElementById('clean-mode-styles');
        if (styleElement) {
            styleElement.remove();
        }

        if (this.cleanModeEnabled) {
            styleElement = document.createElement('style');
            styleElement.id = 'clean-mode-styles';
            styleElement.textContent = `
                p:contains("希望你喜欢这里。有问题,请提问,或搜索现有帖子。") {
                    display: none !important;
                }
                div#global-notice-alert-global-notice.alert.alert-info.alert-global-notice {
                    display: none !important;
                }
                a[href="https://linux.do/t/topic/482293"] {
                    display: none !important;
                }
                div.link-bottom-line a.badge-category__wrapper {
                    display: none !important;
                }
                td.posters.topic-list-data {
                    display: none !important;
                }
                a.discourse-tag.box[href^="/tag/"] {
                    display: none !important;
                }
            `;
            document.head.appendChild(styleElement);
        }
    }

    toggleGrayscaleMode() {
        this.applyGrayscaleModeStyles();
    }

    applyGrayscaleModeStyles() {
        let styleElement = document.getElementById('grayscale-mode-styles');
        if (styleElement) {
            styleElement.remove();
        }

        if (this.grayscaleModeEnabled) {
            // 检测设备类型
            const isAndroid = /Android/i.test(navigator.userAgent);
            const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
            const isMobile = isAndroid || isIOS;
            const isLowEnd = navigator.hardwareConcurrency <= 4 || navigator.deviceMemory <= 4;

            styleElement = document.createElement('style');
            styleElement.id = 'grayscale-mode-styles';
            styleElement.textContent = `
                /*
                 * 黑白灰模式 - 智能高对比度版
                 * 作者: idear
                 * 协议: CC BY-NC-SA 4.0
                 */

                /* ==================== 浅色背景优化 ==================== */
                @media (prefers-color-scheme: light) {
                    /* 只对主要内容容器应用滤镜,不影响 fixed 定位元素 */
                    #main-outlet, .d-header, .menu-panel, main {
                        filter: grayscale(100%) contrast(108%) brightness(97%) !important;
                        -webkit-filter: grayscale(100%) contrast(108%) brightness(97%) !important;
                    }

                    #main-outlet *, .d-header *, .menu-panel *, main * {
                        text-shadow: 0 0 0.3px rgba(0, 0, 0, 0.4) !important;
                    }
                }

                /* ==================== 深色背景优化 ==================== */
                @media (prefers-color-scheme: dark) {
                    /* 只对主要内容容器应用滤镜,不影响 fixed 定位元素 */
                    #main-outlet, .d-header, .menu-panel, main {
                        filter: grayscale(100%) contrast(110%) brightness(103%) !important;
                        -webkit-filter: grayscale(100%) contrast(110%) brightness(103%) !important;
                    }

                    #main-outlet *, .d-header *, .menu-panel *, main * {
                        text-shadow: 0 0 0.3px rgba(255, 255, 255, 0.5) !important;
                    }
                }

                /* ==================== 兜底方案(无主题偏好) ==================== */
                @media (prefers-color-scheme: no-preference) {
                    #main-outlet, .d-header, .menu-panel, main {
                        filter: grayscale(100%) contrast(109%) brightness(99%) !important;
                        -webkit-filter: grayscale(100%) contrast(109%) brightness(99%) !important;
                    }
                }

                /* ==================== 图片对比度增强 ==================== */
                img, svg, canvas, video {
                    filter: grayscale(100%) contrast(110%) !important;
                    -webkit-filter: grayscale(100%) contrast(110%) !important;
                }

                ${isMobile ? `
                /* ==================== 移动端优化 ==================== */
                html {
                    -webkit-font-smoothing: antialiased !important;
                    -moz-osx-font-smoothing: grayscale !important;
                    text-rendering: optimizeLegibility !important;
                }

                * {
                    -webkit-overflow-scrolling: touch !important;
                }
                ` : ''}

                ${isIOS ? `
                /* ==================== iOS Safari 特殊优化 ==================== */
                body {
                    -webkit-transform: translateZ(0) !important;
                }
                ` : ''}

                ${isLowEnd ? `
                /* ==================== 低端设备优化 ==================== */
                *, *::before, *::after {
                    animation-duration: 0.01ms !important;
                    animation-iteration-count: 1 !important;
                    transition-duration: 0.01ms !important;
                }
                ` : ''}
            `;
            document.head.appendChild(styleElement);

            // GPU 资源释放
            setTimeout(() => {
                if (document.documentElement) {
                    const currentWillChange = document.documentElement.style.willChange;
                    if (currentWillChange === 'filter') {
                        document.documentElement.style.willChange = 'auto';
                    }
                }
            }, 1000);

            // 性能日志
            const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
            const isLight = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches;
            const theme = isDark ? '深色' : (isLight ? '浅色' : '未知');
            console.log('🎨 黑白灰模式已启用');
            console.log(`📱 设备类型: ${isMobile ? (isIOS ? 'iOS' : 'Android') : '桌面'}`);
            console.log(`🔧 优化模式: ${isLowEnd ? '低端设备' : '标准'}`);
            console.log(`🌓 检测主题: ${theme}模式`);
            console.log(`✨ 浅色背景: 对比108% + 亮度97%`);
            console.log(`✨ 深色背景: 对比110% + 亮度103%`);
            console.log(`🖼️  图片对比度: 110%`);
        } else {
            console.log('🎨 黑白灰模式已关闭');
        }
    }

    initOnlyOwnerView() {
        this.createToggleButton();
        this.observePageChanges();
        this.toggleVisibility();
    }

    toggleVisibility() {
        const displayMode = localStorage.getItem("on_off") || "当前查看全部";
        const userId = document.getElementById("post_1")?.getAttribute('data-user-id');
        if (userId) {
            document.querySelectorAll('article').forEach(article => {
                article.style.display = (displayMode === "当前只看楼主" && article.dataset.userId !== userId) ? 'none' : '';
            });
        }
    }

    createToggleButton() {
        if (document.getElementById("toggleVisibilityBtn")) {
            return;
        }

        const btn = document.createElement("button");
        btn.id = "toggleVisibilityBtn";
        btn.textContent = localStorage.getItem("on_off") || "当前查看全部";
        btn.onclick = () => {
            const newText = btn.textContent === '当前查看全部' ? '当前只看楼主' : '当前查看全部';
            document.getElementsByClassName("start-date")[0]?.click();
            btn.textContent = newText;
            localStorage.setItem("on_off", newText);
            this.toggleVisibility();
        };

        btn.style.backgroundColor = "#333";
        btn.style.color = "#FFF";
        btn.style.border = "none";
        btn.style.padding = "8px 16px";
        btn.style.marginLeft = "10px";
        btn.style.borderRadius = "5px";
        btn.style.cursor = "pointer";

        const saveButton = document.querySelector('.save-to-local-btn');
        if (saveButton) {
            saveButton.parentElement.appendChild(btn);
        } else {
            const firstPostContent = document.querySelector('.boxed.onscreen-post[data-post-id] .cooked');
            if (firstPostContent) {
                firstPostContent.appendChild(btn);
            }
        }
    }

    observePageChanges() {
        const observer = new MutationObserver(() => {
            if (document.querySelector(".timeline-footer-controls") && !document.getElementById("toggleVisibilityBtn")) {
                this.createToggleButton();
            }
            this.toggleVisibility();
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    initFloorNumberDisplay() {
        this.addFloorNumbers();
        this.initMutationObserver();
        this.setupRandomJumpButton();
        this.monitorURLChangeAndUpdateButton();
    }

    addFloorNumbers() {
        document.querySelectorAll('.boxed.onscreen-post').forEach((post) => {
            if (!post.querySelector('.floor-number')) {
                const floorNumber = document.createElement('div');
                floorNumber.className = 'floor-number';
                floorNumber.textContent = '楼层: ' + post.id.split("_")[1];
                floorNumber.style.cssText = 'color: grey; margin-left: 10px;';
                post.querySelector('.topic-meta-data').appendChild(floorNumber);
            }
        });
        this.setupSaveButton();
    }

    initMutationObserver() {
        const observer = new MutationObserver(() => {
            this.addFloorNumbers();
            this.setupSaveButton();
            this.toggleCleanMode();
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    randomJump() {
        fetch(window.location.href + '.json')
            .then(response => response.json())
            .then(data => {
                if (data && data.posts_count) {
                    const postId = 1 + Math.floor(Math.random() * data.posts_count);
                    const currentUrl = new URL(window.location.href);
                    const list1 = currentUrl.pathname.split("/");
                    if (list1[list1.length - 2] === "topic") {
                        list1.push(postId);
                    } else if (list1[list1.length - 3] === "topic") {
                        list1[list1.length - 1] = postId;
                    }
                    const newUrl = list1.join("/");
                    window.location.href = newUrl;
                    alert('恭喜楼层【' + postId + '】的用户被抽中!');
                }
            })
            .catch(error => console.error('Error:', error));
    }

    setupRandomJumpButton() {
        // 随机按钮已集成到主面板中,不需要单独创建
    }

    setupSaveButton() {
        const firstPost = document.querySelector('.boxed.onscreen-post[data-post-id]');
        if (firstPost && firstPost.id.includes('post_1')) {
            if (!firstPost.querySelector('.save-to-local-btn')) {
                const saveButton = document.createElement('button');
                saveButton.className = 'save-to-local-btn';
                saveButton.textContent = '💾 保存到本地';
                Object.assign(saveButton.style, {
                    padding: '10px 20px',
                    fontSize: '15px',
                    fontWeight: '600',
                    backgroundColor: '#ff9800',
                    color: 'white',
                    border: 'none',
                    borderRadius: '8px',
                    cursor: 'pointer',
                    marginTop: '10px',
                    boxShadow: '0 4px 12px rgba(255, 152, 0, 0.3)',
                    transition: 'all 0.3s'
                });
                saveButton.addEventListener('mouseover', () => {
                    saveButton.style.transform = 'translateY(-2px)';
                    saveButton.style.boxShadow = '0 6px 20px rgba(255, 152, 0, 0.4)';
                });
                saveButton.addEventListener('mouseout', () => {
                    saveButton.style.transform = 'translateY(0)';
                    saveButton.style.boxShadow = '0 4px 12px rgba(255, 152, 0, 0.3)';
                });
                saveButton.addEventListener('click', () => this.savePostToLocal(firstPost));
                const postContent = firstPost.querySelector('.cooked');
                if (postContent) {
                    postContent.appendChild(saveButton);
                }
            }
        }
    }

    async savePostToLocal(postElement) {
        try {
            const topicTitle = document.querySelector('.fancy-title')?.textContent.trim() || 'Untitled_Topic';
            const postContent = postElement.querySelector('.cooked');
            if (!postContent) {
                alert('无法获取帖子内容!');
                return;
            }

            const contentClone = postContent.cloneNode(true);
            contentClone.querySelector('.save-to-local-btn')?.remove();

            const images = contentClone.querySelectorAll('img');
            for (const img of images) {
                try {
                    const response = await fetch(img.src);
                    const blob = await response.blob();
                    const reader = new FileReader();
                    await new Promise((resolve) => {
                        reader.onload = resolve;
                        reader.readAsDataURL(blob);
                    });
                    img.src = reader.result;
                } catch (error) {
                    console.error('图片加载失败:', img.src, error);
                    img.alt = '[图片加载失败]';
                }
            }

            const htmlContent = `
                <!DOCTYPE html>
                <html lang="zh-CN">
                <head>
                    <meta charset="UTF-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                    <title>${topicTitle}</title>
                    <style>
                        body { font-family: Arial, sans-serif; margin: 20px; }
                        .post-content { max-width: 800px; margin: 0 auto; }
                        img { max-width: 100%; height: auto; }
                    </style>
                </head>
                <body>
                    <div class="post-content">
                        <h1>${topicTitle}</h1>
                        ${contentClone.innerHTML}
                    </div>
                </body>
                </html>
            `;

            const blob = new Blob([htmlContent], { type: 'text/html' });
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            const fileName = topicTitle
                .replace(/[\\/:*?"<>|]/g, '_')
                .replace(/\s+/g, '_')
                + '.html';
            link.download = fileName;
            link.click();
            URL.revokeObjectURL(url);

            alert('帖子内容已保存到本地!');
        } catch (error) {
            console.error('保存帖子失败:', error);
            alert('保存失败,请查看控制台错误信息。');
        }
    }

    monitorURLChangeAndUpdateButton() {
        let lastURL = location.href;

        // 初始检查一次
        this.updateButtonVisibility();

        setInterval(() => {
            const currentURL = location.href;
            if (currentURL !== lastURL) {
                lastURL = currentURL;
                this.isTopicPage = location.pathname.includes('/t/topic/');
                this.updateButtonVisibility();
                this.toggleCleanMode();
                if (this.autoLikeEnabled && currentURL.includes('/t/topic/')) {
                    this.autoLikeTopic();
                }
            }
        }, 1000);
    }

    updateButtonVisibility() {
        const isTopicPage = location.pathname.includes('/t/topic/');

        // 整个工具功能区:只在文章页显示
        if (this.toolSectionContainer) {
            this.toolSectionContainer.style.display = isTopicPage ? 'block' : 'none';
        }

        // 文章页功能区上方的分隔线:只在文章页显示
        if (this.divider2) {
            this.divider2.style.display = isTopicPage ? 'block' : 'none';
        }

        // 文章页功能区下方的分隔线:只在文章页显示
        if (this.divider3) {
            this.divider3.style.display = isTopicPage ? 'block' : 'none';
        }

        console.log(`页面类型: ${isTopicPage ? '文章页' : '非文章页'},文章页功能区${isTopicPage ? '显示' : '隐藏'}`);
    }

    async handleRevealUsersClick() {
        if (this.userInfoHelper.revealInProgress) return;

        // 更新按钮状态
        this.revealUsersBtn.disabled = true;
        this.revealUsersBtn.innerHTML = '<span class="btn-icon">⏳</span><span class="btn-text">加载中...</span>';

        try {
            await this.userInfoHelper.revealAllVisibleReplies();
            this.revealUsersBtn.innerHTML = '<span class="btn-icon">✅</span><span class="btn-text">加载完成</span>';

            // 2秒后恢复按钮
            setTimeout(() => {
                this.revealUsersBtn.disabled = false;
                this.revealUsersBtn.innerHTML = '<span class="btn-icon">📊</span><span class="btn-text">批量展示信息</span>';
            }, 2000);
        } catch (error) {
            console.error('展示用户信息失败:', error);
            this.revealUsersBtn.disabled = false;
            this.revealUsersBtn.innerHTML = '<span class="btn-icon">❌</span><span class="btn-text">加载失败</span>';

            setTimeout(() => {
                this.revealUsersBtn.innerHTML = '<span class="btn-icon">📊</span><span class="btn-text">批量展示信息</span>';
            }, 2000);
        }
    }

    handleButtonClick() {
        if (this.isScrolling || this.autoRunning) {
            // 停止自动阅读
            this.stopScrolling();
            this.stopNavigationGuard();
            this.autoRunning = false;
            this.setSessionStorage('autoRunning', false);
            this.button.innerHTML = '<span class="btn-icon">▶</span><span class="btn-text">开始阅读</span>';
            this.button.classList.remove('running');

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

            // 停止阅读时,折叠自动阅读区
            if (this.autoSectionContent) {
                const autoSection = this.container.querySelector('.section-collapsible');
                if (autoSection && !autoSection.classList.contains('collapsed')) {
                    autoSection.classList.add('collapsed');
                    this.autoSectionContent.classList.add('collapsed');
                }
            }

            // 停止阅读时,展开账号信息区
            if (this.accountSection && this.accountSectionContent) {
                if (this.accountSection.classList.contains('collapsed')) {
                    this.accountSection.classList.remove('collapsed');
                    this.accountSectionContent.classList.remove('collapsed');
                }
            }
        } else {
            // 开启自动阅读
            this.autoRunning = true;
            this.setSessionStorage('autoRunning', true);
            this.button.innerHTML = '<span class="btn-icon">⏸</span><span class="btn-text">停止阅读</span>';
            this.button.classList.add('running');

            // 启动导航守护
            this.startNavigationGuard();

            // 开始阅读时,折叠账号信息区
            if (this.accountSection && this.accountSectionContent) {
                if (!this.accountSection.classList.contains('collapsed')) {
                    this.accountSection.classList.add('collapsed');
                    this.accountSectionContent.classList.add('collapsed');
                }
            }

            // 开始阅读时,展开自动阅读区
            if (this.autoSectionContent) {
                const autoSection = this.container.querySelector('.section-collapsible');
                if (autoSection && autoSection.classList.contains('collapsed')) {
                    autoSection.classList.remove('collapsed');
                    this.autoSectionContent.classList.remove('collapsed');
                }
            }

            if (!this.firstUseChecked) {
                this.handleFirstUse();
            } else if (this.isTopicPage) {
                this.startScrolling();
                if (this.autoLikeEnabled) {
                    this.autoLikeTopic();
                }
            } else {
                this.getLatestTopics().then(() => this.navigateNextTopic());
            }
        }
    }

    async autoLikeTopic() {
        if (!this.autoLikeEnabled) return;

        // 检查是否在冷却期
        if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
            console.log("[自动点赞] 点赞功能冷却中,跳过");
            return;
        }

        const match = window.location.pathname.match(/\/t\/topic\/(\d+)/);
        if (!match) {
            console.log("[自动点赞] 无法获取当前主题ID");
            return;
        }
        const topicId = match[1];

        if (this.likedTopics.includes(topicId)) {
            console.log(`[自动点赞] 主题 ${topicId} 已经点赞过,跳过`);
            return;
        }

        console.log("[自动点赞] 正在检查是否需要点赞主题...");
        await Utils.sleep(2000);

        const likeButton = document.querySelector('div.discourse-reactions-reaction-button button.btn-toggle-reaction-like');
        if (likeButton && !likeButton.classList.contains('has-like') && !likeButton.classList.contains('liked')) {
            likeButton.scrollIntoView({ behavior: 'smooth', block: 'center' });
            await Utils.sleep(1000);
            console.log("[自动点赞] 找到主题点赞按钮,执行点击");
            likeButton.click();

            // 点击后等待一下,检查是否触发冷却
            await Utils.sleep(1000);

            // 如果触发了冷却,直接返回
            if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
                console.log("[自动点赞] 检测到点赞冷却,停止点赞");
                return;
            }

            this.likedTopics.push(topicId);
            Storage.set('likedTopics', this.likedTopics);
            console.log(`[自动点赞] 已记录点赞主题 ${topicId}`);
        } else {
            console.log("[自动点赞] 未找到可点赞的按钮或已点赞");
            if (likeButton && (likeButton.classList.contains('has-like') || likeButton.classList.contains('liked'))) {
                if (!this.likedTopics.includes(topicId)) {
                    this.likedTopics.push(topicId);
                    Storage.set('likedTopics', this.likedTopics);
                    console.log(`[自动点赞] 主题 ${topicId} 已点赞,记录到列表`);
                }
            }
        }
    }

    async quickLikeReplies() {
        // 检查是否在冷却期
        if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
            console.log("[快速点赞] 点赞功能冷却中,跳过");
            return;
        }

        // 获取当前帖子ID
        const match = window.location.pathname.match(/\/t\/topic\/(\d+)/);
        if (!match) {
            console.log("[快速点赞] 无法获取当前主题ID");
            return;
        }
        const topicId = match[1];

        // 获取本帖已点赞的楼层列表
        const likedFloorsInThisTopic = this.quickLikedFloors[topicId] || [];

        // 等待页面加载完成
        await Utils.sleep(2000);

        // 获取所有楼层
        const allPosts = Array.from(document.querySelectorAll('.topic-post'));

        // 筛选出未点赞的楼层
        const availablePosts = allPosts.filter(post => {
            const postNumber = post.getAttribute('data-post-number');
            const floorNumber = postNumber ? parseInt(postNumber) : 0;
            return !likedFloorsInThisTopic.includes(floorNumber);
        });

        // 随机打乱楼层顺序
        const shuffledPosts = availablePosts.sort(() => Math.random() - 0.5);

        const maxLikes = 5;
        let likedCount = 0;

        // 随机选择最多5个楼层进行点赞
        for (let i = 0; i < Math.min(shuffledPosts.length, maxLikes); i++) {
            const post = shuffledPosts[i];

            // 获取楼层号
            const postNumber = post.getAttribute('data-post-number');
            const floorNumber = postNumber ? parseInt(postNumber) : (i + 1);

            const likeButton = post.querySelector('.discourse-reactions-reaction-button button.btn-toggle-reaction-like');

            if (likeButton) {
                // 执行点赞
                likeButton.scrollIntoView({ behavior: 'smooth', block: 'center' });
                await Utils.sleep(500);
                likeButton.click();
                likedCount++;

                // 记录已点赞的楼层
                likedFloorsInThisTopic.push(floorNumber);

                await Utils.sleep(500);

                // 每次点击后检查是否触发了冷却
                if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
                    break; // 立即跳出循环,不再继续点赞
                }
            }
        }

        // 保存点赞记录
        this.quickLikedFloors[topicId] = likedFloorsInThisTopic;
        Storage.set('quickLikedFloors', this.quickLikedFloors);
    }

    async handleFirstUse() {
        if (!this.autoRunning) return;

        // 只在 linux.do 域名下执行新手教程
        if (CURRENT_DOMAIN !== 'linux.do') {
            console.log('非 linux.do 域名,跳过新手教程');
            Storage.set('firstUseChecked', true);
            this.firstUseChecked = true;
            await this.getLatestTopics();
            await this.navigateNextTopic();
            return;
        }

        if (!this.selectedPost) {
            const randomIndex = Math.floor(Math.random() * CONFIG.mustRead.posts.length);
            this.selectedPost = CONFIG.mustRead.posts[randomIndex];
            Storage.set('selectedPost', this.selectedPost);
            console.log(`随机选择文章: ${this.selectedPost.url}`);
            window.location.href = this.selectedPost.url;
            return;
        }

        const currentUrl = window.location.href;
        if (currentUrl.includes(this.selectedPost.url)) {
            console.log(`当前在选中的文章页面,已点赞数: ${this.likesCount}`);
            while (this.likesCount < CONFIG.mustRead.likesNeeded && this.autoRunning) {
                // 检查是否在冷却期,如果是则跳过新手教程的点赞要求
                if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
                    console.log('[新手教程] 点赞功能冷却中,跳过点赞要求,直接开始正常浏览');
                    Storage.set('firstUseChecked', true);
                    this.firstUseChecked = true;
                    await this.getLatestTopics();
                    await this.navigateNextTopic();
                    return;
                }
                
                await this.likeRandomComment();
                if (this.likesCount >= CONFIG.mustRead.likesNeeded) {
                    console.log('完成所需点赞数量,开始正常浏览');
                    Storage.set('firstUseChecked', true);
                    this.firstUseChecked = true;
                    await this.getLatestTopics();
                    await this.navigateNextTopic();
                    break;
                }
                await Utils.sleep(1000);
            }
        } else {
            window.location.href = this.selectedPost.url;
        }
    }

    async likeRandomComment() {
        if (!this.autoRunning) return false;

        // 检查是否在冷却期
        if (this.likeResumeTime && Date.now() < this.likeResumeTime) {
            console.log("点赞功能冷却中,跳过点赞");
            return false;
        }

        const likeButtons = Array.from(document.querySelectorAll('.like-button, .like-count, [data-like-button], .discourse-reactions-reaction-button'))
            .filter(button =>
                button &&
                button.offsetParent !== null &&
                !button.classList.contains('has-like') &&
                !button.classList.contains('liked')
            );

        if (likeButtons.length > 0) {
            const randomButton = likeButtons[Math.floor(Math.random() * likeButtons.length)];
            randomButton.scrollIntoView({ behavior: 'smooth', block: 'center' });
            await Utils.sleep(1000);

            if (!this.autoRunning) return false;
            console.log('找到可点赞的评论,准备点赞');
            randomButton.click();
            this.likesCount++;
            Storage.set('likesCount', this.likesCount);
            await Utils.sleep(1000);
            return true;
        }

        window.scrollBy({
            top: 500,
            behavior: 'smooth'
        });
        await Utils.sleep(1000);
        console.log('当前位置没有找到可点赞的评论,继续往下找');
        return false;
    }

    async getLatestTopics() {
        let page = 1;
        let topicList = [];
        let retryCount = 0;

        // 根据设置选择获取最新帖子还是未读帖子
        const endpoint = this.readUnreadEnabled ? 'unread' : 'latest';
        console.log(`正在获取${this.readUnreadEnabled ? '未读' : '最新'}帖子列表...`);

        while (topicList.length < CONFIG.article.topicListLimit && retryCount < CONFIG.article.retryLimit) {
            try {
                const response = await fetch(`${BASE_URL}/${endpoint}.json?no_definitions=true&page=${page}`);
                const data = await response.json();

                if (data?.topic_list?.topics) {
                    const filteredTopics = data.topic_list.topics.filter(topic =>
                        topic.posts_count < CONFIG.article.commentLimit
                    );
                    topicList.push(...filteredTopics);
                    page++;

                    // 如果是未读帖子且没有更多了,直接退出
                    if (this.readUnreadEnabled && filteredTopics.length === 0) {
                        break;
                    }
                } else {
                    break;
                }
            } catch (error) {
                console.error('获取文章列表失败:', error);
                retryCount++;
                await Utils.sleep(1000);
            }
        }

        if (topicList.length > CONFIG.article.topicListLimit) {
            topicList = topicList.slice(0, CONFIG.article.topicListLimit);
        }

        this.topicList = topicList;
        this.setSessionStorage('topicList', topicList);
        console.log(`已获取 ${topicList.length} 篇${this.readUnreadEnabled ? '未读' : '最新'}文章`);

        // 如果未读帖子为空,提示用户
        if (this.readUnreadEnabled && topicList.length === 0) {
            this.showNotification('📭 没有未读帖子,将切换到最新帖子');
            this.readUnreadEnabled = false;
            Storage.set('readUnreadEnabled', false);
            // 重新获取最新帖子
            await this.getLatestTopics();
        }
    }

    async getNextTopic() {
        if (this.topicList.length === 0) {
            await this.getLatestTopics();
        }

        if (this.topicList.length > 0) {
            const topic = this.topicList.shift();
            this.setSessionStorage('topicList', this.topicList);
            return topic;
        }

        return null;
    }

    async startScrolling() {
        if (this.isScrolling) return;

        this.isScrolling = true;
        this.button.innerHTML = '<span class="btn-icon">⏸</span><span class="btn-text">停止阅读</span>';
        this.button.classList.add('running');
        this.lastActionTime = Date.now();

        // 在开始滚动前,先执行点赞操作
        if (this.isTopicPage) {
            if (this.autoLikeEnabled) {
                await this.autoLikeTopic();
            } else if (this.quickLikeEnabled) {
                await this.quickLikeReplies();
            }
        }

        // 记录页面开始滚动的时间,用于强制跳转
        this.scrollStartTime = Date.now();
        // 设置最大滚动时间(30秒),超过后强制跳转,避免卡在一个页面
        const maxScrollTime = 30000; // 30秒

        while (this.isScrolling) {
            const speed = Utils.random(CONFIG.scroll.minSpeed, CONFIG.scroll.maxSpeed);
            const distance = Utils.random(CONFIG.scroll.minDistance, CONFIG.scroll.maxDistance);
            const scrollStep = distance * 2.5;

            window.scrollBy({
                top: scrollStep,
                behavior: 'smooth'
            });

            // 检查是否到达底部
            if (Utils.isNearBottom()) {
                await Utils.sleep(800);

                if (Utils.isNearBottom() && Utils.isPageLoaded()) {
                    console.log("已到达页面底部,准备导航到下一篇文章...");
                    await Utils.sleep(1000);
                    await this.navigateNextTopic();
                    break;
                }
            }

            // 强制跳转检查:如果在当前页面滚动超过最大时间,强制跳转到下一篇
            const scrolledTime = Date.now() - this.scrollStartTime;
            if (scrolledTime > maxScrollTime) {
                console.log(`已在当前页面滚动${Math.floor(scrolledTime/1000)}秒,强制跳转到下一篇文章...`);
                await this.navigateNextTopic();
                break;
            }

            await Utils.sleep(speed);
            this.accumulateTime();

            if (Math.random() < CONFIG.scroll.fastScrollChance) {
                const fastScroll = Utils.random(CONFIG.scroll.fastScrollMin, CONFIG.scroll.fastScrollMax);
                window.scrollBy({
                    top: fastScroll,
                    behavior: 'smooth'
                });
                await Utils.sleep(200);
            }
        }
    }

    async waitForPageLoad() {
        let attempts = 0;
        const maxAttempts = 5;

        while (attempts < maxAttempts) {
            if (Utils.isPageLoaded()) {
                return true;
            }
            await Utils.sleep(300);
            attempts++;
        }

        return false;
    }

    stopScrolling() {
        this.isScrolling = false;
        clearInterval(this.scrollInterval);
        clearTimeout(this.pauseTimeout);
        this.button.innerHTML = '<span class="btn-icon">▶</span><span class="btn-text">开始阅读</span>';
        this.button.classList.remove('running');
    }

    accumulateTime() {
        const now = Date.now();
        this.accumulatedTime += now - this.lastActionTime;
        this.setSessionStorage('accumulatedTime', this.accumulatedTime);
        this.lastActionTime = now;

        if (this.accumulatedTime >= CONFIG.time.browseTime) {
            this.accumulatedTime = 0;
            this.setSessionStorage('accumulatedTime', 0);
            this.pauseForRest();
        }
    }

    async pauseForRest() {
        this.stopScrolling();
        const restMinutes = Math.floor(CONFIG.time.restTime / 60000);
        console.log(`休息${restMinutes}分钟...`);

        // 显示休息开始通知
        this.showNotification(`⏸️ 开始休息 ${restMinutes} 分钟`);

        await Utils.sleep(CONFIG.time.restTime);

        console.log("休息结束,继续浏览...");

        // 显示休息结束通知
        this.showNotification(`✅ 休息结束,继续浏览`);

        this.startScrolling();
    }

    async navigateNextTopic() {
        const nextTopic = await this.getNextTopic();
        if (nextTopic) {
            console.log("导航到新文章:", nextTopic.title);

            // 保存当前帖子为已读
            const currentMatch = window.location.pathname.match(/\/t\/topic\/(\d+)/);
            if (currentMatch) {
                const currentTopicId = currentMatch[1];
                await this.saveUserReadHistory(currentTopicId);
            }

            const url = nextTopic.last_read_post_number
                ? `${BASE_URL}/t/topic/${nextTopic.id}/${nextTopic.last_read_post_number}`
                : `${BASE_URL}/t/topic/${nextTopic.id}`;

            console.log("正在跳转到:", url);

            // 设置跳转超时保护 - 如果10秒内没有跳转成功,强制重新跳转
            this.navigationTimeout = setTimeout(() => {
                console.warn("⚠️ 跳转超时,尝试重新跳转...");
                if (window.location.href !== url) {
                    window.location.href = url;
                }
            }, 10000);

            // 直接跳转
            window.location.href = url;
        } else {
            console.log("没有更多文章,返回首页");
            window.location.href = `${BASE_URL}/latest`;
        }
    }

    resetFirstUse() {
        Storage.set('firstUseChecked', false);
        Storage.set('likesCount', 0);
        Storage.set('selectedPost', null);
        this.firstUseChecked = false;
        this.likesCount = 0;
        this.selectedPost = null;
        console.log('已重置首次使用状态');
    }

    // 加载 Credit 积分信息
    async loadCreditInfo(isManualRefresh = false) {
        if (!this.creditContainer) return;

        // 显示加载状态
        if (isManualRefresh) {
            const refreshBtn = this.creditContainer.querySelector('.credit-refresh-btn');
            if (refreshBtn) {
                refreshBtn.textContent = '刷新中...';
                refreshBtn.disabled = true;
            }
        } else {
            this.creditContainer.innerHTML = '<div class="trust-level-loading">加载积分信息...</div>';
        }

        try {
            // 使用 GM_xmlhttpRequest 获取用户信息
            const userData = await this.fetchCreditUserInfo();
            if (!userData) {
                this.renderCreditError('请先登录 credit.linux.do', true);
                return;
            }

            // 获取每日统计
            const dailyStats = await this.fetchCreditDailyStats();

            // 获取排行榜数据(明日积分)
            const leaderboardData = await this.fetchLeaderboardData();

            // 渲染数据
            this.renderCreditInfo(userData, dailyStats, leaderboardData);

        } catch (error) {
            console.error('加载 Credit 信息失败:', error);
            this.renderCreditError('加载失败,请稍后重试');
        }
    }

    // 获取 Credit 用户信息
    fetchCreditUserInfo() {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: 'https://credit.linux.do/api/v1/oauth/user-info',
                withCredentials: true,
                headers: {
                    'Accept': 'application/json',
                    'Referer': 'https://credit.linux.do/home'
                },
                onload: (response) => {
                    if (response.status === 200) {
                        try {
                            const json = JSON.parse(response.responseText);
                            if (json && json.data) {
                                resolve(json.data);
                                return;
                            }
                        } catch (e) {
                            console.error('Credit API 解析错误:', e);
                        }
                    }
                    resolve(null);
                },
                onerror: (error) => {
                    console.error('Credit API 请求错误:', error);
                    reject(error);
                },
                ontimeout: () => {
                    reject(new Error('请求超时'));
                }
            });
        });
    }

    // 获取 Credit 每日统计
    fetchCreditDailyStats() {
        return new Promise((resolve) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: 'https://credit.linux.do/api/v1/dashboard/stats/daily?days=7',
                withCredentials: true,
                headers: {
                    'Accept': 'application/json',
                    'Referer': 'https://credit.linux.do/home'
                },
                onload: (response) => {
                    if (response.status === 200) {
                        try {
                            const json = JSON.parse(response.responseText);
                            if (json && json.data && Array.isArray(json.data)) {
                                resolve(json.data);
                                return;
                            }
                        } catch (e) {
                            console.error('Credit 每日统计解析错误:', e);
                        }
                    }
                    resolve([]);
                },
                onerror: () => resolve([]),
                ontimeout: () => resolve([])
            });
        });
    }

    // 获取排行榜数据(明日积分)
    fetchLeaderboardData() {
        return new Promise((resolve) => {
            // 使用普通 fetch 请求 linux.do 的排行榜 API
            fetch('https://linux.do/leaderboard/1.json?period=daily', {
                credentials: 'include',
                headers: {
                    'Accept': 'application/json'
                }
            })
            .then(response => {
                if (response.ok) {
                    return response.json();
                }
                throw new Error('请求失败');
            })
            .then(data => {
                if (data && data.personal && data.personal.user) {
                    resolve({
                        tomorrowCredits: data.personal.user.total_score || 0,
                        rank: data.personal.position || data.personal.user.position || 0
                    });
                } else {
                    resolve(null);
                }
            })
            .catch(error => {
                console.error('获取排行榜数据失败:', error);
                resolve(null);
            });
        });
    }

    // 渲染 Credit 信息
    renderCreditInfo(userData, dailyStats, leaderboardData = null) {
        const credits = userData.available_balance || '0';
        const dailyLimit = userData.remain_quota || '0';
        const incomeTotal = userData.total_receive || '0';
        const expenseTotal = userData.total_payment || '0';
        const username = userData.nickname || userData.username || 'User';

        // 处理每日统计
        let incomeList = [];
        let expenseList = [];
        if (dailyStats && dailyStats.length > 0) {
            dailyStats.forEach(item => {
                const date = item.date.substring(5).replace('-', '/');
                const income = parseFloat(item.income) || 0;
                const expense = parseFloat(item.expense) || 0;
                if (income > 0) incomeList.push({ date, amount: '+' + income.toFixed(2) });
                if (expense > 0) expenseList.push({ date, amount: '-' + expense.toFixed(2) });
            });
            incomeList.reverse();
            expenseList.reverse();
        }

        const updateTime = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });

        let html = `
            <div class="trust-level-header">
                <span>💰 ${this.escapeHtml(username)} 的积分</span>
                <button class="trust-level-refresh credit-refresh-btn" data-action="refresh-credit">🔄 刷新</button>
            </div>
            <div class="credit-main-stat">
                <span class="credit-stat-label">可用积分</span>
                <span class="credit-stat-value">${this.escapeHtml(credits)}</span>
            </div>
        `;

        // 明日积分(来自排行榜)
        if (leaderboardData) {
            html += `
            <div class="trust-level-item">
                <span class="trust-level-name">🌟 明日积分</span>
                <span class="trust-level-value" style="color: #ffd700; font-weight: bold;">${this.escapeHtml(leaderboardData.tomorrowCredits)}</span>
            </div>
            <div class="trust-level-item">
                <span class="trust-level-name">📊 今日排名</span>
                <span class="trust-level-value" style="color: #87ceeb;">#${this.escapeHtml(leaderboardData.rank)}</span>
            </div>
            `;
        }

        html += `
            <div class="trust-level-item">
                <span class="trust-level-name">今日剩余额度</span>
                <span class="trust-level-value" style="color: #fff;">${this.escapeHtml(dailyLimit)}</span>
            </div>
            <div class="trust-level-item">
                <span class="trust-level-name">总收入</span>
                <span class="trust-level-value" style="color: #7dffb3;">+${this.escapeHtml(incomeTotal)}</span>
            </div>
            <div class="trust-level-item">
                <span class="trust-level-name">总支出</span>
                <span class="trust-level-value" style="color: #ff9999;">-${this.escapeHtml(expenseTotal)}</span>
            </div>
        `;

        // 近7天收入
        if (incomeList.length > 0) {
            html += `<div class="credit-section-title">近7天收入</div>`;
            incomeList.slice(0, 3).forEach(item => {
                html += `
                    <div class="trust-level-item">
                        <span class="trust-level-name">${this.escapeHtml(item.date)}</span>
                        <span class="trust-level-value" style="color: #7dffb3;">${this.escapeHtml(item.amount)}</span>
                    </div>
                `;
            });
        }

        // 近7天支出
        if (expenseList.length > 0) {
            html += `<div class="credit-section-title">近7天支出</div>`;
            expenseList.slice(0, 3).forEach(item => {
                html += `
                    <div class="trust-level-item">
                        <span class="trust-level-name">${this.escapeHtml(item.date)}</span>
                        <span class="trust-level-value" style="color: #ff9999;">${this.escapeHtml(item.amount)}</span>
                    </div>
                `;
            });
        }

        html += `
            <div class="credit-footer">
                <a href="https://credit.linux.do/home" target="_blank" class="credit-link">查看详情 →</a>
                <span class="credit-update-time">更新: ${this.escapeHtml(updateTime)}</span>
            </div>
        `;

        this.creditContainer.innerHTML = html;

        // 添加刷新按钮事件
        setTimeout(() => {
            const refreshBtn = this.creditContainer.querySelector('.credit-refresh-btn');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    this.loadCreditInfo(true);
                });
            }
        }, 100);
    }

    // 渲染 Credit 错误
    renderCreditError(message, showLogin = false) {
        let html = `
            <div class="trust-level-header">
                <span>💰 Credit 积分</span>
                <button class="trust-level-refresh credit-refresh-btn" data-action="refresh-credit">🔄 刷新</button>
            </div>
            <div class="trust-level-loading">${this.escapeHtml(message)}</div>
        `;

        if (showLogin) {
            html += `
                <div class="credit-footer">
                    <a href="https://credit.linux.do" target="_blank" class="credit-login-btn">去登录</a>
                </div>
            `;
        }

        this.creditContainer.innerHTML = html;

        // 添加刷新按钮事件
        setTimeout(() => {
            const refreshBtn = this.creditContainer.querySelector('.credit-refresh-btn');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    this.loadCreditInfo(true);
                });
            }
        }, 100);
    }

    // HTML 转义
    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = String(text);
        return div.innerHTML;
    }
}

// 初始化
(function() {
    window.browseController = new BrowseController();
})();