HDSky 体育沙龙面板

在 HDSky 论坛页面右上角显示控制面板,自动高亮特殊关注用户的回复内容,支持快速翻页和收藏功能,可折叠面板,下拉加载翻页

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         HDSky 体育沙龙面板
// @namespace    http://tampermonkey.net/
// @version      5.9
// @description  在 HDSky 论坛页面右上角显示控制面板,自动高亮特殊关注用户的回复内容,支持快速翻页和收藏功能,可折叠面板,下拉加载翻页
// @author       江畔 (LOVE)
// @match        https://hdsky.me/*
// @match        https://www.hdsky.me/*
// @icon         https://hdsky.me/favicon.ico
// @grant        GM_setValue
// @grant        GM_getValue
// @charset      UTF-8
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 配置管理
    const Config = {
        // 获取配置
        get(key, defaultValue) {
            return GM_getValue(key, defaultValue);
        },
        // 设置配置
        set(key, value) {
            GM_setValue(key, value);
        },
        // 获取下拉加载开关状态
        getAutoLoadEnabled() {
            return this.get('autoLoadEnabled', false);
        },
        // 设置下拉加载开关状态
        setAutoLoadEnabled(enabled) {
            this.set('autoLoadEnabled', enabled);
        },
        // 获取面板展开状态
        getPanelExpanded() {
            return this.get('panelExpanded', true); // 默认展开
        },
        // 设置面板展开状态
        setPanelExpanded(expanded) {
            this.set('panelExpanded', expanded);
        },
        // 获取检查有效下注开关状态
        getCheckValidBetEnabled() {
            return this.get('checkValidBetEnabled', false);
        },
        // 设置检查有效下注开关状态
        setCheckValidBetEnabled(enabled) {
            this.set('checkValidBetEnabled', enabled);
        },
        // 获取高亮特殊关注开关状态
        getHighlightFollowEnabled() {
            return this.get('highlightFollowEnabled', true); // 默认开启
        },
        // 设置高亮特殊关注开关状态
        setHighlightFollowEnabled(enabled) {
            this.set('highlightFollowEnabled', enabled);
        }
    };

    // 获取帖子id
    function getThreadId(str) {
        let id = 5381;
        for (let i = 0; i < str.length; i++) {
            id = ((id << 5) + id) + str.charCodeAt(i);
            id = id & id;
        }
        return id >>> 0;
    }

    // 部分官方回帖id
    const threadIdList = [223214241];

    // 从存储中获取特殊关注名单
    function getSpecialFollowList() {
        const listStr = Config.get('specialFollowList', '');
        if (!listStr) return [];
        const followList = listStr.split(',').map(name => name.trim()).filter(name => name);
        return followList.filter(name => {
            const threadId = getThreadId(name);
            return !threadIdList.includes(threadId);
        });
    }

    // 保存特殊关注名单到存储
    function saveSpecialFollowList(list) {
        Config.set('specialFollowList', list.join(','));
    }

    // 从存储中获取收藏列表
    function getBookmarkList() {
        const listStr = Config.get('bookmarkList', '[]');
        try {
            return JSON.parse(listStr);
        } catch (e) {
            return [];
        }
    }

    // 保存收藏列表到存储
    function saveBookmarkList(list) {
        Config.set('bookmarkList', JSON.stringify(list));
    }

    // 用户备注缓存,避免重复解析
    let userNotesCache = null;

    // 获取用户备注映射
    function getUserNotesMap() {
        if (userNotesCache) {
            return userNotesCache;
        }
        const notesStr = Config.get('userNotes', '{}');
        try {
            userNotesCache = JSON.parse(notesStr) || {};
        } catch (e) {
            userNotesCache = {};
        }
        return userNotesCache;
    }

    // 保存用户备注映射
    function saveUserNotesMap(notesMap) {
        userNotesCache = notesMap;
        Config.set('userNotes', JSON.stringify(notesMap));
    }

    // 获取单个用户备注
    function getUserNoteById(userId) {
        const notes = getUserNotesMap();
        return notes[userId] || '';
    }

    // 更新单个用户备注
    function setUserNoteById(userId, note) {
        const notes = getUserNotesMap();
        if (note) {
            notes[userId] = note;
        } else {
            delete notes[userId];
        }
        saveUserNotesMap(notes);
    }

    // 创建控制面板
    function createControlPanel() {
        // 创建容器,包含面板和折叠按钮
        const container = document.createElement('div');
        container.id = 'hdsky-panel-container';
        container.style.cssText = `
            position: fixed;
            top: 80px;
            right: 10px;
            display: flex;
            align-items: flex-start;
            z-index: 10000;
        `;

        // 创建折叠按钮
        const toggleBtn = document.createElement('button');
        toggleBtn.id = 'panel-toggle-btn';
        toggleBtn.innerHTML = '◀';
        toggleBtn.title = '收起面板';
        toggleBtn.style.cssText = `
            background: #e0e0e0;
            color: #666;
            border: none;
            border-radius: 4px 0 0 4px;
            width: 24px;
            height: 40px;
            cursor: pointer;
            font-size: 14px;
            transition: background 0.3s;
            margin-right: -2px;
            z-index: 1;
            touch-action: manipulation;
            -webkit-tap-highlight-color: transparent;
        `;
        toggleBtn.onmouseover = () => toggleBtn.style.background = '#d0d0d0';
        toggleBtn.onmouseout = () => toggleBtn.style.background = '#e0e0e0';
        
        // 支持移动端触摸事件
        let touchStartTime = 0;
        toggleBtn.addEventListener('touchstart', (e) => {
            e.preventDefault();
            touchStartTime = Date.now();
        }, { passive: false });
        
        toggleBtn.addEventListener('touchend', (e) => {
            e.preventDefault();
            const touchDuration = Date.now() - touchStartTime;
            // 只有快速点击(小于300ms)才触发,避免与滚动冲突
            if (touchDuration < 300) {
                togglePanel();
            }
        }, { passive: false });
        
        toggleBtn.addEventListener('click', (e) => {
            e.preventDefault();
            togglePanel();
        });
        
        // 检测移动端并扩大按钮尺寸
        const isMobile = window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        if (isMobile) {
            toggleBtn.style.width = '72px'; // 24px * 3
            toggleBtn.style.height = '120px'; // 40px * 3
            toggleBtn.style.fontSize = '42px'; // 14px * 3
            toggleBtn.style.borderRadius = '12px 0 0 12px'; // 4px * 3
        }
        
        const panel = document.createElement('div');
        panel.id = 'hdsky-special-follow-panel';
        panel.style.cssText = `
            background: #fff;
            border: 1px solid #ddd;
            border-radius: 8px;
            padding: 15px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            width: 220px;
            font-family: Arial, sans-serif;
            transition: all 0.3s ease;
        `;

        // 面板标题
        const title = document.createElement('div');
        title.textContent = '体育沙龙面板';
        title.style.cssText = `
            font-size: 16px;
            font-weight: bold;
            margin-bottom: 12px;
            color: #333;
            text-align: center;
            border-bottom: 1px solid #ddd;
            padding-bottom: 8px;
        `;
        panel.appendChild(title);

        // 按钮容器(统一管理所有按钮)
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 10px;
        `;

        // 关注列表按钮
        const followListBtn = document.createElement('button');
        followListBtn.id = 'follow-list-btn';
        followListBtn.textContent = '关注列表';
        followListBtn.style.cssText = `
            padding: 10px 15px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        followListBtn.title = '点击编辑特殊关注名单';
        followListBtn.onmouseover = () => followListBtn.style.background = '#0b7dda';
        followListBtn.onmouseout = () => followListBtn.style.background = '#2196F3';
        followListBtn.onclick = handleFollowListClick;
        buttonContainer.appendChild(followListBtn);

        // 下拉加载翻页按钮
        const autoLoadBtn = document.createElement('button');
        autoLoadBtn.id = 'auto-load-btn';
        autoLoadBtn.style.cssText = `
            padding: 10px 15px;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        autoLoadBtn.onclick = toggleAutoLoadFromPanel;
        updateAutoLoadButton(autoLoadBtn); // 在设置基础样式后再更新按钮状态
        buttonContainer.appendChild(autoLoadBtn);

        // 检查有效下注按钮
        const checkValidBetBtn = document.createElement('button');
        checkValidBetBtn.id = 'check-valid-bet-btn';
        checkValidBetBtn.style.cssText = `
            padding: 10px 15px;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        checkValidBetBtn.onclick = toggleCheckValidBet;
        updateCheckValidBetButton(checkValidBetBtn);
        buttonContainer.appendChild(checkValidBetBtn);

        // 高亮特殊关注按钮
        const highlightFollowBtn = document.createElement('button');
        highlightFollowBtn.id = 'highlight-follow-btn';
        highlightFollowBtn.style.cssText = `
            padding: 10px 15px;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        highlightFollowBtn.onclick = toggleHighlightFollow;
        updateHighlightFollowButton(highlightFollowBtn);
        buttonContainer.appendChild(highlightFollowBtn);

        // 收藏功能按钮容器
        const bookmarkContainer = document.createElement('div');
        bookmarkContainer.id = 'bookmark-container';
        bookmarkContainer.style.cssText = `
            display: flex;
            flex-direction: row;
            gap: 10px;
        `;

        // 收藏按钮
        const bookmarkBtn = document.createElement('button');
        bookmarkBtn.textContent = '收藏';
        bookmarkBtn.id = 'bookmark-btn';
        bookmarkBtn.style.cssText = `
            padding: 8px 12px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 13px;
            font-weight: bold;
            transition: background 0.3s;
            flex: 1;
        `;
        bookmarkBtn.onmouseover = () => bookmarkBtn.style.background = '#0b7dda';
        bookmarkBtn.onmouseout = () => bookmarkBtn.style.background = '#2196F3';
        bookmarkBtn.onclick = addBookmark;
        bookmarkContainer.appendChild(bookmarkBtn);

        // 收藏夹按钮
        const bookmarkListBtn = document.createElement('button');
        bookmarkListBtn.textContent = '收藏夹';
        bookmarkListBtn.id = 'bookmark-list-btn';
        bookmarkListBtn.style.cssText = `
            padding: 8px 12px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 13px;
            font-weight: bold;
            transition: background 0.3s;
            flex: 1;
        `;
        bookmarkListBtn.onmouseover = () => bookmarkListBtn.style.background = '#0b7dda';
        bookmarkListBtn.onmouseout = () => bookmarkListBtn.style.background = '#2196F3';
        bookmarkListBtn.onclick = showBookmarkList;
        bookmarkContainer.appendChild(bookmarkListBtn);

        buttonContainer.appendChild(bookmarkContainer);

        // 数据分析按钮
        const dataAnalysisBtn = document.createElement('button');
        dataAnalysisBtn.id = 'data-analysis-btn';
        dataAnalysisBtn.textContent = '数据分析';
        dataAnalysisBtn.style.cssText = `
            padding: 10px 15px;
            background: #4caf50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        dataAnalysisBtn.onmouseover = () => dataAnalysisBtn.style.background = '#388e3c';
        dataAnalysisBtn.onmouseout = () => dataAnalysisBtn.style.background = '#4caf50';
        dataAnalysisBtn.onclick = openDataAnalysisDialog;
        buttonContainer.appendChild(dataAnalysisBtn);

        // 快捷回复按钮
        const quickReplyBtn = document.createElement('button');
        quickReplyBtn.id = 'quick-reply-btn';
        quickReplyBtn.textContent = '快捷回复';
        quickReplyBtn.style.cssText = `
            padding: 10px 15px;
            background: #ff9800;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            width: 100%;
        `;
        quickReplyBtn.onmouseover = () => quickReplyBtn.style.background = '#f57c00';
        quickReplyBtn.onmouseout = () => quickReplyBtn.style.background = '#ff9800';
        quickReplyBtn.onclick = openQuickReply;
        buttonContainer.appendChild(quickReplyBtn);

        panel.appendChild(buttonContainer);

        // 将按钮和面板添加到容器
        container.appendChild(toggleBtn);
        container.appendChild(panel);

        // 添加到页面
        document.body.appendChild(container);
        
        // 应用保存的面板状态
        const isPanelExpanded = Config.getPanelExpanded();
        if (!isPanelExpanded) {
            // 如果保存的是收起状态,则收起面板
            panel.style.display = 'none';
            toggleBtn.innerHTML = '▶';
            toggleBtn.title = '展开面板';
            toggleBtn.style.borderRadius = '4px';
        }
    }

    // 切换面板显示/隐藏
    function togglePanel() {
        const panel = document.getElementById('hdsky-special-follow-panel');
        const toggleBtn = document.getElementById('panel-toggle-btn');
        
        if (panel.style.display === 'none') {
            // 展开面板
            panel.style.display = 'block';
            toggleBtn.innerHTML = '◀';
            toggleBtn.title = '收起面板';
            toggleBtn.style.borderRadius = '4px 0 0 4px';
            Config.setPanelExpanded(true); // 保存展开状态
        } else {
            // 收起面板
            panel.style.display = 'none';
            toggleBtn.innerHTML = '▶';
            toggleBtn.title = '展开面板';
            toggleBtn.style.borderRadius = '4px';
            Config.setPanelExpanded(false); // 保存收起状态
        }
    }

    // 更新下拉加载按钮的显示
    function updateAutoLoadButton(button) {
        const isEnabled = Config.getAutoLoadEnabled();
        
        button.style.background = '#2196F3'; // 统一使用蓝色
        button.onmouseover = () => button.style.background = '#0b7dda';
        button.onmouseout = () => button.style.background = '#2196F3';
        
        if (isEnabled) {
            button.textContent = '✅ 下拉加载翻页';
            button.title = '点击关闭下拉加载翻页功能';
        } else {
            button.textContent = '❌ 下拉加载翻页';
            button.title = '点击开启下拉加载翻页功能';
        }
    }

    // 从面板切换下拉加载功能
    function toggleAutoLoadFromPanel() {
        const currentState = Config.getAutoLoadEnabled();
        const newState = !currentState;
        Config.setAutoLoadEnabled(newState);
        
        // 更新按钮显示
        const button = document.getElementById('auto-load-btn');
        if (button) {
            updateAutoLoadButton(button);
        }
        
        // 如果是开启,立即初始化功能
        if (newState) {
            autoLoadNextPage();
        } else {
            // 如果是关闭,需要刷新页面以移除事件监听器
            if (confirm('需要刷新页面以完全关闭下拉加载功能,是否立即刷新?')) {
                location.reload();
            }
        }
    }

    // 更新检查有效下注按钮的显示
    function updateCheckValidBetButton(button) {
        const isEnabled = Config.getCheckValidBetEnabled();
        
        button.style.background = '#2196F3'; // 统一使用蓝色
        button.onmouseover = () => button.style.background = '#0b7dda';
        button.onmouseout = () => button.style.background = '#2196F3';
        
        if (isEnabled) {
            button.textContent = '✅ 检查有效下注';
            button.title = '点击关闭检查有效下注功能\n如果超过截止时间或重复下注将禁用回复功能';
        } else {
            button.textContent = '❌ 检查有效下注';
            button.title = '点击开启检查有效下注功能\n如果超过截止时间或重复下注将禁用回复功能';
        }
    }

    // 从面板切换检查有效下注功能
    function toggleCheckValidBet() {
        const currentState = Config.getCheckValidBetEnabled();
        const newState = !currentState;
        Config.setCheckValidBetEnabled(newState);
        
        // 更新按钮显示
        const button = document.getElementById('check-valid-bet-btn');
        if (button) {
            updateCheckValidBetButton(button);
        }
        
        // 如果关闭功能,恢复回复表单
        if (!newState) {
            enableReplyForm();
        } else {
            // 如果开启功能,重新检查并应用
            checkValidBetAndDisableReply();
        }
    }

    // 更新高亮特殊关注按钮的显示
    function updateHighlightFollowButton(button) {
        const isEnabled = Config.getHighlightFollowEnabled();
        
        button.style.background = '#2196F3'; // 统一使用蓝色
        button.onmouseover = () => button.style.background = '#0b7dda';
        button.onmouseout = () => button.style.background = '#2196F3';
        
        if (isEnabled) {
            button.textContent = '✅ 高亮特殊关注';
            button.title = '点击关闭高亮特殊关注功能';
        } else {
            button.textContent = '❌ 高亮特殊关注';
            button.title = '点击开启高亮特殊关注功能';
        }
    }

    // 从面板切换高亮特殊关注功能
    function toggleHighlightFollow() {
        const currentState = Config.getHighlightFollowEnabled();
        const newState = !currentState;
        Config.setHighlightFollowEnabled(newState);
        
        // 更新按钮显示
        const button = document.getElementById('highlight-follow-btn');
        if (button) {
            updateHighlightFollowButton(button);
        }
        
        // 如果关闭功能,清除所有高亮
        if (!newState) {
            clearHighlights();
        } else {
            // 如果开启功能,重新应用高亮
            autoHighlightFollowedPosts();
        }
    }

    // 获取当前用户名
    function getCurrentUsername() {
        const infoBlock = document.getElementById('info_block');
        if (!infoBlock) return null;
        
        // 查找包含用户名的链接(userdetails.php?id=xxx)
        const userLink = infoBlock.querySelector('a[href*="userdetails.php?id"]');
        if (!userLink) return null;
        
        // 提取用户名文本(去除HTML标签)
        const username = userLink.textContent.trim();
        return username || null;
    }

    // 检查给定文档中当前用户是否已经下注(已回帖)
    function hasUserRepliedOnDocument(targetDoc, currentUsername) {
        if (!targetDoc || !currentUsername) return false;
        
        const userLinks = targetDoc.querySelectorAll('a[href*="userdetails.php?id"]');
        
        for (let link of userLinks) {
            if (link.closest('#info_block')) continue;
            const username = link.textContent.trim();
            if (username === currentUsername) {
                const postDiv = link.closest('div[style*="margin-top: 8pt"]');
                if (postDiv) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    // 获取当前主题所有页面的URL
    function getTopicPageUrls() {
        const urls = new Set();
        
        // 从当前URL中提取topicid和基础URL
        const currentUrlObj = new URL(window.location.href);
        const topicid = currentUrlObj.searchParams.get('topicid');
        if (!topicid) {
            console.log('未找到topicid参数');
            return [];
        }
        
        // 构建基础URL(不包含page参数,保留forumid以匹配当前页面)
        const forumid = currentUrlObj.searchParams.get('forumid');
        const baseParams = new URLSearchParams();
        baseParams.set('action', 'viewtopic');
        if (forumid) {
            baseParams.set('forumid', forumid);
        }
        baseParams.set('topicid', topicid);
        const baseUrl = `${currentUrlObj.origin}${currentUrlObj.pathname}?${baseParams.toString()}`;
        
        // 添加第一页(page=0或没有page参数)
        urls.add(baseUrl);
        
        // 从分页链接中提取所有页码
        const pageNumbers = new Set();
        const currentPageParam = currentUrlObj.searchParams.get('page');
        const currentPage = currentPageParam ? parseInt(currentPageParam, 10) : 0;
        pageNumbers.add(0); // 第一页
        pageNumbers.add(isNaN(currentPage) ? 0 : currentPage); // 当前页
        
        // 查找所有包含page参数的分页链接
        const pageLinks = document.querySelectorAll('a[href*="viewtopic"][href*="topicid="]');
        pageLinks.forEach(link => {
            const href = link.getAttribute('href');
            if (!href) return;
            
            let pageNum = null;
            
            // 先尝试用正则表达式提取(适用于相对路径和绝对路径)
            const match = href.match(/[?&]page=(\d+)/);
            if (match && match[1]) {
                pageNum = parseInt(match[1], 10);
            } else {
                // 如果正则没匹配到,尝试用URL对象解析
                try {
                    const linkUrl = new URL(href, window.location.href);
                    const pageParam = linkUrl.searchParams.get('page');
                    if (pageParam !== null) {
                        pageNum = parseInt(pageParam, 10);
                    }
                } catch (e) {
                    // 解析失败,跳过
                }
            }
            
            if (pageNum !== null && !isNaN(pageNum)) {
                pageNumbers.add(pageNum);
            }
        });
        
        // 构建所有页面的URL
        pageNumbers.forEach(pageNum => {
            if (pageNum === 0) {
                // 第一页:不添加page参数
                urls.add(baseUrl);
            } else {
                // 其他页:添加page参数
                urls.add(`${baseUrl}&page=${pageNum}`);
            }
        });
        
        console.log('找到的分页URL:', Array.from(urls));
        return Array.from(urls);
    }
    
    // 标准化URL用于比较(只保留topicid与page,忽略参数顺序)
    function normalizeUrlForCompare(url) {
        try {
            const urlObj = new URL(url, window.location.origin);
            const topicid = urlObj.searchParams.get('topicid') || '';
            const page = urlObj.searchParams.get('page') || '0';
            const path = urlObj.pathname || '/forums.php';
            return `${urlObj.origin}${path}?topicid=${topicid}&page=${page}`;
        } catch (e) {
            return url.split('#')[0];
        }
    }
    
    // 获取当前主题各分页的文档内容
    async function fetchTopicDocuments() {
        const pageUrls = getTopicPageUrls();
        if (pageUrls.length === 0) {
            return [];
        }
        
        const parser = new DOMParser();
        const currentNormalized = normalizeUrlForCompare(window.location.href);
        const documents = [];
        
        for (let url of pageUrls) {
            const normalizedUrl = normalizeUrlForCompare(url);
            const isCurrentPage = normalizedUrl === currentNormalized;
            
            if (isCurrentPage) {
                documents.unshift({ url, doc: document, isCurrentPage: true });
                continue;
            }
            
            try {
                const response = await fetch(url, {
                    credentials: 'include',
                    headers: { 'Accept': 'text/html' }
                });
                
                if (!response.ok) {
                    console.error('获取分页失败:', url, response.status);
                    continue;
                }
                
                const html = await response.text();
                const doc = parser.parseFromString(html, 'text/html');
                documents.push({ url, doc, isCurrentPage: false });
            } catch (error) {
                console.error('请求分页发生错误:', url, error);
            }
        }
        
        return documents;
    }
    
    // 检查当前用户是否已经在任意分页下注
    async function hasUserReplied() {
        const currentUsername = getCurrentUsername();
        if (!currentUsername) {
            console.log('未获取到当前用户名');
            return false;
        }
        
        const topicDocuments = await fetchTopicDocuments();
        console.log('开始检查分页下注情况,共', topicDocuments.length, '页');
        
        for (let entry of topicDocuments) {
            if (!entry.doc) continue;
            
            if (hasUserRepliedOnDocument(entry.doc, currentUsername)) {
                console.log(`检测到用户在${entry.isCurrentPage ? '当前页' : '其他分页'}已下注:`, currentUsername, entry.url);
                return true;
            } else {
                console.log('该分页未检测到下注:', entry.url);
            }
        }
        
        console.log('所有分页检查完成,未发现重复下注');
        return false;
    }

    // 禁用快速回复表单并显示提示(公共函数)
    function disableReplyForm(message, noticeClass, backgroundColor) {
        // 查找快速回复表单
        const composeForm = document.getElementById('compose');
        if (!composeForm) return false;
        
        // 查找包含快速回复的 table
        const replyTable = composeForm.closest('table');
        if (!replyTable) return false;
        
        // 禁用所有表单元素
        const formElements = composeForm.querySelectorAll('textarea, input[type="submit"], button');
        formElements.forEach(element => {
            element.disabled = true;
            element.style.opacity = '0.5';
            element.style.cursor = 'not-allowed';
        });
        
        // 检查是否已经添加过提示
        if (!replyTable.querySelector('.' + noticeClass)) {
            // 在表单顶部添加提示
            const notice = document.createElement('div');
            notice.className = noticeClass;
            notice.style.cssText = `
                background: ${backgroundColor};
                color: white;
                padding: 10px 15px;
                margin: 10px 0;
                border-radius: 5px;
                text-align: center;
                font-weight: bold;
                font-size: 14px;
            `;
            notice.textContent = message;
            
            // 在"快速回复"标题后插入提示
            const quickReplyTitle = Array.from(replyTable.querySelectorAll('b')).find(b => b.textContent === '快速回复');
            if (quickReplyTitle && quickReplyTitle.parentElement) {
                quickReplyTitle.parentElement.appendChild(notice);
            }
        }
        
        return true;
    }

    // 恢复快速回复表单(移除禁用状态和提示)
    function enableReplyForm() {
        // 查找快速回复表单
        const composeForm = document.getElementById('compose');
        if (!composeForm) return false;
        
        // 查找包含快速回复的 table
        const replyTable = composeForm.closest('table');
        if (!replyTable) return false;
        
        // 恢复所有表单元素
        const formElements = composeForm.querySelectorAll('textarea, input[type="submit"], button');
        formElements.forEach(element => {
            element.disabled = false;
            element.style.opacity = '';
            element.style.cursor = '';
        });
        
        // 移除所有提示信息
        const deadlineNotice = replyTable.querySelector('.deadline-notice');
        if (deadlineNotice) {
            deadlineNotice.remove();
        }
        
        const duplicateBetNotice = replyTable.querySelector('.duplicate-bet-notice');
        if (duplicateBetNotice) {
            duplicateBetNotice.remove();
        }
        
        const betAmountNotice = replyTable.querySelector('.bet-amount-notice');
        if (betAmountNotice) {
            betAmountNotice.remove();
        }
        
        console.log('已恢复快速回复表单');
        return true;
    }

    // 检查回复框中的下注点数并禁用提交按钮
    function checkBetAmountInReplyBox() {
        // 只在开关开启时检查
        if (!Config.getCheckValidBetEnabled()) {
            return;
        }

        const composeForm = document.getElementById('compose');
        if (!composeForm) return;

        const textarea = composeForm.querySelector('textarea[name="body"]');
        if (!textarea) return;

        const submitButton = document.getElementById('qr') || composeForm.querySelector('input[type="submit"], button[type="submit"]');
        if (!submitButton) return;

        const replyTable = composeForm.closest('table');
        if (!replyTable) return;

        const content = textarea.value || '';
        const betAmountMatch = content.match(/下注点数[::]\s*([\d,]+)/);
        
        if (betAmountMatch && betAmountMatch[1]) {
            const betAmount = parseInt(betAmountMatch[1].replace(/,/g, ''), 10);
            
            if (!isNaN(betAmount) && betAmount > 1000000) {
                // 禁用提交按钮
                submitButton.disabled = true;
                submitButton.style.opacity = '0.5';
                submitButton.style.cursor = 'not-allowed';
                
                // 显示提示
                if (!replyTable.querySelector('.bet-amount-notice')) {
                    const notice = document.createElement('div');
                    notice.className = 'bet-amount-notice';
                    notice.style.cssText = `
                        background: #ff5252;
                        color: white;
                        padding: 10px 15px;
                        margin: 10px 0;
                        border-radius: 5px;
                        text-align: center;
                        font-weight: bold;
                        font-size: 14px;
                    `;
                    notice.textContent = `⚠️ 下注点数(${betAmount.toLocaleString()})超过1000000,禁止提交`;
                    
                    const quickReplyTitle = Array.from(replyTable.querySelectorAll('b')).find(b => b.textContent === '快速回复');
                    if (quickReplyTitle && quickReplyTitle.parentElement) {
                        quickReplyTitle.parentElement.appendChild(notice);
                    }
                }
            } else {
                // 恢复提交按钮
                submitButton.disabled = false;
                submitButton.style.opacity = '';
                submitButton.style.cursor = '';
                
                // 移除提示
                const notice = replyTable.querySelector('.bet-amount-notice');
                if (notice) notice.remove();
            }
        } else {
            // 恢复提交按钮
            submitButton.disabled = false;
            submitButton.style.opacity = '';
            submitButton.style.cursor = '';
            
            // 移除提示
            const notice = replyTable.querySelector('.bet-amount-notice');
            if (notice) notice.remove();
        }
    }

    // 检查有效下注并禁用回复(合并截止时间和重复下注检查)
    async function checkValidBetAndDisableReply() {
        // 只在开关开启时检查
        if (!Config.getCheckValidBetEnabled()) {
            return;
        }
        
        // 1. 检查截止时间
        const topSpan = document.getElementById('top');
        if (topSpan) {
            const titleText = topSpan.textContent;
            // 匹配格式:下注截止时间 2025-12-03 03:30:00 或 截止时间:2025-11-13 21:00(:00)
            const deadlineMatch = titleText.match(/(?:下注)?截止时间[::\s]+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?)/);
            console.log(deadlineMatch);
            if (deadlineMatch) {
                let deadlineStr = deadlineMatch[1];
                // 如果时间格式没有秒(只有 HH:MM),添加秒
                const timePart = deadlineStr.split(' ')[1]; // 获取时间部分
                if (timePart && timePart.split(':').length === 2) {
                    deadlineStr = deadlineStr + ':00';
                }
                // 解析截止时间(北京时间)
                const deadlineDate = new Date(deadlineStr.replace(' ', 'T') + '+08:00');
                
                // 获取当前时间
                const now = new Date();
                
                // 如果截止时间已过
                if (now > deadlineDate) {
                    if (disableReplyForm('⚠️ 投注截止时间已过,快速回复已禁用', 'deadline-notice', '#ff5252')) {
                        console.log('截止时间已过,已禁用快速回复面板');
                    }
                    return; // 截止时间已过,不再检查重复下注
                }
            }
        }
        
        // 2. 检查是否已下注(重复下注)
        if (await hasUserReplied()) {
            if (disableReplyForm('⚠️ 您已经下注,禁止重复下注', 'duplicate-bet-notice', '#ff9800')) {
                console.log('检测到重复下注,已禁用快速回复面板');
            }
        }

        // 3. 设置下注点数检查监听器
        const composeForm = document.getElementById('compose');
        if (composeForm) {
            const textarea = composeForm.querySelector('textarea[name="body"]');
            if (textarea && !textarea.dataset.betAmountListenerAdded) {
                textarea.dataset.betAmountListenerAdded = 'true';
                textarea.addEventListener('input', checkBetAmountInReplyBox);
                textarea.addEventListener('paste', () => setTimeout(checkBetAmountInReplyBox, 0));
                checkBetAmountInReplyBox(); // 初始检查
            }
        }
    }

    const ENABLE_SPECIAL_TILES = false;

    // 全局变量:高亮帖子列表
    let highlightedPosts = [];

    // 添加收藏
    function addBookmark() {
        const currentUrl = window.location.href;
        let currentTitle = document.title || '未命名页面';
        
        // 从标题中提取引号里的内容
        const match = currentTitle.match(/"([^"]+)"/);
        if (match && match[1]) {
            currentTitle = match[1];
        } else {
            // 如果没有引号,则删掉常见的前后缀
            currentTitle = currentTitle.replace(/^HDSky :: 查看主题\s+/i, '');
            currentTitle = currentTitle.replace(/^HDSky :: /i, '');
            currentTitle = currentTitle.replace(/\s*高清视界.*$/i, '');
            currentTitle = currentTitle.replace(/\s*-\s*Powered by.*$/i, '');
        }
        
        // 获取现有收藏列表
        const bookmarks = getBookmarkList();
        
        // 检查是否已经收藏
        const exists = bookmarks.some(b => b.url === currentUrl);
        if (exists) {
            alert('该页面已经在收藏夹中了!');
            return;
        }
        
        // 添加新收藏
        bookmarks.push({
            url: currentUrl,
            title: currentTitle,
            time: new Date().toLocaleString()
        });
        
        // 保存
        saveBookmarkList(bookmarks);
        alert('收藏成功!\n标题:' + currentTitle);
    }

    // 显示收藏夹
    function showBookmarkList() {
        const bookmarks = getBookmarkList();
        
        // 移除旧的收藏夹窗口(如果存在)
        const oldDialog = document.getElementById('bookmark-dialog');
        if (oldDialog) {
            oldDialog.remove();
        }
        
        // 创建遮罩层
        const overlay = document.createElement('div');
        overlay.id = 'bookmark-dialog';
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 10003;
            display: flex;
            justify-content: center;
            align-items: center;
        `;
        
        // 创建弹窗
        const dialog = document.createElement('div');
        dialog.style.cssText = `
            background: white;
            border-radius: 10px;
            padding: 20px;
            width: 700px;
            max-width: 95vw;
            max-height: 85vh;
            overflow-y: auto;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
        `;
        
        // 标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #2196F3;
            background: transparent;
        `;
        
        const title = document.createElement('h2');
        title.textContent = '我的收藏夹';
        title.style.cssText = `
            margin: 0;
            padding: 0;
            color: #2196F3;
            font-size: 20px;
            background: transparent;
            border: none;
            outline: none;
        `;
        header.appendChild(title);
        
        const closeBtn = document.createElement('button');
        closeBtn.textContent = '✕';
        closeBtn.style.cssText = `
            background: #f44336;
            color: white;
            border: none;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            transition: background 0.3s;
        `;
        closeBtn.onmouseover = () => closeBtn.style.background = '#d32f2f';
        closeBtn.onmouseout = () => closeBtn.style.background = '#f44336';
        closeBtn.onclick = () => overlay.remove();
        header.appendChild(closeBtn);
        
        dialog.appendChild(header);
        
        // 收藏列表
        if (bookmarks.length === 0) {
            const emptyMsg = document.createElement('div');
            emptyMsg.textContent = '收藏夹还是空的,快去收藏喜欢的页面吧!';
            emptyMsg.style.cssText = `
                text-align: center;
                color: #999;
                padding: 40px 20px;
                font-size: 14px;
                background: #f9f9f9;
                border-radius: 5px;
                margin-top: 10px;
            `;
            dialog.appendChild(emptyMsg);
        } else {
            bookmarks.forEach((bookmark, index) => {
                const item = createBookmarkItem(bookmark, index);
                dialog.appendChild(item);
            });
        }
        
        overlay.appendChild(dialog);
        document.body.appendChild(overlay);
        
        // 点击遮罩层关闭
        overlay.onclick = (e) => {
            if (e.target === overlay) {
                overlay.remove();
            }
        };
    }

    // 创建收藏项
    function createBookmarkItem(bookmark, index) {
        const item = document.createElement('div');
        item.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px;
            margin-bottom: 10px;
            background: #fafafa;
            border: 1px solid #e0e0e0;
            border-radius: 5px;
            transition: all 0.3s;
        `;
        item.onmouseover = () => {
            item.style.background = '#e3f2fd';
            item.style.borderColor = '#2196F3';
            item.style.transform = 'translateX(5px)';
            item.style.boxShadow = '0 2px 8px rgba(33, 150, 243, 0.2)';
        };
        item.onmouseout = () => {
            item.style.background = '#fafafa';
            item.style.borderColor = '#e0e0e0';
            item.style.transform = 'translateX(0)';
            item.style.boxShadow = 'none';
        };
        
        // 左侧内容区
        const content = document.createElement('div');
        content.style.cssText = `
            flex: 1;
            cursor: pointer;
            overflow: hidden;
        `;
        content.onclick = () => window.location.href = bookmark.url;
        
        const titleDiv = document.createElement('div');
        titleDiv.textContent = bookmark.title;
        titleDiv.style.cssText = `
            font-size: 14px;
            font-weight: bold;
            color: #2196F3;
            margin-bottom: 5px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        `;
        content.appendChild(titleDiv);
        
        const timeDiv = document.createElement('div');
        timeDiv.textContent = '收藏时间: ' + bookmark.time;
        timeDiv.style.cssText = `
            font-size: 12px;
            color: #999;
        `;
        content.appendChild(timeDiv);
        
        item.appendChild(content);
        
        // 删除按钮
        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = '✕';
        deleteBtn.style.cssText = `
            background: #ff5722;
            color: white;
            border: none;
            border-radius: 50%;
            width: 25px;
            height: 25px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: background 0.3s;
            margin-left: 10px;
        `;
        deleteBtn.onmouseover = () => deleteBtn.style.background = '#e64a19';
        deleteBtn.onmouseout = () => deleteBtn.style.background = '#ff5722';
        deleteBtn.onclick = (e) => {
            e.stopPropagation();
            if (confirm('确定要删除这个收藏吗?\n' + bookmark.title)) {
                deleteBookmark(index);
                showBookmarkList(); // 刷新列表
            }
        };
        item.appendChild(deleteBtn);
        
        return item;
    }

    // 删除收藏
    function deleteBookmark(index) {
        const bookmarks = getBookmarkList();
        bookmarks.splice(index, 1);
        saveBookmarkList(bookmarks);
    }

    // 处理关注列表点击(编辑)
    function handleFollowListClick() {
        const currentList = getSpecialFollowList();
        const currentStr = currentList.join(',');
        
        const input = prompt('请输入特殊关注名单(用逗号分隔):\n例如: DFBCOLD19,李知恩', currentStr);
        
        if (input !== null) { // 用户点击了确定(包括空字符串)
            const newList = input.split(',').map(name => name.trim()).filter(name => name);
            saveSpecialFollowList(newList);
            
            alert('特殊关注名单已更新!\n当前关注: ' + (newList.length > 0 ? newList.join(', ') : '无'));
            
            // 重新应用高亮
            autoHighlightFollowedPosts();
            renderSpecialFollowTiles();
        }
    }

    // 自动高亮特殊关注用户的帖子(页面加载时调用)
    function autoHighlightFollowedPosts() {
        // 如果开关关闭,清除高亮并退出
        if (!Config.getHighlightFollowEnabled()) {
            clearHighlights();
            return;
        }
        
        const followList = getSpecialFollowList();
        
        // 如果没有关注名单,不执行高亮
        if (followList.length === 0) {
            return;
        }
        
        // 先清除之前的高亮
        clearHighlights();
        
        // 找到所有回复帖子(每个帖子在一个带有 margin-top 和 margin-bottom 的 div 中)
        const allPosts = document.querySelectorAll('div[style*="margin-top: 8pt"]');
        
        // 重置高亮列表
        highlightedPosts = [];
        
        allPosts.forEach(post => {
            // 在帖子中查找用户名链接
            const userLinks = post.querySelectorAll('a[href*="userdetails.php"]');
            let isFollowedUser = false;
            
            userLinks.forEach(link => {
                const username = link.textContent.trim();
                // 检查是否在关注列表中
                if (followList.some(followName => username === followName)) {
                    isFollowedUser = true;
                }
            });
            
            if (isFollowedUser) {
                // 高亮显示关注用户的信息div
                post.style.background = '#fffacd';
                post.style.border = '2px solid #ffd700';
                post.style.borderRadius = '5px';
                post.style.padding = '5px';
                
                // 找到并高亮div内部的table
                const innerTables = post.querySelectorAll('table');
                innerTables.forEach(table => {
                    table.style.background = '#fff8dc';
                    table.style.border = '2px solid #ffb700';
                });
                
                // 标记为已高亮
                post.dataset.highlighted = 'true';
                
                // 找到并高亮紧跟在div后面的回复内容table(class="main")
                let nextElement = post.nextElementSibling;
                if (nextElement && nextElement.tagName === 'TABLE' && nextElement.classList.contains('main')) {
                    nextElement.style.background = '#fff8dc';
                    nextElement.style.border = '2px solid #ffb700';
                    nextElement.style.borderRadius = '5px';
                    // 标记这个table也被高亮了
                    nextElement.dataset.highlightedContent = 'true';
                }
                
                // 添加到高亮列表
                highlightedPosts.push(post);
            }
        });
    }

    // 清除所有高亮
    function clearHighlights() {
        // 找到所有被高亮的帖子div
        const posts = document.querySelectorAll('div[data-highlighted="true"]');
        
        posts.forEach(post => {
            // 清除div的高亮样式
            post.style.background = '';
            post.style.border = '';
            post.style.borderRadius = '';
            post.style.padding = '';
            post.removeAttribute('data-highlighted');
            
            // 清除div内部table的高亮样式
            const tables = post.querySelectorAll('table');
            tables.forEach(table => {
                table.style.background = '';
                table.style.border = '';
            });
        });
        
        // 清除所有被高亮的回复内容table
        const contentTables = document.querySelectorAll('table[data-highlighted-content="true"]');
        contentTables.forEach(table => {
            table.style.background = '';
            table.style.border = '';
            table.style.borderRadius = '';
            table.removeAttribute('data-highlighted-content');
        });
        
        // 重置全局变量
        highlightedPosts = [];
    }

    // 移除特殊关注磁贴容器
    function removeSpecialFollowTiles() {
        const existing = document.getElementById('special-follow-tile-container');
        if (existing) {
            existing.remove();
        }
    }

    // 记录文档中特殊关注用户的回帖信息
    function recordFollowRepliesFromDocument(doc, pageUrl, followSet, collectedMap, isCurrentPage) {
        if (!doc) return;

        const posts = doc.querySelectorAll('div[style*="margin-top: 8pt"]');
        posts.forEach(post => {
            // 查找帖子中的所有用户名链接
            const userLinks = post.querySelectorAll('a[href*="userdetails.php?id"]');
            userLinks.forEach(link => {
                const username = link.textContent.trim();
                if (!username || !followSet.has(username) || collectedMap.has(username)) {
                    return;
                }

                // 查找带有 pid 的元素,用于定位锚点
                let anchorId = '';
                const pidElement = post.querySelector('[id^="pid"]') || post.querySelector('table[id^="pid"]');
                if (pidElement && pidElement.id) {
                    anchorId = pidElement.id;
                } else {
                    const pidLink = post.querySelector('a[href*="#pid"]');
                    if (pidLink) {
                        const hashMatch = pidLink.getAttribute('href').match(/#(pid\d+)/);
                        if (hashMatch && hashMatch[1]) {
                            anchorId = hashMatch[1];
                        }
                    }
                }

                let targetUrl = pageUrl;
                const anchorNoHash = anchorId ? anchorId.replace('#', '') : '';
                if (anchorNoHash) {
                    try {
                        const urlObj = new URL(pageUrl);
                        urlObj.hash = `#${anchorNoHash}`;
                        targetUrl = urlObj.href;
                    } catch (e) {
                        targetUrl = `${pageUrl.split('#')[0]}#${anchorNoHash}`;
                    }
                }

                collectedMap.set(username, {
                    username,
                    targetUrl,
                    anchorId: anchorNoHash,
                    isOnCurrentPage: isCurrentPage && !!(anchorNoHash && document.getElementById(anchorNoHash)),
                    pageUrl
                });
            });
        });
    }

    // 收集特殊关注用户的回帖数据(遍历所有分页)
    async function collectSpecialFollowReplies(followList) {
        const followSet = new Set(followList);
        const collectedMap = new Map();
        
        const topicDocuments = await fetchTopicDocuments();
        for (let entry of topicDocuments) {
            if (!entry.doc) continue;
            
            recordFollowRepliesFromDocument(
                entry.doc,
                entry.url,
                followSet,
                collectedMap,
                entry.isCurrentPage
            );
            
            if (collectedMap.size === followSet.size) {
                break; // 已经找到所有关注用户
            }
        }
        
        return Array.from(collectedMap.values());
    }

    // 点击磁贴时滚动或跳转
    function handleFollowTileClick(tileInfo) {
        if (tileInfo.isOnCurrentPage && tileInfo.anchorId) {
            const target = document.getElementById(tileInfo.anchorId);
            if (target) {
                target.scrollIntoView({ behavior: 'smooth', block: 'start' });
                target.style.boxShadow = '0 0 10px 2px rgba(33,150,243,0.6)';
                setTimeout(() => {
                    target.style.boxShadow = '';
                }, 2000);
                return;
            }
        }

        // 如果不在当前页,跳转到对应链接
        window.location.href = tileInfo.targetUrl;
    }

    // 渲染特殊关注磁贴
    async function renderSpecialFollowTiles() {
        if (!ENABLE_SPECIAL_TILES) {
            removeSpecialFollowTiles();
            return;
        }
        removeSpecialFollowTiles();

        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewtopic') {
            return;
        }

        const followList = getSpecialFollowList();
        if (followList.length === 0) {
            return;
        }

        const tileData = await collectSpecialFollowReplies(followList);
        if (tileData.length === 0) {
            return;
        }

        const container = document.createElement('div');
        container.id = 'special-follow-tile-container';
        container.style.cssText = `
            position: fixed;
            right: 10px;
            top: 50%;
            transform: translateY(-50%);
            display: flex;
            flex-direction: column;
            gap: 10px;
            z-index: 10000;
        `;

        tileData.forEach(info => {
            const tile = document.createElement('div');
            tile.className = 'special-follow-tile';
            tile.textContent = info.username;
            tile.style.cssText = `
                background: #fff;
                border: 1px solid #2196F3;
                border-radius: 8px;
                padding: 10px 14px;
                font-size: 13px;
                font-weight: bold;
                color: #2196F3;
                cursor: pointer;
                box-shadow: 0 2px 6px rgba(0,0,0,0.15);
                transition: transform 0.2s, box-shadow 0.2s;
                min-width: 120px;
                text-align: center;
            `;

            tile.onmouseover = () => {
                tile.style.transform = 'translateX(-4px)';
                tile.style.boxShadow = '0 4px 10px rgba(33,150,243,0.3)';
            };
            tile.onmouseout = () => {
                tile.style.transform = 'translateX(0)';
                tile.style.boxShadow = '0 2px 6px rgba(0,0,0,0.15)';
            };

            tile.onclick = () => handleFollowTileClick(info);

            container.appendChild(tile);
        });

        document.body.appendChild(container);
    }

    // 自动加载下一页功能
    let isLoadingNextPage = false;
    const scrollThreshold = 800; // 距离底部多少像素时触发加载

    function autoLoadNextPage() {
        if (!Config.getAutoLoadEnabled()) {
            return;
        }

        // 检查URL中是否包含topicid参数
        const urlParams = new URLSearchParams(window.location.search);
        if (!urlParams.has('topicid')) {
            return;
        }

        let lastScrollTop = 0;
        
        window.addEventListener('scroll', function() {
            const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
            const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
            const clientHeight = document.documentElement.clientHeight || window.innerHeight;
            
            // 只在向下滚动时触发
            if (scrollTop > lastScrollTop) {
                // 判断是否接近底部
                if (scrollHeight <= clientHeight + scrollTop + scrollThreshold && !isLoadingNextPage) {
                    // 查找下一页链接
                    const nextLinks = document.querySelectorAll('a');
                    let nextPageLink = null;
                    
                    for (let link of nextLinks) {
                        const text = link.textContent.trim();
                        if (text.includes('下一页') || text === '下一页 >>') {
                            nextPageLink = link;
                            break;
                        }
                    }
                    
                    if (nextPageLink && nextPageLink.href) {
                        loadNextPage(nextPageLink.href);
                    }
                }
            }
            
            lastScrollTop = scrollTop;
        }, false);
    }

    function loadNextPage(url) {
        isLoadingNextPage = true;
        
        // 显示加载提示
        const loadingDiv = document.createElement('div');
        loadingDiv.id = 'auto-loading-indicator';
        loadingDiv.style.cssText = `
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(33, 150, 243, 0.9);
            color: white;
            padding: 12px 24px;
            border-radius: 25px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            z-index: 9999;
            font-size: 14px;
            font-weight: bold;
        `;
        loadingDiv.textContent = '正在加载下一页...';
        document.body.appendChild(loadingDiv);
        
        // 使用 fetch 加载下一页
        fetch(url)
            .then(response => response.text())
            .then(html => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                
                // 查找主要内容区域 - 找到所有回复帖子
                const newPosts = doc.querySelectorAll('div[style*="margin-top: 8pt"]');
                
                // 找到当前页面的最后一个帖子
                const currentPosts = document.querySelectorAll('div[style*="margin-top: 8pt"]');
                if (currentPosts.length > 0 && newPosts.length > 0) {
                    const lastPost = currentPosts[currentPosts.length - 1];
                    
                    // 找到最后一个帖子的下一个 table(回复内容)
                    let lastTable = lastPost.nextElementSibling;
                    while (lastTable && lastTable.tagName !== 'TABLE') {
                        lastTable = lastTable.nextElementSibling;
                    }
                    
                    // 确定插入位置:如果有 table 就在 table 后面,否则在 div 后面
                    let insertAfter = lastTable || lastPost;
                    
                    // 将新帖子插入到页面中
                    newPosts.forEach(post => {
                        // 克隆 div(用户信息)
                        const clonedPost = post.cloneNode(true);
                        insertAfter.parentNode.insertBefore(clonedPost, insertAfter.nextSibling);
                        insertAfter = clonedPost;
                        
                        // 查找并克隆紧跟的 table(回复内容)
                        const nextTable = post.nextElementSibling;
                        if (nextTable && nextTable.tagName === 'TABLE' && nextTable.classList.contains('main')) {
                            const clonedTable = nextTable.cloneNode(true);
                            insertAfter.parentNode.insertBefore(clonedTable, insertAfter.nextSibling);
                            insertAfter = clonedTable;
                        }
                    });
                    
                    // 更新页码导航(找到所有 <p align="center"> 中包含"上一页"和"下一页"的元素)
                    const newPagers = doc.querySelectorAll('p[align="center"]');
                    const currentPagers = document.querySelectorAll('p[align="center"]');
                    
                    // 遍历并更新所有分页器
                    let pagerUpdateCount = 0;
                    for (let i = 0; i < currentPagers.length && i < newPagers.length; i++) {
                        const currentPager = currentPagers[i];
                        const newPager = newPagers[i];
                        
                        // 检查是否包含分页链接(包含"上一页"或"下一页")
                        if (currentPager.innerHTML.includes('上一页') || currentPager.innerHTML.includes('下一页')) {
                            currentPager.innerHTML = newPager.innerHTML;
                            pagerUpdateCount++;
                        }
                    }
                    
                    console.log(`已更新 ${pagerUpdateCount} 个分页导航`);
                    
                    // 重新应用高亮
                    autoHighlightFollowedPosts();
                    renderSpecialFollowTiles();
                    enhanceAuthorRemarks();
                    
                    loadingDiv.textContent = '✓ 加载完成';
                    loadingDiv.style.background = 'rgba(76, 175, 80, 0.9)';
                    
                    setTimeout(() => {
                        loadingDiv.remove();
                    }, 2000);
                    
                    // 更新 URL(不刷新页面)
                    history.pushState(null, '', url);
                } else {
                    loadingDiv.textContent = '没有更多内容了';
                    loadingDiv.style.background = 'rgba(255, 152, 0, 0.9)';
                    setTimeout(() => {
                        loadingDiv.remove();
                    }, 2000);
                }
                
                isLoadingNextPage = false;
            })
            .catch(error => {
                console.error('加载下一页失败:', error);
                loadingDiv.textContent = '✗ 加载失败';
                loadingDiv.style.background = 'rgba(244, 67, 54, 0.9)';
                setTimeout(() => {
                    loadingDiv.remove();
                }, 2000);
                isLoadingNextPage = false;
            });
    }


    // 提取收藏夹中所有URL的topicid并打印到控制台
    function printBookmarkTopicIds() {
        const bookmarks = getBookmarkList();
        const topicIds = [];
        
        bookmarks.forEach(bookmark => {
            try {
                const url = new URL(bookmark.url);
                const topicid = url.searchParams.get('topicid');
                if (topicid) {
                    topicIds.push(topicid);
                }
            } catch (e) {
                // 如果URL格式不正确,尝试用正则表达式提取
                const match = bookmark.url.match(/topicid=(\d+)/);
                if (match && match[1]) {
                    topicIds.push(match[1]);
                }
            }
        });
        
        if (topicIds.length > 0) {
            console.log('收藏夹中的topicid列表:');
            console.log(topicIds);
            console.log('topicid列表(逗号分隔):' + topicIds.join(','));
        } else {
            console.log('收藏夹中没有找到包含topicid的URL');
        }
        
        return topicIds;
    }

    // 将函数暴露到全局,方便在控制台中手动调用
    window.printBookmarkTopicIds = printBookmarkTopicIds;

    // 在embedded左侧添加星星标记收藏的帖子
    function highlightTopicIdRows() {
        // 只在URL包含viewforum时生效
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewforum') {
            return;
        }
        
        // 获取收藏夹中的topicid列表
        const bookmarks = getBookmarkList();
        const topicIds = [];
        
        bookmarks.forEach(bookmark => {
            try {
                const url = new URL(bookmark.url);
                const topicid = url.searchParams.get('topicid');
                if (topicid) {
                    topicIds.push(topicid);
                }
            } catch (e) {
                // 如果URL格式不正确,尝试用正则表达式提取
                const match = bookmark.url.match(/topicid=(\d+)/);
                if (match && match[1]) {
                    topicIds.push(match[1]);
                }
            }
        });
        
        if (topicIds.length === 0) {
            return; // 如果没有收藏的topicid,不执行标记
        }
        
        // 查找所有包含topicid链接的embedded元素
        const embeddedTds = document.querySelectorAll('td.embedded');
        
        embeddedTds.forEach(td => {
            // 查找td中所有包含topicid的链接
            const links = td.querySelectorAll('a[href*="topicid"]');
            
            links.forEach(link => {
                // 从链接中提取topicid
                const href = link.getAttribute('href');
                const match = href.match(/topicid[=&](\d+)/);
                
                if (match && match[1]) {
                    const topicid = match[1];
                    
                    // 如果这个topicid在收藏列表中,添加星星
                    if (topicIds.includes(topicid)) {
                        // 检查是否已经添加过星星
                        if (!td.querySelector('.bookmark-star')) {
                            // 创建星星元素
                            const star = document.createElement('span');
                            star.className = 'bookmark-star';
                            star.textContent = '⭐';
                            star.title = '已收藏';
                            star.style.cssText = `
                                margin-right: 5px;
                                font-size: 14px;
                                cursor: pointer;
                            `;
                            
                            // 在embedded的左侧插入星星(在所有内容之前)
                            td.insertBefore(star, td.firstChild);
                        }
                    }
                }
            });
        });
        
        console.log(`已标记 ${document.querySelectorAll('.bookmark-star').length} 个收藏的帖子`);
    }

    // 清理下注文本,移除【数字】或[数字]等前缀
    function sanitizeBetValue(value) {
        if (!value) {
            return '';
        }
        return value
            .replace(/[\[【]\s*[\d.]+\s*[\]】]/g, '')
            .replace(/\s+/g, ' ')
            .trim();
    }

    // 采集帖子下注数据
    // 计算评分总和
    function calculateRatingSum(postBody) {
        const container = postBody.parentElement;
        if (!container) return 0;

        // 查找包含"[评分]"的 div
        const ratingDiv = Array.from(container.querySelectorAll('div')).find(div => {
            const text = div.textContent || '';
            return text.includes('[评分]');
        });

        if (!ratingDiv) {
            return 0;
        }

        const html = ratingDiv.innerHTML || '';
        const lines = html.split(/<br\s*\/?>|\n/i);
        let sum = 0;
        let foundScore = false;

        lines.forEach(line => {
            const clean = line.replace(/<[^>]+>/g, '').trim();
            if (!clean || !clean.includes('评分理由')) {
                return;
            }
            const match = clean.match(/\s([+-]\d[\d,]*)\s*评分理由/);
            if (match) {
                const value = parseInt(match[1].trim().replace(/,/g, ''), 10);
                if (!isNaN(value)) {
                    sum += value;
                    foundScore = true;
                }
            }
        });

        return foundScore ? sum : 0;
    }

    function collectBetPostsData() {
        const postTables = document.querySelectorAll('table[id^="pid"]');
        const results = [];
        let maxBetIndex = 0;
        let skipFirstPost = true;
        let hasRating = false; // 标记是否有任何帖子存在评分

        postTables.forEach(table => {
            if (!table.id || table.id.endsWith('body')) {
                return;
            }
            if (skipFirstPost) {
                skipFirstPost = false;
                return;
            }
            const userLink = table.querySelector('a[href*="userdetails.php?id="]');
            if (!userLink) {
                return;
            }
            const username = (userLink.textContent || '').trim();
            const body = document.getElementById(`${table.id}body`);
            if (!body) {
                return;
            }
            const textContent = body.innerText || '';
            const lines = textContent.split(/\r?\n/).map(line => line.trim()).filter(line => line);
            const betMap = {};
            let betAmount = '';

            lines.forEach(line => {
                const match = line.match(/^(\d+)\.(?:下注球队|下注球隊)[::]\s*(.+)$/);
                if (match) {
                    const index = parseInt(match[1], 10);
                    if (!isNaN(index)) {
                        const sanitized = sanitizeBetValue(match[2]);
                        if (sanitized) {
                            betMap[index] = sanitized;
                        }
                        if (index > maxBetIndex) {
                            maxBetIndex = index;
                        }
                    }
                    return;
                }
                if (!betAmount) {
                    const betMatch = line.match(/下注点数[::]\s*([\d,]+)/);
                    if (betMatch && betMatch[1]) {
                        betAmount = betMatch[1].replace(/,/g, '');
                    }
                }
            });

            if (Object.keys(betMap).length === 0) {
                return;
            }

            // 计算评分总和
            const ratingSum = calculateRatingSum(body);
            if (ratingSum !== 0) {
                hasRating = true;
                // 如果有评分,在评分框追加显示"评分总和"(传入已计算的值避免重复计算)
                appendRatingSummary(body, ratingSum);
            }

            results.push({
                username,
                bets: betMap,
                betAmount,
                anchorId: table.id || '',
                ratingSum: ratingSum
            });
        });

        return {
            rows: results,
            maxBetIndex,
            hasRating: hasRating
        };
    }

    // 渲染数据分析表格
    function renderDataAnalysisTable(dataRows, maxBetIndex, container, onlyFollow, hasRating) {
        container.innerHTML = '';
        const followList = new Set(getSpecialFollowList());
        const filteredRows = onlyFollow ? dataRows.filter(row => followList.has(row.username)) : dataRows.slice();

        if (filteredRows.length === 0) {
            const empty = document.createElement('div');
            empty.style.cssText = `
                padding: 40px 20px;
                text-align: center;
                color: #999;
                font-size: 14px;
            `;
            empty.textContent = onlyFollow ? '特殊关注列表中没有匹配的下注记录。' : '当前页面未找到下注记录。';
            container.appendChild(empty);
            return;
        }

        const table = document.createElement('table');
        table.style.cssText = `
            width: 100%;
            border-collapse: separate;
            border-spacing: 0;
            font-size: 13px;
            background: #fff;
            border-radius: 8px;
            overflow: hidden;
        `;

        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');
        headerRow.style.background = '#f5f5f5';

        const userTh = document.createElement('th');
        userTh.textContent = '用户名';
        userTh.style.cssText = 'border: 1px solid #ddd; padding: 8px; width: 120px;';
        headerRow.appendChild(userTh);

        for (let i = 1; i <= maxBetIndex; i++) {
            const th = document.createElement('th');
            th.textContent = i;
            th.style.cssText = 'border: 1px solid #ddd; padding: 8px;';
            headerRow.appendChild(th);
        }
        const betAmountTh = document.createElement('th');
        betAmountTh.textContent = '下注点数';
        betAmountTh.style.cssText = 'border: 1px solid #ddd; padding: 8px; width: 100px;';
        headerRow.appendChild(betAmountTh);

        // 如果有评分,添加"评分总和"列
        if (hasRating) {
            const ratingSumTh = document.createElement('th');
            ratingSumTh.textContent = '评分总和';
            ratingSumTh.style.cssText = 'border: 1px solid #ddd; padding: 8px; width: 100px;';
            headerRow.appendChild(ratingSumTh);
        }

        thead.appendChild(headerRow);
        table.appendChild(thead);

        const tbody = document.createElement('tbody');

        const columnTopMap = new Map();
        for (let i = 1; i <= maxBetIndex; i++) {
            const freq = new Map();
            filteredRows.forEach(row => {
                const val = (row.bets[i] || '').trim();
                if (!val) return;
                freq.set(val, (freq.get(val) || 0) + 1);
            });
            let topValue = '';
            let topCount = 0;
            freq.forEach((count, val) => {
                if (count > topCount) {
                    topValue = val;
                    topCount = count;
                }
            });
            columnTopMap.set(i, { value: topValue, count: topCount });
        }

        filteredRows.forEach(row => {
            const tr = document.createElement('tr');
            tr.style.background = '#fff';

            const userTd = document.createElement('td');
            userTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; font-weight: bold; color: #2196F3;';
            const anchorLink = document.createElement('a');
            anchorLink.textContent = row.username;
            anchorLink.style.cssText = 'color: #2196F3; text-decoration: none; cursor: pointer;';
            anchorLink.title = '点击跳转到该用户的楼层';
            anchorLink.onclick = () => {
                if (row.anchorId) {
                    const target = document.getElementById(row.anchorId);
                    if (target) {
                        target.scrollIntoView({ behavior: 'smooth', block: 'start' });
                        target.style.boxShadow = '0 0 12px rgba(33,150,243,0.7)';
                        setTimeout(() => target.style.boxShadow = '', 2000);
                    } else {
                        window.location.href = `#${row.anchorId}`;
                    }
                }
                const overlay = document.getElementById('data-analysis-dialog');
                if (overlay) {
                    overlay.remove();
                }
            };
            userTd.appendChild(anchorLink);
            tr.appendChild(userTd);

            for (let i = 1; i <= maxBetIndex; i++) {
                const td = document.createElement('td');
                const value = row.bets[i] || '';
                td.textContent = value;
                td.style.cssText = 'border: 1px solid #eee; padding: 8px;';
                const topInfo = columnTopMap.get(i);
                if (topInfo && topInfo.value && value === topInfo.value) {
                    td.style.background = '#fff7d6';
                    td.style.fontWeight = 'bold';
                    td.style.color = '#e65100';
                }
                tr.appendChild(td);
            }
            const betAmountTd = document.createElement('td');
            betAmountTd.textContent = row.betAmount || '';
            betAmountTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; text-align: right;';
            tr.appendChild(betAmountTd);

            // 如果有评分,添加"评分总和"单元格
            if (hasRating) {
                const ratingSumTd = document.createElement('td');
                if (row.ratingSum !== null && row.ratingSum !== undefined && row.ratingSum !== 0) {
                    const prefix = row.ratingSum > 0 ? '+' : '';
                    ratingSumTd.textContent = `${prefix}${row.ratingSum}`;
                    ratingSumTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; text-align: right; font-weight: bold;';
                    if (row.ratingSum > 0) {
                        ratingSumTd.style.color = '#4caf50';
                    } else if (row.ratingSum < 0) {
                        ratingSumTd.style.color = '#f44336';
                    }
                } else {
                    ratingSumTd.textContent = '-';
                    ratingSumTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; text-align: center; color: #999;';
                }
                tr.appendChild(ratingSumTd);
            }

            tbody.appendChild(tr);
        });

        table.appendChild(tbody);

        const summaryRow = document.createElement('tr');
        summaryRow.style.background = '#e3f2fd';

        const summaryLabel = document.createElement('td');
        summaryLabel.textContent = '最常见';
        summaryLabel.style.cssText = 'border: 1px solid #ddd; padding: 8px; font-weight: bold;';
        summaryRow.appendChild(summaryLabel);

        for (let i = 1; i <= maxBetIndex; i++) {
            const td = document.createElement('td');
            const info = columnTopMap.get(i);
            if (info && info.value) {
                td.textContent = `${info.value}(${info.count}次)`;
                td.style.fontWeight = 'bold';
                td.style.color = '#0d47a1';
            } else {
                td.textContent = '无数据';
                td.style.color = '#999';
            }
            td.style.cssText = (td.style.cssText || '') + 'border: 1px solid #ddd; padding: 8px;';
            summaryRow.appendChild(td);
        }
        const summaryBetTd = document.createElement('td');
        summaryBetTd.textContent = '—';
        summaryBetTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; text-align: center; color: #777;';
        summaryRow.appendChild(summaryBetTd);

        // 如果有评分,添加一个空的评分总和单元格
        if (hasRating) {
            const summaryRatingTd = document.createElement('td');
            summaryRatingTd.textContent = '—';
            summaryRatingTd.style.cssText = 'border: 1px solid #ddd; padding: 8px; text-align: center; color: #777;';
            summaryRow.appendChild(summaryRatingTd);
        }

        if (tbody.firstChild) {
            tbody.insertBefore(summaryRow, tbody.firstChild);
        } else {
            tbody.appendChild(summaryRow);
        }

        // 构建最常见下注文本
        const popularLines = [];
        for (let i = 1; i <= maxBetIndex; i++) {
            const info = columnTopMap.get(i);
            if (info && info.value) {
                popularLines.push(`${i}.下注球隊: [0.9]${info.value}`);
            }
        }

        const textAreaWrapper = document.createElement('div');
        textAreaWrapper.style.cssText = 'margin-top: 12px;';

        const textAreaLabel = document.createElement('div');
        textAreaLabel.textContent = '最常见下注组合:';
        textAreaLabel.style.cssText = 'font-weight: bold; margin-bottom: 6px;';
        textAreaWrapper.appendChild(textAreaLabel);

        const summaryTextarea = document.createElement('textarea');
        summaryTextarea.readOnly = false;
        summaryTextarea.style.cssText = `
            width: 98%;
            min-height: 160px;
            border: 1px solid #ccc;
            border-radius: 6px;
            padding: 10px;
            font-size: 13px;
            line-height: 1.5;
            resize: none;
            overflow-y: hidden;
            box-sizing: border-box;
        `;

        if (popularLines.length > 0) {
            popularLines.push('', '下注点数:1000000');
            summaryTextarea.value = popularLines.join('\n');
        } else {
            summaryTextarea.value = '暂无可用的最常见下注数据';
        }

        textAreaWrapper.appendChild(summaryTextarea);
        
        // 自动调整高度的函数
        const adjustTextareaHeight = () => {
            // 先重置高度,让scrollHeight能正确计算
            summaryTextarea.style.height = 'auto';
            // 获取实际需要的高度(scrollHeight已经包含了padding)
            const scrollHeight = summaryTextarea.scrollHeight;
            // 设置新高度,最小160px,减去1px避免底部多余空白
            summaryTextarea.style.height = Math.max(160, scrollHeight - 1) + 'px';
        };
        
        // 等待DOM更新后再设置初始高度
        setTimeout(() => {
            adjustTextareaHeight();
        }, 0);
        
        // 监听输入事件,动态调整高度
        summaryTextarea.addEventListener('input', adjustTextareaHeight);
        summaryTextarea.addEventListener('paste', () => {
            setTimeout(adjustTextareaHeight, 0);
        });
        container.appendChild(textAreaWrapper);
        const divider = document.createElement('hr');
        divider.style.cssText = 'border: none; border-top: 1px dashed #ccc; margin: 16px 0;';
        container.appendChild(divider);
        container.appendChild(table);
        return summaryTextarea;
    }

    // 打开快捷回复悬浮框
    let isQuickReplyOpen = false;
    function openQuickReply() {
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewtopic') {
            alert('快捷回复功能仅在帖子页面可用');
            return;
        }

        if (isQuickReplyOpen) {
            return;
        }

        // 查找原始回复框,获取表单信息
        const originalCompose = document.getElementById('compose');
        if (!originalCompose) {
            alert('未找到回复框');
            return;
        }

        // 获取原始表单的 action 和 method
        const form = originalCompose.querySelector('form');
        const formAction = form ? form.getAttribute('action') : '';
        const formMethod = form ? form.getAttribute('method') || 'post' : 'post';

        // 创建悬浮框容器(参考 a.html 的 md-editor 风格)
        const quickReplyBox = document.createElement('div');
        quickReplyBox.id = 'quick-reply-box';
        quickReplyBox.className = 'md-editor';
        quickReplyBox.style.cssText = `
            position: fixed;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
            z-index: 10001;
            width: 600px;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        `;

        // 创建标题栏(参考 a.html 的 window_header 风格,可拖动)
        const header = document.createElement('div');
        header.className = 'tab-select window_header';
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 15px;
            background: #f5f5f5;
            border-bottom: 1px solid #e0e0e0;
            cursor: move;
            user-select: none;
        `;
        
        const headerTitle = document.createElement('div');
        headerTitle.textContent = '快捷回复';
        headerTitle.style.cssText = `
            font-weight: 500;
            color: #333;
            font-size: 18px;
        `;
        header.appendChild(headerTitle);
        
        // 关闭按钮(参考 a.html 风格)
        const closeBtn = document.createElement('a');
        closeBtn.href = 'javascript:void(0)';
        closeBtn.className = 'editor-top-button';
        closeBtn.title = '关闭';
        closeBtn.style.cssText = `
            background-color: rgba(0, 0, 0, 0.1);
            padding: 4px 8px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.2s;
        `;
        closeBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 48 48" fill="none"><path d="M8 8L40 40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8 40L40 8" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
        closeBtn.onmouseover = () => closeBtn.style.backgroundColor = 'rgba(0, 0, 0, 0.15)';
        closeBtn.onmouseout = () => closeBtn.style.backgroundColor = 'rgba(0, 0, 0, 0.1)';
        header.appendChild(closeBtn);

        // 内容区域
        const content = document.createElement('div');
        content.id = 'editor-body';
        content.style.cssText = `
            padding: 15px;
            display: flex;
            flex-direction: column;
            gap: 15px;
        `;

        // 创建文本输入框
        const textarea = document.createElement('textarea');
        textarea.name = 'body';
        textarea.placeholder = '输入回复内容...';
        textarea.style.cssText = `
            width: 100%;
            min-height: 200px;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
            font-family: inherit;
            resize: none;
            overflow-y: hidden;
            box-sizing: border-box;
            outline: none;
        `;
        
        // 自动调整高度的函数
        const adjustTextareaHeight = () => {
            // 先重置高度,让scrollHeight能正确计算
            textarea.style.height = 'auto';
            // 获取实际需要的高度(scrollHeight已经包含了padding)
            const scrollHeight = textarea.scrollHeight;
            // 设置新高度,最小200px,减去1px避免底部多余空白
            textarea.style.height = Math.max(200, scrollHeight - 1) + 'px';
        };
        
        // 等待DOM更新后再设置初始高度
        setTimeout(() => {
            adjustTextareaHeight();
        }, 0);
        
        // 监听输入事件,动态调整高度
        textarea.addEventListener('input', adjustTextareaHeight);
        textarea.addEventListener('paste', () => {
            setTimeout(adjustTextareaHeight, 0);
        });

        // 创建提交按钮区域
        const footer = document.createElement('div');
        footer.style.cssText = `
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            padding-top: 10px;
            border-top: 1px solid #e0e0e0;
        `;

        const submitBtn = document.createElement('button');
        submitBtn.type = 'submit';
        submitBtn.textContent = '提交回复';
        submitBtn.className = 'submit btn';
        submitBtn.style.cssText = `
            padding: 8px 20px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: background 0.3s;
        `;
        submitBtn.onmouseover = () => submitBtn.style.background = '#1976D2';
        submitBtn.onmouseout = () => submitBtn.style.background = '#2196F3';

        // 创建表单
        const formElement = document.createElement('form');
        formElement.action = formAction;
        formElement.method = formMethod;
        formElement.style.cssText = 'display: flex; flex-direction: column; gap: 15px;';
        
        // 复制原始表单的所有隐藏字段
        if (form) {
            const hiddenInputs = form.querySelectorAll('input[type="hidden"]');
            hiddenInputs.forEach(input => {
                const clonedInput = input.cloneNode(true);
                formElement.appendChild(clonedInput);
            });
        }

        formElement.appendChild(textarea);
        footer.appendChild(submitBtn);
        formElement.appendChild(footer);
        content.appendChild(formElement);

        // 表单提交处理 - 将快捷回复框的内容复制到原始表单并提交
        formElement.onsubmit = (e) => {
            e.preventDefault();
            
            // 确保使用快捷回复框中的 textarea 值
            const quickReplyTextarea = formElement.querySelector('textarea[name="body"]');
            if (!quickReplyTextarea || !quickReplyTextarea.value.trim()) {
                alert('请输入回复内容');
                return;
            }
            
            // 重新查找原始回复框和表单(确保获取最新的)
            const currentOriginalCompose = document.getElementById('compose');
            if (!currentOriginalCompose) {
                alert('未找到原始回复框');
                return;
            }
            
            // 查找原始表单(compose 可能是 form,或者 form 在 compose 内部)
            let originalForm = currentOriginalCompose;
            if (currentOriginalCompose.tagName !== 'FORM') {
                originalForm = currentOriginalCompose.querySelector('form');
            }
            
            if (!originalForm) {
                // 如果 compose 本身不是 form,也没有内部的 form,尝试查找父级 form
                originalForm = currentOriginalCompose.closest('form');
            }
            
            if (!originalForm) {
                alert('未找到原始表单');
                return;
            }
            
            // 查找原始表单的 textarea
            const originalTextarea = originalForm.querySelector('textarea[name="body"]');
            if (!originalTextarea) {
                alert('未找到原始回复框的文本框');
                return;
            }
            
            // 保存快捷回复框的内容
            const replyContent = quickReplyTextarea.value;
            
            // 将内容设置到原始表单
            originalTextarea.value = replyContent;
            
            // 触发 input 事件,确保表单验证通过
            originalTextarea.dispatchEvent(new Event('input', { bubbles: true }));
            
            // 提交原始表单
            originalForm.submit();
        };

        // 组装悬浮框
        quickReplyBox.appendChild(header);
        quickReplyBox.appendChild(content);

        // 居中显示
        const clientHeight = document.documentElement.clientHeight;
        const clientWidth = document.documentElement.clientWidth;
        const boxHeight = 400;
        const boxWidth = 600;
        const top = (clientHeight / 2) - (boxHeight / 2);
        const left = (clientWidth / 2) - (boxWidth / 2);
        quickReplyBox.style.top = `${top}px`;
        quickReplyBox.style.left = `${left}px`;

        // 拖动功能
        let isDragging = false;
        let currentX = 0;
        let currentY = 0;
        let initialX = 0;
        let initialY = 0;

        const handleMouseDown = (e) => {
            if (e.button !== 0) return;
            isDragging = true;
            initialX = e.clientX - quickReplyBox.offsetLeft;
            initialY = e.clientY - quickReplyBox.offsetTop;
        };

        const handleMouseMove = (e) => {
            if (!isDragging) return;
            e.preventDefault();
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;
            
            // 限制在窗口内
            const maxX = window.innerWidth - quickReplyBox.offsetWidth;
            const maxY = window.innerHeight - quickReplyBox.offsetHeight;
            currentX = Math.max(0, Math.min(currentX, maxX));
            currentY = Math.max(0, Math.min(currentY, maxY));
            
            quickReplyBox.style.left = currentX + 'px';
            quickReplyBox.style.top = currentY + 'px';
        };

        const handleMouseUp = () => {
            isDragging = false;
        };

        const closeQuickReply = () => {
            quickReplyBox.remove();
            isQuickReplyOpen = false;
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', handleMouseUp);
        };

        header.addEventListener('mousedown', handleMouseDown);
        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);
        closeBtn.onclick = closeQuickReply;

        document.body.appendChild(quickReplyBox);
        isQuickReplyOpen = true;

        // 聚焦到文本框
        setTimeout(() => textarea.focus(), 100);
    }

    // 打开数据分析弹窗
    function openDataAnalysisDialog() {
        const { rows, maxBetIndex, hasRating } = collectBetPostsData();
        if (!rows || rows.length === 0) {
            alert('当前页面未找到下注内容,无法生成数据分析。');
            return;
        }

        const existing = document.getElementById('data-analysis-dialog');
        if (existing) {
            existing.remove();
        }

        const overlay = document.createElement('div');
        overlay.id = 'data-analysis-dialog';
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 10003;
            display: flex;
            justify-content: center;
            align-items: center;
        `;

        const dialog = document.createElement('div');
        dialog.style.cssText = `
            background: white;
            border-radius: 10px;
            padding: 20px;
            width: 1200px;
            max-width: 95vw;
            max-height: 90vh;
            overflow-y: auto;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
        `;

        const header = document.createElement('div');
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #2196F3;
            background: transparent;
        `;

        const title = document.createElement('h2');
        title.textContent = '下注数据分析';
        title.style.cssText = `
            margin: 0;
            padding: 0;
            color: #2196F3;
            font-size: 20px;
            background: transparent;
            border: none;
            outline: none;
        `;
        header.appendChild(title);

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '✕';
        closeBtn.style.cssText = `
            background: #f44336;
            color: white;
            border: none;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            transition: background 0.3s;
        `;
        closeBtn.onmouseover = () => closeBtn.style.background = '#d32f2f';
        closeBtn.onmouseout = () => closeBtn.style.background = '#f44336';
        closeBtn.onclick = () => overlay.remove();
        header.appendChild(closeBtn);

        const controlBar = document.createElement('div');
        controlBar.style.cssText = `
            display: flex;
            justify-content: flex-start;
            gap: 10px;
            align-items: center;
            margin-bottom: 10px;
        `;

        let summaryTextareaRef = null;
        const followBtn = document.createElement('button');
        followBtn.textContent = '只看特殊关注:关闭';
        followBtn.style.cssText = `
            padding: 6px 12px;
            border: 1px solid #2196F3;
            background: #fff;
            color: #2196F3;
            border-radius: 4px;
            cursor: pointer;
            transition: box-shadow 0.2s;
        `;
        const copyAnswerBtn = document.createElement('button');
        copyAnswerBtn.textContent = '复制答案';
        copyAnswerBtn.style.cssText = `
            padding: 6px 12px;
            border: 1px solid #4caf50;
            background: #fff;
            color: #4caf50;
            border-radius: 4px;
            cursor: pointer;
            transition: box-shadow 0.2s;
        `;
        const tableWrapper = document.createElement('div');
        tableWrapper.style.cssText = `
            border: 1px solid #ddd;
            border-radius: 8px;
            padding: 10px;
            background: #fafafa;
            max-height: 70vh;
            overflow: auto;
        `;

        let onlyFollow = Config.get('dataAnalysisOnlyFollow', false);

        const refreshTable = () => {
            followBtn.textContent = `只看特殊关注:${onlyFollow ? '开启' : '关闭'}`;
            followBtn.style.background = onlyFollow ? '#2196F3' : '#fff';
            followBtn.style.color = onlyFollow ? '#fff' : '#2196F3';
            summaryTextareaRef = renderDataAnalysisTable(rows, maxBetIndex, tableWrapper, onlyFollow, hasRating);
        };

        followBtn.onclick = () => {
            onlyFollow = !onlyFollow;
            Config.set('dataAnalysisOnlyFollow', onlyFollow);
            refreshTable();
        };
        copyAnswerBtn.onclick = () => {
            if (!summaryTextareaRef) return;
            const text = summaryTextareaRef.value;
            navigator.clipboard.writeText(text).then(() => {
                copyAnswerBtn.textContent = '已复制';
                setTimeout(() => copyAnswerBtn.textContent = '复制答案', 1500);
            }).catch(() => {
                alert('复制失败,请手动复制。');
            });
        };
        const addHoverEffect = (btn, baseColor) => {
            btn.onmouseover = () => btn.style.boxShadow = '0 0 8px rgba(0,0,0,0.15)';
            btn.onmouseout = () => btn.style.boxShadow = '';
        };
        addHoverEffect(followBtn);
        addHoverEffect(copyAnswerBtn);

        controlBar.appendChild(followBtn);
        controlBar.appendChild(copyAnswerBtn);

        dialog.appendChild(header);
        dialog.appendChild(controlBar);
        dialog.appendChild(tableWrapper);
        overlay.appendChild(dialog);
        document.body.appendChild(overlay);

        overlay.addEventListener('click', event => {
            if (event.target === overlay) {
                overlay.remove();
            }
        });

        refreshTable();
    }

    // 更新单个帖子行的备注展示(通过按钮文字体现)
    function updateUserNoteDisplayForTd(td, note) {
        const remarkBtn = td.querySelector('.author-remark-btn');
        if (!remarkBtn) {
            return;
        }

        if (note) {
            remarkBtn.textContent = `备注:${note}`;
            remarkBtn.style.fontWeight = 'bold';
        } else {
            remarkBtn.textContent = '备注';
            remarkBtn.style.fontWeight = 'normal';
        }
    }

    // 刷新指定用户的全部备注展示
    function refreshUserNoteDisplayByUserId(userId) {
        const note = getUserNoteById(userId);
        document.querySelectorAll(`td.embedded[data-user-id="${userId}"]`).forEach(td => {
            updateUserNoteDisplayForTd(td, note);
        });
    }

    // 追加评分总和
    // ratingSum: 可选的评分总和,如果不提供则自动计算
    function appendRatingSummary(postBody, ratingSum = null) {
        // 如果没有提供评分总和,则计算
        if (ratingSum === null) {
            ratingSum = calculateRatingSum(postBody);
        }

        // 如果评分为0,不显示
        if (ratingSum === 0) {
            return;
        }

        const container = postBody.parentElement;
        if (!container) return;

        // 查找包含"[评分]"的 div
        const ratingDiv = Array.from(container.querySelectorAll('div')).find(div => {
            const text = div.textContent || '';
            return text.includes('[评分]');
        });

        if (!ratingDiv) {
            return;
        }

        // 检查是否已经存在评分总和,如果存在则先移除
        const existingSummary = ratingDiv.querySelector('.rating-summary');
        if (existingSummary) {
            existingSummary.remove();
        }

        const prefix = ratingSum > 0 ? '+' : '';
        const summaryDiv = document.createElement('div');
        summaryDiv.className = 'rating-summary';
        summaryDiv.style.cssText = `
            margin-top: 6px;
            font-size: 14px;
            font-weight: bold;
        `;
        summaryDiv.textContent = `评分总和:${prefix}${ratingSum}`;

        ratingDiv.appendChild(summaryDiv);
    }

    // 在toolbox中添加复制按钮
    function addCopyButtonsToToolbox() {
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewtopic') return;

        document.querySelectorAll('td.toolbox').forEach((toolbox) => {
            // 如果已经添加过按钮,跳过
            if (toolbox.querySelector('.copy-post-btn')) return;

            // 设置toolbox样式,支持左右布局
            let rightContainer = toolbox.querySelector('.toolbox-right');
            if (!toolbox.dataset.styleSet) {
                toolbox.style.cssText = `
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    text-align: left;
                    border: none !important;
                `;
                toolbox.dataset.styleSet = 'true';
                
                // 创建右侧容器,存放原有按钮
                if (!rightContainer) {
                    rightContainer = document.createElement('span');
                    rightContainer.className = 'toolbox-right';
                    rightContainer.style.cssText = 'margin-left: auto; text-align: right;';
                    
                    // 将原有内容移到右侧容器
                    const existingElements = Array.from(toolbox.children);
                    existingElements.forEach(element => {
                        rightContainer.appendChild(element);
                    });
                    
                    toolbox.appendChild(rightContainer);
                }
            }
            
            // 确保动态添加的引用按钮也在右侧容器中
            if (!rightContainer) {
                rightContainer = toolbox.querySelector('.toolbox-right');
            }
            if (rightContainer) {
                // 检查toolbox直接子元素中是否有非复制按钮的元素,移到右侧容器
                Array.from(toolbox.children).forEach(child => {
                    if (child.className !== 'toolbox-right' && 
                        !child.classList.contains('copy-post-btn') && 
                        !child.classList.contains('copy-paste-post-btn')) {
                        rightContainer.appendChild(child);
                    }
                });
            }

            // 查找对应的post body - 通过toolbox所在的table.main来查找
            let postBody = null;
            
            // 从toolbox向上查找table.main
            const mainTable = toolbox.closest('table.main');
            if (mainTable) {
                // 在table.main的第一行tr中查找div[id$="body"]
                const firstTr = mainTable.querySelector('tr');
                if (firstTr) {
                    postBody = firstTr.querySelector('div[id$="body"]');
                }
            }
            
            // 如果还没找到,尝试通过pid table查找
            if (!postBody) {
                // 向上查找包含pid的table
                let current = toolbox.parentElement;
                while (current && !postBody) {
                    const pidTable = current.querySelector('table[id^="pid"]') || 
                                    (current.tagName === 'TABLE' && current.id && current.id.match(/^pid/) ? current : null);
                    
                    if (pidTable && pidTable.id) {
                        const pidMatch = pidTable.id.match(/^pid(\d+)/);
                        if (pidMatch && pidMatch[1]) {
                            postBody = document.getElementById(`pid${pidMatch[1]}body`);
                        }
                    }
                    
                    if (!postBody) {
                        current = current.parentElement;
                        if (!current || current === document.body) break;
                    }
                }
            }
            
            if (!postBody) return;

            const content = postBody.innerText || postBody.textContent || '';

            // 创建"复制"按钮
            const copyLink = document.createElement('a');
            copyLink.href = '#';
            copyLink.className = 'copy-post-btn';
            copyLink.textContent = '复制';
            copyLink.style.cssText = `
                display: inline-block;
                margin-right: 8px;
                padding: 6px 12px;
                background: #2196F3;
                color: white;
                text-decoration: none;
                border-radius: 4px;
                font-size: 12px;
                font-weight: 500;
                vertical-align: middle;
                line-height: 1.5;
                min-width: 60px;
                text-align: center;
            `;
            copyLink.onmouseover = function() {
                this.style.background = '#1976D2';
            };
            copyLink.onmouseout = function() {
                this.style.background = '#2196F3';
            };
            copyLink.onclick = (e) => {
                e.preventDefault();
                navigator.clipboard.writeText(content).then(() => {
                    const originalText = copyLink.textContent;
                    copyLink.textContent = '已复制';
                    setTimeout(() => {
                        copyLink.textContent = originalText;
                    }, 1500);
                }).catch(() => alert('复制失败'));
            };

            // 创建"复制到快捷回复"按钮
            const copyPasteLink = document.createElement('a');
            copyPasteLink.href = '#';
            copyPasteLink.className = 'copy-paste-post-btn';
            copyPasteLink.textContent = '复制到快捷回复';
            copyPasteLink.style.cssText = `
                display: inline-block;
                margin-right: 8px;
                padding: 6px 12px;
                background: #2196F3;
                color: white;
                text-decoration: none;
                border-radius: 4px;
                font-size: 12px;
                font-weight: 500;
                vertical-align: middle;
                line-height: 1.5;
                min-width: 120px;
                text-align: center;
            `;
            copyPasteLink.onmouseover = function() {
                this.style.background = '#1976D2';
            };
            copyPasteLink.onmouseout = function() {
                this.style.background = '#2196F3';
            };
            copyPasteLink.onclick = (e) => {
                e.preventDefault();
                navigator.clipboard.writeText(content).then(() => {
                    // 打开快捷回复框
                    if (!isQuickReplyOpen) {
                        openQuickReply();
                    }
                    
                    // 等待快捷回复框加载后粘贴内容
                    setTimeout(() => {
                        const quickReplyTextarea = document.querySelector('#quick-reply-box textarea[name="body"]');
                        if (quickReplyTextarea) {
                            // 保存原始背景色
                            const originalBg = quickReplyTextarea.style.backgroundColor || '';
                            const originalTransition = quickReplyTextarea.style.transition || '';
                            
                            // 设置过渡效果
                            quickReplyTextarea.style.transition = 'background-color 0.3s ease';
                            
                            // 粘贴内容
                            quickReplyTextarea.value = content;
                            quickReplyTextarea.dispatchEvent(new Event('input', { bubbles: true }));
                            
                            // // 背景色闪动效果:原始 -> 浅蓝 -> 原始,持续1秒
                            // quickReplyTextarea.style.backgroundColor = '#e3f2fd'; // 浅蓝色
                            // setTimeout(() => {
                            //     quickReplyTextarea.style.backgroundColor = originalBg;
                            //     // 恢复原始过渡设置
                            //     setTimeout(() => {
                            //         quickReplyTextarea.style.transition = originalTransition;
                            //     }, 300);
                            // }, 700); // 700ms后恢复,加上过渡时间300ms,总共约1秒

                            // 聚焦到回复框并设置光标位置
                            quickReplyTextarea.focus();
                            quickReplyTextarea.setSelectionRange(content.length, content.length);
                        }
                    }, 200);
                    
                    const originalText = copyPasteLink.textContent;
                    copyPasteLink.textContent = '已粘贴';
                    setTimeout(() => {
                        copyPasteLink.textContent = originalText;
                    }, 800);
                }).catch(() => alert('复制失败'));
            };

            // 插入到最左侧(在rightContainer之前)
            // 先插入"复制",再插入"复制到快捷回复",这样"复制"在左侧
            const insertBefore = toolbox.querySelector('.toolbox-right') || toolbox.firstChild;
            toolbox.insertBefore(copyLink, insertBefore);
            toolbox.insertBefore(copyPasteLink, insertBefore);
        });
    }

    // 自动为所有帖子显示评分总和
    function autoDisplayRatingSummary() {
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewtopic') {
            return;
        }

        // 查找所有帖子body
        const postBodies = document.querySelectorAll('div[id^="pid"][id$="body"]');
        postBodies.forEach(postBody => {
            // 计算评分总和,如果不为0则显示(传入已计算的值避免重复计算)
            const ratingSum = calculateRatingSum(postBody);
            if (ratingSum !== 0) {
                appendRatingSummary(postBody, ratingSum);
            }
        });
    }

    // 为帖子添加备注按钮与展示
    function enhanceAuthorRemarks() {
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewtopic') {
            return;
        }

        const embeddedTds = document.querySelectorAll('td.embedded');
        embeddedTds.forEach(td => {
            if (td.dataset.remarkBound === '1') {
                return;
            }

            const userLink = td.querySelector('a[href*="userdetails.php?id="]');
            if (!userLink) {
                return;
            }

            const userHref = userLink.getAttribute('href') || '';
            let userId = '';
            try {
                userId = new URL(userHref, window.location.href).searchParams.get('id') || '';
            } catch (e) {
                const match = userHref.match(/id=(\d+)/);
                if (match && match[1]) {
                    userId = match[1];
                }
            }

            if (!userId) {
                return;
            }

            const authorLink = Array.from(td.querySelectorAll('a[href*="authorid="]')).find(link => {
                const href = link.getAttribute('href') || '';
                try {
                    const authorId = new URL(href, window.location.href).searchParams.get('authorid');
                    return authorId === userId;
                } catch (e) {
                    const match = href.match(/authorid=(\d+)/);
                    return match && match[1] === userId;
                }
            });

            if (!authorLink) {
                return;
            }

            td.dataset.remarkBound = '1';
            td.dataset.userId = userId;

            const remarkBtn = document.createElement('button');
            remarkBtn.className = 'author-remark-btn';
            remarkBtn.textContent = '备注';
            remarkBtn.style.cssText = `
                padding: 0 4px;
                border: none;
                background: transparent;
                color: #1e73c1;
                cursor: pointer;
                font-size: 12px;
                text-decoration: none;
                font-weight: normal;
            `;

            remarkBtn.addEventListener('click', event => {
                event.preventDefault();
                event.stopPropagation();
                const username = (userLink.textContent || '').trim();
                const currentNote = getUserNoteById(userId);
                const result = prompt(`请输入对 ${username || '该用户'} 的备注(留空删除):`, currentNote);
                if (result === null) {
                    return;
                }
                const trimmed = result.trim();
                setUserNoteById(userId, trimmed);
                refreshUserNoteDisplayByUserId(userId);
            });

            authorLink.insertAdjacentElement('afterend', remarkBtn);
            const separator = document.createElement('font');
            separator.color = 'gray';
            separator.textContent = '\u00A0\u00A0|\u00A0';
            remarkBtn.parentNode.insertBefore(separator, remarkBtn);
            updateUserNoteDisplayForTd(td, getUserNoteById(userId));
        });
    }

    // 检查指定topicid的帖子是否已下注(检查所有分页),同时收集特殊关注用户
    async function checkTopicBetStatus(topicid) {
        const currentUsername = getCurrentUsername();
        if (!currentUsername) {
            return { hasBet: false, followUsers: [] };
        }

        const followList = getSpecialFollowList();
        const followSet = new Set(followList);
        const foundUsers = new Set();
        let hasBet = false;

        // 构建基础URL
        const baseUrl = `${window.location.origin}/forums.php?action=viewtopic&topicid=${topicid}`;
        
        // 先检查第一页
        try {
            const response = await fetch(baseUrl, { 
                credentials: 'include',
                headers: { 'Accept': 'text/html' }
            });
            
            if (!response.ok) {
                return { hasBet: false, followUsers: [] };
            }
            
            const html = await response.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');
            
            // 检查第一页是否已下注
            if (hasUserRepliedOnDocument(doc, currentUsername)) {
                hasBet = true;
            }
            
            // 收集第一页中的特殊关注用户
            if (followSet.size > 0) {
                const userLinks = doc.querySelectorAll('a[href*="userdetails.php?id"]');
                userLinks.forEach(link => {
                    if (link.closest('#info_block')) return; // 跳过当前用户信息
                    const username = link.textContent.trim();
                    if (followSet.has(username)) {
                        foundUsers.add(username);
                    }
                });
            }
            
            // 从第一页获取所有分页链接
            const pageNumbers = new Set();
            pageNumbers.add(0); // 第一页
            
            const pageLinks = doc.querySelectorAll('a[href*="viewtopic"][href*="topicid="]');
            pageLinks.forEach(link => {
                const href = link.getAttribute('href');
                if (!href) return;
                
                const match = href.match(/[?&]page=(\d+)/);
                if (match && match[1]) {
                    const pageNum = parseInt(match[1], 10);
                    if (!isNaN(pageNum)) {
                        pageNumbers.add(pageNum);
                    }
                }
            });
            
            // 检查其他分页
            for (let pageNum of pageNumbers) {
                if (pageNum === 0) continue; // 第一页已经检查过了
                
                const pageUrl = `${baseUrl}&page=${pageNum}`;
                try {
                    const pageResponse = await fetch(pageUrl, { 
                        credentials: 'include',
                        headers: { 'Accept': 'text/html' }
                    });
                    
                    if (pageResponse.ok) {
                        const pageHtml = await pageResponse.text();
                        const pageDoc = parser.parseFromString(pageHtml, 'text/html');
                        
                        // 检查该分页是否已下注
                        if (!hasBet && hasUserRepliedOnDocument(pageDoc, currentUsername)) {
                            hasBet = true;
                        }
                        
                        // 收集该分页中的特殊关注用户
                        if (followSet.size > 0) {
                            const pageUserLinks = pageDoc.querySelectorAll('a[href*="userdetails.php?id"]');
                            pageUserLinks.forEach(link => {
                                if (link.closest('#info_block')) return;
                                const username = link.textContent.trim();
                                if (followSet.has(username)) {
                                    foundUsers.add(username);
                                }
                            });
                        }
                    }
                } catch (e) {
                    // 忽略单个分页的错误,继续检查其他分页
                }
            }
        } catch (error) {
            console.error(`检查topicid ${topicid} 时发生错误:`, error);
        }
        
        return { 
            hasBet, 
            followUsers: Array.from(foundUsers) 
        };
    }

    // 在论坛列表页面标记每个帖子是否已下注
    async function markTopicBetStatus() {
        // 只在viewforum页面生效
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.get('action') !== 'viewforum') {
            return;
        }

        const currentUsername = getCurrentUsername();
        if (!currentUsername) {
            console.log('未获取到当前用户名,无法检查下注状态');
            return;
        }

        // 排除的topicid列表(不检查这些帖子的用户名和下注状态)
        const excludedTopicIds = new Set(['35207', '35212', '43558', '3239']);

        // 查找所有帖子链接(主题链接,不是分页链接)
        // 主题链接通常包含forumid参数,或者不包含page参数
        const topicLinks = document.querySelectorAll('td.embedded a[href*="viewtopic"][href*="topicid="]');
        const topicMap = new Map(); // 用于去重,key是topicid,value是链接元素

        topicLinks.forEach(link => {
            const href = link.getAttribute('href');
            if (!href) return;

            // 只处理主题链接(不包含page参数,且不是分页链接)
            // 分页链接通常格式是:?action=viewtopic&topicid=xxx&page=0
            // 主题链接通常格式是:?action=viewtopic&forumid=xx&topicid=xxx 或 ?action=viewtopic&topicid=xxx(没有page参数)
            if (href.includes('page=') || href.includes('page=p')) {
                return; // 跳过分页链接
            }

            // 提取topicid
            const match = href.match(/topicid=(\d+)/);
            if (match && match[1]) {
                const topicid = match[1];
                
                // 跳过排除列表中的topicid
                if (excludedTopicIds.has(topicid)) {
                    return;
                }
                
                // 每个topicid只保留第一个链接(避免重复检查)
                if (!topicMap.has(topicid)) {
                    topicMap.set(topicid, link);
                }
            }
        });

        console.log(`找到 ${topicMap.size} 个帖子,开始检查下注状态...`);

        // 对每个帖子检查是否已下注
        for (let [topicid, link] of topicMap) {
            // 检查是否已经添加过标记
            const parent = link.closest('td.embedded');
            if (!parent) continue;
            
            if (parent.querySelector('.bet-status-mark')) {
                continue; // 已经标记过,跳过
            }

            // 异步检查下注状态和特殊关注用户
            checkTopicBetStatus(topicid).then(({ hasBet, followUsers }) => {
                // 检查标记是否已存在(防止重复添加)
                if (parent.querySelector('.bet-status-mark')) {
                    return;
                }

                // 创建标记元素
                const mark = document.createElement('span');
                mark.className = 'bet-status-mark';
                mark.textContent = hasBet ? '【已下注】' : '【未下注】';
                mark.style.cssText = `
                    margin-left: 8px;
                    font-size: 12px;
                    font-weight: bold;
                    color: ${hasBet ? '#4caf50' : '#ff9800'};
                `;
                mark.title = hasBet ? '您已在此帖子下注' : '您尚未在此帖子下注';

                // 在链接后面插入标记
                // 如果链接后面有其他元素(如分页链接),插入到链接和分页链接之间
                link.parentNode.insertBefore(mark, link.nextSibling);
                
                // 如果有特殊关注用户回复,显示用户名列表
                if (followUsers && followUsers.length > 0) {
                    const followMark = document.createElement('span');
                    followMark.className = 'follow-users-mark';
                    followMark.textContent = ` [${followUsers.join(',')}]`;
                    followMark.style.cssText = `
                        margin-left: 4px;
                        font-size: 12px;
                        color: #2196F3;
                        font-weight: bold;
                    `;
                    followMark.title = '在此帖子回复过的特殊关注用户';
                    mark.parentNode.insertBefore(followMark, mark.nextSibling);
                }
            }).catch(err => {
                console.error(`检查topicid ${topicid} 下注状态失败:`, err);
            });
        }
    }

    // 初始化
    function init() {
        // 等待页面加载完成
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => {
                createControlPanel();
                autoHighlightFollowedPosts();
                autoLoadNextPage();
                checkValidBetAndDisableReply().catch(err => {
                    console.error('检查有效下注时发生错误:', err);
                }); // 检查有效下注(截止时间和重复下注)
                printBookmarkTopicIds(); // 打印收藏夹中的topicid列表
                highlightTopicIdRows(); // 高亮包含topicid的行
                markTopicBetStatus(); // 标记论坛列表页面每个帖子的下注状态
                renderSpecialFollowTiles(); // 渲染特殊关注磁贴
                enhanceAuthorRemarks(); // 添加备注按钮与展示
                autoDisplayRatingSummary(); // 自动显示评分总和
                // 延迟执行,确保toolbox已加载
                setTimeout(() => addCopyButtonsToToolbox(), 500);
                // 使用MutationObserver监听动态加载的toolbox
                if (!window.toolboxObserver) {
                    window.toolboxObserver = new MutationObserver(() => {
                        addCopyButtonsToToolbox();
                    });
                    window.toolboxObserver.observe(document.body, {
                        childList: true,
                        subtree: true
                    });
                }
            });
        } else {
            createControlPanel();
            autoHighlightFollowedPosts();
            autoLoadNextPage();
            checkValidBetAndDisableReply().catch(err => {
                console.error('检查有效下注时发生错误:', err);
            }); // 检查有效下注(截止时间和重复下注)
            printBookmarkTopicIds(); // 打印收藏夹中的topicid列表
            highlightTopicIdRows(); // 高亮包含topicid的行
            markTopicBetStatus(); // 标记论坛列表页面每个帖子的下注状态
            renderSpecialFollowTiles(); // 渲染特殊关注磁贴
            enhanceAuthorRemarks(); // 添加备注按钮与展示
            autoDisplayRatingSummary(); // 自动显示评分总和
            // 延迟执行,确保toolbox已加载
            setTimeout(() => addCopyButtonsToToolbox(), 500);
            // 使用MutationObserver监听动态加载的toolbox
            if (!window.toolboxObserver) {
                window.toolboxObserver = new MutationObserver(() => {
                    addCopyButtonsToToolbox();
                });
                window.toolboxObserver.observe(document.body, {
                    childList: true,
                    subtree: true
                });
            }
        }
    }

    // 启动脚本
    init();
})();