MediaWiki 批量管理工具

一个用于MediaWiki站点(包括Fandom, Miraheze, SkyWiki等)的批量删除、保护、用户管理工具。

// ==UserScript==
// @name         MediaWiki 批量管理工具
// @author       PandaFiredoge
// @version      4.0
// @description  一个用于MediaWiki站点(包括Fandom, Miraheze, SkyWiki等)的批量删除、保护、用户管理工具。
// @match        *://*.fandom.com/*/wiki/Special:*
// @match        *://*.fandom.com/wiki/Special:*
// @match        *://*.miraheze.org/wiki/Special:*
// @match        *://*.miraheze.org/w/index.php*Special:*
// @match        *://*.skywiki.org/wiki/Special:*
// @match        *://*.skywiki.org/w/index.php*Special:*
// @match        *://*/w/index.php*Special:*
// @match        *://*/wiki/Special:*
// @grant        none
// @license      GPL-3.0-or-later
// @namespace https://greasyfork.org/users/1413764
// ==/UserScript==

(function() {
    'use strict';

    // 确保mw API可用
    if (typeof mw === 'undefined' || typeof mw.Api === 'undefined') {
        console.error('MediaWiki API不可用,工具无法加载');
        return;
    }

    // 只在特殊页面运行
    if (!mw.config.get('wgCanonicalSpecialPageName')) return;

    // 确保用户有管理员权限
    if (!mw.config.get('wgUserGroups') || !mw.config.get('wgUserGroups').includes('sysop')) {
        console.log('用户没有管理员权限,批量删除工具不会加载');
        return;
    }

    // 创建工具界面
    function createInterface() {
        const container = document.createElement('div');
        container.id = 'bulk-delete-tool';
        container.style.cssText = 'padding: 15px; margin: 15px 0; border: 1px solid #ccc; border-radius: 4px; background-color: #f9f9f9;';

        container.innerHTML = `
            <h2 style="margin-top: 0;">批量删除与保护页面工具</h2>
            <p>输入要删除的页面标题(每行一个):</p>
            <textarea id="pages-to-delete" style="width: 100%; height: 150px; margin-bottom: 10px; padding: 8px; box-sizing: border-box; border: 1px solid #ddd;"></textarea>

            <div style="margin-top: 15px;">
                <label for="delete-reason">删除原因:</label>
                <input type="text" id="delete-reason" value="批量清理" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
            </div>

            <div style="margin-top: 15px; display: flex; align-items: center;">
                <label for="processing-rate" style="margin-right: 10px;">处理速率:</label>
                <input type="number" id="processing-rate" min="0.2" max="10" step="0.1" value="1" style="width: 70px; padding: 8px; border: 1px solid #ddd;">
                <span style="margin-left: 5px;">秒/页面</span>
                <div style="margin-left: 15px; color: #666; font-size: 0.9em;">
                    (推荐:0.5-2秒,过快可能导致API限制)
                </div>
            </div>

            <div style="margin-top: 15px;">
                <label>
                    <input type="checkbox" id="protect-after-delete" style="margin-right: 5px;">
                    删除后保护页面
                </label>
            </div>

            <div id="protection-options" style="margin-top: 10px; padding: 10px; background-color: #f5f5f5; border-radius: 4px; display: none;">
                <div style="margin-bottom: 10px;">
                    <label for="protection-level">保护级别:</label>
                    <select id="protection-level" style="padding: 5px;">
                        <option value="sysop">仅管理员</option>
                        <option value="autoconfirmed">仅自动确认用户</option>
                    </select>
                </div>
                <div>
                    <label for="protection-reason">保护原因:</label>
                    <input type="text" id="protection-reason" value="防止重建" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                </div>
                <div style="margin-top: 10px;">
                    <label for="protection-expiry">保护期限:</label>
                    <select id="protection-expiry" style="padding: 5px;">
                        <option value="1 week">1周</option>
                        <option value="1 month">1个月</option>
                        <option value="3 months">3个月</option>
                        <option value="6 months">6个月</option>
                        <option value="1 year">1年</option>
                        <option value="infinite" selected>永久</option>
                    </select>
                </div>
            </div>

            <div style="margin-top: 15px; display: flex; gap: 10px; flex-wrap: wrap;">
                <button id="load-category-button" style="padding: 8px 15px; background-color: #3a87ad; color: white; border: none; border-radius: 3px; cursor: pointer;">加载分类页面</button>
                <button id="load-prefix-button" style="padding: 8px 15px; background-color: #3a87ad; color: white; border: none; border-radius: 3px; cursor: pointer;">加载前缀页面</button>
                <button id="load-regex-button" style="padding: 8px 15px; background-color: #3a87ad; color: white; border: none; border-radius: 3px; cursor: pointer;">正则匹配页面</button>
                <button id="load-user-pages-button" style="padding: 8px 15px; background-color: #3a87ad; color: white; border: none; border-radius: 3px; cursor: pointer;">用户创建的页面</button>
                <button id="rollback-user-button" style="padding: 8px 15px; background-color: #d9534f; color: white; border: none; border-radius: 3px; cursor: pointer;">回退用户编辑</button>
                <button id="manage-user-button" style="padding: 8px 15px; background-color: #d9534f; color: white; border: none; border-radius: 3px; cursor: pointer; font-weight: bold;">一键处理用户</button>
                <button id="preview-button" style="padding: 8px 15px; background-color: #5bc0de; color: white; border: none; border-radius: 3px; cursor: pointer;">预览页面列表</button>
                <button id="delete-button" style="padding: 8px 15px; background-color: #d9534f; color: white; border: none; border-radius: 3px; cursor: pointer;">开始删除</button>
            </div>

            <div id="modal-container" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5);">
                <div id="modal-content" style="background-color: white; margin: 10% auto; padding: 20px; border-radius: 5px; width: 70%; max-width: 800px; max-height: 80vh; overflow-y: auto;">
                    <span id="modal-close" style="float: right; cursor: pointer; font-size: 20px;">&times;</span>
                    <div id="modal-body"></div>
                </div>
            </div>

            <div id="deletion-status" style="margin-top: 15px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; display: none;">
                <div id="progress-container">
                    <div id="progress-bar" style="width: 100%; height: 20px; background-color: #f5f5f5; border-radius: 4px; margin: 10px 0;">
                        <div id="progress" style="width: 0%; height: 100%; background-color: #5cb85c; border-radius: 4px;"></div>
                    </div>
                    <div id="progress-text">准备中...</div>
                </div>
                <div id="deletion-results" style="margin-top: 15px; max-height: 300px; overflow-y: auto;"></div>
            </div>

            <div id="tool-message" style="margin-top: 15px; padding: 10px; border-radius: 4px; display: none;"></div>
        `;

        // 将工具添加到页面
        const mainContent = document.querySelector('#WikiaMainContent, .WikiaMainContent, #mw-content-text, .mw-body-content');
        if (mainContent) {
            mainContent.prepend(container);
        } else {
            document.body.prepend(container);
        }

        // 添加事件监听器
        document.getElementById('preview-button').addEventListener('click', previewPages);
        document.getElementById('delete-button').addEventListener('click', startDeletion);
        document.getElementById('load-category-button').addEventListener('click', showCategoryModal);
        document.getElementById('load-prefix-button').addEventListener('click', showPrefixModal);
        document.getElementById('load-regex-button').addEventListener('click', showRegexModal);
        document.getElementById('load-user-pages-button').addEventListener('click', showUserPagesModal);
        document.getElementById('rollback-user-button').addEventListener('click', showRollbackModal);
        document.getElementById('manage-user-button').addEventListener('click', showManageUserModal); // 新增一键处理用户按钮事件
        document.getElementById('modal-close').addEventListener('click', closeModal);

        // 添加保护选项切换功能
        document.getElementById('protect-after-delete').addEventListener('change', function() {
            document.getElementById('protection-options').style.display = this.checked ? 'block' : 'none';
        });

        // 添加处理速率验证
        const rateInput = document.getElementById('processing-rate');
        rateInput.addEventListener('change', function() {
            const value = parseFloat(this.value);
            if (isNaN(value) || value < 0.2) {
                this.value = 0.2;
                showMessage('处理速率不能低于0.2秒/页面', 'error');
            } else if (value > 10) {
                this.value = 10;
                showMessage('处理速率不能高于10秒/页面', 'error');
            }
        });

        // 添加CSS样式
        addStyles();
    }

    // 添加 CSS 样式,保持原有代码,添加一些新的样式
    function addStyles() {
        const style = document.createElement('style');
        style.textContent = `
            .collapsible-section {
                border: 1px solid #ddd;
                border-radius: 4px;
                margin-bottom: 15px;
            }

            .collapsible-header {
                padding: 10px;
                background-color: #f5f5f5;
                cursor: pointer;
                display: flex;
                justify-content: space-between;
                align-items: center;
                font-weight: bold;
            }

            .collapsible-header:hover {
                background-color: #e9e9e9;
            }

            .collapsible-content {
                padding: 10px;
                border-top: 1px solid #ddd;
                max-height: 300px;
                overflow-y: auto;
            }

            .collapsed .collapsible-content {
                display: none;
            }

            .page-list-container {
                max-height: 300px;
                overflow-y: auto;
                border: 1px solid #ddd;
                padding: 10px;
                margin: 10px 0;
            }

            .action-buttons {
                position: sticky;
                bottom: 0;
                background-color: white;
                padding: 10px 0;
                border-top: 1px solid #ddd;
                margin-top: 10px;
            }

            #modal-content {
                display: flex;
                flex-direction: column;
            }

            #modal-body {
                overflow-y: auto;
            }

            .rate-control {
                display: flex;
                align-items: center;
                margin-top: 15px;
            }

            .rate-slider {
                flex: 1;
                margin: 0 10px;
            }

            .rate-value {
                width: 60px;
                text-align: center;
            }

            .ban-options {
                margin-top: 15px;
                padding: 10px;
                background-color: #f8d7da;
                border: 1px solid #f5c6cb;
                border-radius: 4px;
            }

            .ban-options.disabled {
                opacity: 0.5;
                pointer-events: none;
            }

            .edit-item {
                padding: 8px;
                border-bottom: 1px solid #eee;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .edit-item:hover {
                background-color: #f9f9f9;
            }

            .edit-info {
                flex: 1;
            }

            .tab-container {
                margin-bottom: 15px;
            }

            .tab-header {
                display: flex;
                border-bottom: 1px solid #ddd;
            }

            .tab {
                padding: 8px 15px;
                background-color: #f5f5f5;
                cursor: pointer;
                border: 1px solid #ddd;
                border-bottom: none;
                margin-right: 5px;
                border-top-left-radius: 3px;
                border-top-right-radius: 3px;
            }

            .tab.active {
                background-color: white;
                border-bottom: 1px solid white;
                margin-bottom: -1px;
            }

            .tab-content {
                display: none;
                padding: 15px;
                border: 1px solid #ddd;
                border-top: none;
            }

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

            .rollback-options {
                margin-top: 15px;
                padding: 10px;
                background-color: #f8f9fa;
                border: 1px solid #e9ecef;
                border-radius: 4px;
            }

            /* 一键处理用户相关样式 */
            .manage-user-options {
                margin-top: 15px;
                padding: 15px;
                background-color: #f8f9fa;
                border: 1px solid #e9ecef;
                border-radius: 4px;
            }

            .manage-user-section {
                margin-bottom: 20px;
                padding-bottom: 15px;
                border-bottom: 1px dashed #ddd;
            }

            .manage-user-section:last-child {
                border-bottom: none;
            }

            .manage-user-section h4 {
                margin-top: 0;
                margin-bottom: 10px;
                color: #333;
            }

            .progress-step {
                display: flex;
                align-items: center;
                margin-bottom: 5px;
            }

            .progress-indicator {
                width: 20px;
                height: 20px;
                border-radius: 50%;
                background-color: #f5f5f5;
                border: 1px solid #ddd;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-right: 10px;
                font-size: 12px;
                font-weight: bold;
            }

            .progress-step.active .progress-indicator {
                background-color: #5bc0de;
                color: white;
                border-color: #5bc0de;
            }

            .progress-step.completed .progress-indicator {
                background-color: #5cb85c;
                color: white;
                border-color: #5cb85c;
            }

            .progress-step.error .progress-indicator {
                background-color: #d9534f;
                color: white;
                border-color: #d9534f;
            }

            .progress-label {
                flex: 1;
            }

            .progress-status {
                font-style: italic;
                color: #666;
                font-size: 0.9em;
            }
        `;
        document.head.appendChild(style);
    }

    // 显示消息
    function showMessage(message, type) {
        const messageElement = document.getElementById('tool-message');
        messageElement.textContent = message;
        messageElement.style.display = 'block';

        if (type === 'error') {
            messageElement.style.backgroundColor = '#f2dede';
            messageElement.style.borderColor = '#ebccd1';
            messageElement.style.color = '#a94442';
        } else if (type === 'success') {
            messageElement.style.backgroundColor = '#dff0d8';
            messageElement.style.borderColor = '#d6e9c6';
            messageElement.style.color = '#3c763d';
        } else {
            messageElement.style.backgroundColor = '#d9edf7';
            messageElement.style.borderColor = '#bce8f1';
            messageElement.style.color = '#31708f';
        }

        // 5秒后自动隐藏
        setTimeout(() => {
            messageElement.style.display = 'none';
        }, 5000);
    }

    // 显示模态框
    function showModal(title, content) {
        document.getElementById('modal-container').style.display = 'block';
        document.getElementById('modal-body').innerHTML = `
            <h3>${title}</h3>
            ${content}
        `;

        // 修复:立即添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();
    }

    // 关闭模态框
    function closeModal() {
        document.getElementById('modal-container').style.display = 'none';
    }

    // 添加折叠区域的事件监听器
    function addCollapsibleSectionsEventListeners() {
        document.querySelectorAll('.collapsible-header').forEach(header => {
            // 移除现有事件监听器防止重复
            header.removeEventListener('click', toggleCollapsibleSection);
            // 添加新的事件监听器
            header.addEventListener('click', toggleCollapsibleSection);
        });
    }

    // 切换折叠区域
    function toggleCollapsibleSection() {
        const section = this.parentElement;
        section.classList.toggle('collapsed');
        const chevron = this.querySelector('.chevron');
        if (chevron) {
            chevron.textContent = section.classList.contains('collapsed') ? '▼' : '▲';
        }
    }

    // 创建可折叠区域
    function createCollapsibleSection(title, contentHtml, initiallyCollapsed = false) {
        return `
            <div class="collapsible-section ${initiallyCollapsed ? 'collapsed' : ''}">
                <div class="collapsible-header">
                    <span>${title}</span>
                    <span class="chevron">${initiallyCollapsed ? '▼' : '▲'}</span>
                </div>
                <div class="collapsible-content">
                    ${contentHtml}
                </div>
            </div>
        `;
    }

    // 新增:显示一键处理用户模态框
    function showManageUserModal() {
        const content = `
            <div style="margin-bottom: 15px;">
                <label for="manage-username">用户名:</label>
                <input type="text" id="manage-username" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;" placeholder="输入要处理的用户名(不含User:前缀)">
            </div>

            <div style="margin-bottom: 15px;">
                <label for="manage-date-limit">时间限制(可选):</label>
                <input type="date" id="manage-date-limit" style="padding: 8px; margin-top: 5px; border: 1px solid #ddd;">
                <small style="display: block; margin-top: 5px; color: #666;">只处理此日期之后的操作。留空表示处理所有内容。</small>
            </div>

            <div class="manage-user-options">
                <div class="manage-user-section">
                    <h4>封禁设置</h4>
                    <div style="margin-bottom: 10px;">
                        <label for="manage-ban-reason">封禁原因:</label>
                        <input type="text" id="manage-ban-reason" value="破坏行为" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                    </div>

                    <div style="margin-bottom: 10px;">
                        <label for="manage-ban-duration">封禁期限:</label>
                        <select id="manage-ban-duration" style="padding: 5px;">
                            <option value="1 day">1天</option>
                            <option value="3 days">3天</option>
                            <option value="1 week">1周</option>
                            <option value="2 weeks">2周</option>
                            <option value="1 month">1个月</option>
                            <option value="3 months">3个月</option>
                            <option value="6 months">6个月</option>
                            <option value="1 year">1年</option>
                            <option value="infinite" selected>永久</option>
                        </select>
                    </div>

                    <div>
                        <input type="checkbox" id="manage-ban-autoblock" checked style="margin-right: 5px;">
                        <label for="manage-ban-autoblock">自动封禁最后使用的IP地址</label>
                    </div>

                    <div>
                        <input type="checkbox" id="manage-ban-talk-page" style="margin-right: 5px;">
                        <label for="manage-ban-talk-page">阻止用户编辑自己的讨论页</label>
                    </div>
                </div>

                <div class="manage-user-section">
                    <h4>回退设置</h4>
                    <div style="margin-bottom: 10px;">
                        <label for="manage-rollback-reason">回退原因:</label>
                        <input type="text" id="manage-rollback-reason" value="回退破坏性编辑" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                    </div>

                    <div style="margin-bottom: 10px;">
                        <label for="manage-rollback-limit">最大回退数量:</label>
                        <input type="number" id="manage-rollback-limit" value="200" min="1" max="500" style="width: 100px; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                        <small style="display: block; margin-top: 5px; color: #666;">建议不超过200,以避免API限制</small>
                    </div>
                </div>

                <div class="manage-user-section">
                    <h4>删除设置</h4>
                    <div style="margin-bottom: 10px;">
                        <label for="manage-delete-reason">删除原因:</label>
                        <input type="text" id="manage-delete-reason" value="清理破坏内容" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                    </div>

                    <div>
                        <input type="checkbox" id="manage-protect-pages" checked style="margin-right: 5px;">
                        <label for="manage-protect-pages">删除后保护页面</label>
                    </div>

                    <div id="manage-protection-options" style="margin-top: 10px; padding: 10px; background-color: #f5f5f5; border-radius: 4px;">
                        <div style="margin-bottom: 10px;">
                            <label for="manage-protection-level">保护级别:</label>
                            <select id="manage-protection-level" style="padding: 5px;">
                                <option value="sysop" selected>仅管理员</option>
                                <option value="autoconfirmed">仅自动确认用户</option>
                            </select>
                        </div>
                        <div>
                            <label for="manage-protection-reason">保护原因:</label>
                            <input type="text" id="manage-protection-reason" value="防止重建" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                        </div>
                        <div style="margin-top: 10px;">
                            <label for="manage-protection-expiry">保护期限:</label>
                            <select id="manage-protection-expiry" style="padding: 5px;">
                                <option value="1 week">1周</option>
                                <option value="1 month">1个月</option>
                                <option value="3 months">3个月</option>
                                <option value="6 months">6个月</option>
                                <option value="1 year">1年</option>
                                <option value="infinite" selected>永久</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>

            ${createCollapsibleSection('命名空间选项', `
                <div style="margin-top: 5px;">
                    <input type="checkbox" id="manage-namespace-main" checked>
                    <label for="manage-namespace-main">主命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="manage-namespace-user">
                    <label for="manage-namespace-user">用户命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="manage-namespace-template">
                    <label for="manage-namespace-template">模板命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="manage-namespace-category">
                    <label for="manage-namespace-category">分类命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="manage-namespace-file">
                    <label for="manage-namespace-file">文件命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="manage-namespace-other">
                    <label for="manage-namespace-other">其他命名空间</label>
                </div>
            `, true)}

            <button id="start-manage-user-button" style="padding: 8px 15px; background-color: #d9534f; color: white; border: none; border-radius: 3px; cursor: pointer; margin-top: 15px; font-weight: bold;">开始处理用户</button>
        `;

        showModal('一键处理用户', content);

        // 添加保护选项切换功能
        document.getElementById('manage-protect-pages').addEventListener('change', function() {
            document.getElementById('manage-protection-options').style.display = this.checked ? 'block' : 'none';
        });

        // 添加开始处理按钮事件
        document.getElementById('start-manage-user-button').addEventListener('click', function() {
            const username = document.getElementById('manage-username').value.trim();
            if (!username) {
                showMessage('请输入有效的用户名', 'error');
                return;
            }

            // 获取所有设置
            const settings = {
                username: username,
                dateLimit: document.getElementById('manage-date-limit').value,

                // 封禁设置
                ban: {
                    reason: document.getElementById('manage-ban-reason').value,
                    duration: document.getElementById('manage-ban-duration').value,
                    autoBlock: document.getElementById('manage-ban-autoblock').checked,
                    disallowTalkPage: document.getElementById('manage-ban-talk-page').checked
                },

                // 回退设置
                rollback: {
                    reason: document.getElementById('manage-rollback-reason').value,
                    limit: parseInt(document.getElementById('manage-rollback-limit').value) || 200
                },

                // 删除设置
                deletion: {
                    reason: document.getElementById('manage-delete-reason').value,
                    protect: document.getElementById('manage-protect-pages').checked,
                    protection: {
                        level: document.getElementById('manage-protection-level').value,
                        reason: document.getElementById('manage-protection-reason').value,
                        expiry: document.getElementById('manage-protection-expiry').value
                    }
                },

                // 命名空间设置
                namespaces: []
            };

            // 获取选中的命名空间
            if (document.getElementById('manage-namespace-main').checked) settings.namespaces.push(0);
            if (document.getElementById('manage-namespace-user').checked) settings.namespaces.push(2, 3);
            if (document.getElementById('manage-namespace-template').checked) settings.namespaces.push(10, 11);
            if (document.getElementById('manage-namespace-category').checked) settings.namespaces.push(14, 15);
            if (document.getElementById('manage-namespace-file').checked) settings.namespaces.push(6, 7);
            if (document.getElementById('manage-namespace-other').checked) settings.namespaces.push(4, 5, 8, 9, 12, 13);

            // 确认对话框
            if (confirm(`您即将对用户 "${username}" 执行以下操作:\n1. 封禁用户\n2. 回退用户编辑\n3. 删除用户创建的页面\n\n是否继续?`)) {
                // 关闭模态框
                closeModal();

                // 开始处理用户
                startManageUser(settings);
            }
        });
    }

    // 新增:开始处理用户
    function startManageUser(settings) {
        // 显示进度条
        const statusContainer = document.getElementById('deletion-status');
        statusContainer.style.display = 'block';

        const progressElement = document.getElementById('progress');
        const progressTextElement = document.getElementById('progress-text');
        const resultsElement = document.getElementById('deletion-results');

        // 重置进度条
        progressElement.style.width = '0%';

        // 清空结果区
        resultsElement.innerHTML = `
            <div style="margin-bottom: 20px;">
                <h4>处理用户:${settings.username}</h4>
                <div id="manage-user-progress">
                    <div class="progress-step" id="step-ban">
                        <div class="progress-indicator">1</div>
                        <div class="progress-label">封禁用户</div>
                        <div class="progress-status">等待中...</div>
                    </div>
                    <div class="progress-step" id="step-rollback">
                        <div class="progress-indicator">2</div>
                        <div class="progress-label">回退编辑</div>
                        <div class="progress-status">等待中...</div>
                    </div>
                    <div class="progress-step" id="step-delete">
                        <div class="progress-indicator">3</div>
                        <div class="progress-label">删除创建的页面</div>
                        <div class="progress-status">等待中...</div>
                    </div>
                </div>
            </div>
            <div id="manage-user-details"></div>
        `;

        progressTextElement.textContent = `正在处理用户:${settings.username}`;

        // 获取自定义处理速率
        const processingRate = parseFloat(document.getElementById('processing-rate').value) * 1000; // 转换为毫秒

        // 开始执行步骤 1:封禁用户
        executeManageUserStep1_Ban(settings, processingRate);
    }

    // 执行步骤 1:封禁用户
    function executeManageUserStep1_Ban(settings, processingRate) {
        // 更新步骤状态
        updateStepStatus('step-ban', 'active', '正在封禁用户...');

        const detailsContainer = document.getElementById('manage-user-details');
        detailsContainer.innerHTML += `<div style="margin-top: 10px;"><strong>正在封禁用户 ${settings.username}...</strong></div>`;

        // 执行封禁API调用
        banUser(
            settings.username,
            settings.ban.reason,
            settings.ban.duration,
            settings.ban.autoBlock,
            settings.ban.disallowTalkPage,
            function(success, message) {
                if (success) {
                    updateStepStatus('step-ban', 'completed', '用户已封禁');
                    detailsContainer.innerHTML += `<div style="color: #3c763d;">✓ 用户 ${settings.username} 已成功封禁</div>`;
                } else {
                    updateStepStatus('step-ban', 'error', '封禁失败');
                    detailsContainer.innerHTML += `<div style="color: #a94442;">✗ 封禁用户 ${settings.username} 失败: ${message}</div>`;
                }

                // 继续执行步骤 2:加载并回退用户编辑
                setTimeout(function() {
                    executeManageUserStep2_Rollback(settings, processingRate);
                }, 1000); // 延迟1秒继续
            }
        );
    }

    // 执行步骤 2:加载并回退用户编辑
    function executeManageUserStep2_Rollback(settings, processingRate) {
        // 更新步骤状态
        updateStepStatus('step-rollback', 'active', '正在加载用户编辑...');

        const detailsContainer = document.getElementById('manage-user-details');
        detailsContainer.innerHTML += `<div style="margin-top: 15px;"><strong>正在加载用户 ${settings.username} 的编辑...</strong></div>`;

        // 加载用户编辑
        const api = new mw.Api();

        // 构建参数
        let params = {
            action: 'query',
            list: 'usercontribs',
            ucuser: settings.username,
            uclimit: Math.min(settings.rollback.limit, 500), // API限制通常为500
            ucprop: 'title|timestamp|comment|ids',
            format: 'json'
        };

        // 添加日期限制
        if (settings.dateLimit) {
            params.ucend = settings.dateLimit + 'T00:00:00Z'; // 转换为ISO格式
        }

        // 添加命名空间限制
        if (settings.namespaces && settings.namespaces.length > 0) {
            params.ucnamespace = settings.namespaces.join('|');
        }

        // 保存找到的编辑
        const userEdits = [];

        // 获取用户编辑记录
        api.get(params).done(function(data) {
            if (data.query && data.query.usercontribs && data.query.usercontribs.length > 0) {
                data.query.usercontribs.forEach(function(contrib) {
                    userEdits.push({
                        title: contrib.title,
                        revid: contrib.revid,
                        timestamp: contrib.timestamp,
                        comment: contrib.comment
                    });
                });

                detailsContainer.innerHTML += `<div>找到 ${userEdits.length} 个编辑,准备回退...</div>`;

                // 显示进度
                updateStepStatus('step-rollback', 'active', `找到 ${userEdits.length} 个编辑`);

                // 开始回退编辑
                processManageUserRollback(userEdits, settings, 0, processingRate);
            } else {
                // 没有找到编辑
                detailsContainer.innerHTML += `<div>未找到用户 ${settings.username} 的编辑,跳过回退步骤。</div>`;
                updateStepStatus('step-rollback', 'completed', '无编辑需回退');

                // 继续执行步骤 3:加载并删除用户创建的页面
                setTimeout(function() {
                    executeManageUserStep3_Delete(settings, processingRate);
                }, 1000); // 延迟1秒继续
            }
        }).fail(function(code, result) {
            // 加载编辑失败
            detailsContainer.innerHTML += `<div style="color: #a94442;">✗ 加载用户编辑失败: ${result.error ? result.error.info : code}</div>`;
            updateStepStatus('step-rollback', 'error', '加载编辑失败');

            // 继续执行步骤 3
            setTimeout(function() {
                executeManageUserStep3_Delete(settings, processingRate);
            }, 1000); // 延迟1秒继续
        });
    }

    // 处理用户回退过程
    function processManageUserRollback(edits, settings, index, processingRate) {
        const detailsContainer = document.getElementById('manage-user-details');

        if (index >= edits.length) {
            // 所有编辑处理完毕
            updateStepStatus('step-rollback', 'completed', `已回退 ${edits.length} 个编辑`);
            detailsContainer.innerHTML += `<div style="color: #3c763d;">✓ 已完成所有编辑的回退</div>`;

            // 继续执行步骤 3:加载并删除用户创建的页面
            setTimeout(function() {
                executeManageUserStep3_Delete(settings, processingRate);
            }, 1000); // 延迟1秒继续
            return;
        }

        const edit = edits[index];
        const progressElement = document.getElementById('progress');

        // 更新进度
        const progressPercentage = Math.round((index / edits.length) * 33); // 回退占总进度的33%
        progressElement.style.width = progressPercentage + '%';

        // 更新步骤状态
        updateStepStatus('step-rollback', 'active', `正在回退 ${index + 1}/${edits.length}`);

        // 执行回退API调用
        rollbackEdit(edit.title, settings.username, settings.rollback.reason, function(success, message) {
            // 添加结果到列表
            if (success) {
                detailsContainer.innerHTML += `<div style="color: #3c763d;">✓ 成功回退: ${edit.title}</div>`;
            } else {
                detailsContainer.innerHTML += `<div style="color: #a94442;">✗ 回退失败: ${edit.title} - ${message}</div>`;
            }

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processManageUserRollback(edits, settings, index + 1, processingRate);
            }, processingRate);
        });
    }

    // 执行步骤 3:加载并删除用户创建的页面
    function executeManageUserStep3_Delete(settings, processingRate) {
        // 更新步骤状态
        updateStepStatus('step-delete', 'active', '正在加载用户创建的页面...');

        const detailsContainer = document.getElementById('manage-user-details');
        detailsContainer.innerHTML += `<div style="margin-top: 15px;"><strong>正在加载用户 ${settings.username} 创建的页面...</strong></div>`;

        // 加载用户创建的页面
        const api = new mw.Api();

        // 构建参数
        let params = {
            action: 'query',
            list: 'usercontribs',
            ucuser: settings.username,
            uclimit: 500,
            ucprop: 'title|timestamp',
            ucshow: 'new', // 只显示创建新页面的贡献
            format: 'json'
        };

        // 添加日期限制
        if (settings.dateLimit) {
            params.ucend = settings.dateLimit + 'T00:00:00Z'; // 转换为ISO格式
        }

        // 添加命名空间限制
        if (settings.namespaces && settings.namespaces.length > 0) {
            params.ucnamespace = settings.namespaces.join('|');
        }

        // 保存找到的页面
        const userPages = [];

        // 递归函数获取所有页面
        function getUserPages(continueParam) {
            if (continueParam) {
                // 添加continue参数
                for (let prop in continueParam) {
                    params[prop] = continueParam[prop];
                }
            }

            api.get(params).done(function(data) {
                if (data.query && data.query.usercontribs) {
                    data.query.usercontribs.forEach(function(contrib) {
                        userPages.push({
                            title: contrib.title,
                            timestamp: contrib.timestamp
                        });
                    });

                    // 更新状态信息
                    detailsContainer.innerHTML += `<div>已找到 ${userPages.length} 个页面,继续搜索...</div>`;

                    // 如果有更多结果,继续查询
                    if (data.continue) {
                        getUserPages(data.continue);
                    } else {
                        // 完成所有查询
                        if (userPages.length > 0) {
                            detailsContainer.innerHTML += `<div>共找到 ${userPages.length} 个页面,准备删除...</div>`;
                            updateStepStatus('step-delete', 'active', `找到 ${userPages.length} 个页面`);

                            // 开始删除页面
                            processManageUserDeletion(userPages, settings, 0, processingRate);
                        } else {
                            // 没有找到页面
                            detailsContainer.innerHTML += `<div>未找到用户 ${settings.username} 创建的页面,流程完成。</div>`;
                            updateStepStatus('step-delete', 'completed', '无页面需删除');
                            completeManageUserProcess(settings);
                        }
                    }
                } else {
                    // 没有找到贡献
                    if (userPages.length === 0) {
                        detailsContainer.innerHTML += `<div>未找到用户 ${settings.username} 创建的页面,流程完成。</div>`;
                        updateStepStatus('step-delete', 'completed', '无页面需删除');
                        completeManageUserProcess(settings);
                    } else {
                        detailsContainer.innerHTML += `<div>共找到 ${userPages.length} 个页面,准备删除...</div>`;
                        updateStepStatus('step-delete', 'active', `找到 ${userPages.length} 个页面`);
                        processManageUserDeletion(userPages, settings, 0, processingRate);
                    }
                }
            }).fail(function(code, result) {
                // 加载页面失败
                detailsContainer.innerHTML += `<div style="color: #a94442;">✗ 加载用户创建的页面失败: ${result.error ? result.error.info : code}</div>`;
                updateStepStatus('step-delete', 'error', '加载页面失败');
                completeManageUserProcess(settings);
            });
        }

        // 开始查询
        getUserPages();
    }

    // 处理用户页面删除过程
    function processManageUserDeletion(pages, settings, index, processingRate) {
        const detailsContainer = document.getElementById('manage-user-details');

        if (index >= pages.length) {
            // 所有页面处理完毕
            updateStepStatus('step-delete', 'completed', `已删除 ${pages.length} 个页面`);
            detailsContainer.innerHTML += `<div style="color: #3c763d;">✓ 已完成所有页面的删除</div>`;
            completeManageUserProcess(settings);
            return;
        }

        const page = pages[index].title;
        const progressElement = document.getElementById('progress');

        // 更新进度
        // 将进度范围设为33%-100%(前33%由回退步骤占据)
        const progressPercentage = 33 + Math.round((index / pages.length) * 67);
        progressElement.style.width = progressPercentage + '%';

        // 更新步骤状态
        updateStepStatus('step-delete', 'active', `正在删除 ${index + 1}/${pages.length}`);

        // 准备保护参数
        let protectionParams = null;
        if (settings.deletion.protect) {
            protectionParams = {
                level: settings.deletion.protection.level,
                expiry: convertExpiryToTimestamp(settings.deletion.protection.expiry),
                reason: settings.deletion.protection.reason
            };
        }

        // 执行删除API调用
        const api = new mw.Api();
        api.postWithToken('csrf', {
            action: 'delete',
            title: page,
            reason: settings.deletion.reason,
            format: 'json'
        }).done(function() {
            // 删除成功
            detailsContainer.innerHTML += `<div style="color: #3c763d;">✓ 成功删除: ${page}</div>`;

            // 如果需要保护页面
            if (protectionParams) {
                protectDeletedPage(page, protectionParams, {
                    onSuccess: function() {
                        detailsContainer.innerHTML += `<div style="color: #3a87ad;">🔒 成功保护: ${page}</div>`;
                    },
                    onFail: function(message) {
                        detailsContainer.innerHTML += `<div style="color: #8a6d3b;">⚠ 保护失败: ${page} - ${message}</div>`;
                    }
                });
            }

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processManageUserDeletion(pages, settings, index + 1, processingRate);
            }, processingRate);
        }).fail(function(code, result) {
            // 删除失败
            detailsContainer.innerHTML += `<div style="color: #a94442;">✗ 删除失败: ${page} - ${result.error ? result.error.info : code}</div>`;

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processManageUserDeletion(pages, settings, index + 1, processingRate);
            }, processingRate);
        });
    }

    // 完成用户处理流程
    function completeManageUserProcess(settings) {
        const progressElement = document.getElementById('progress');
        const progressTextElement = document.getElementById('progress-text');
        const detailsContainer = document.getElementById('manage-user-details');

        // 设置进度为100%
        progressElement.style.width = '100%';
        progressTextElement.textContent = `用户 ${settings.username} 处理完成!`;

        // 添加总结信息
        detailsContainer.innerHTML += `
            <div style="margin-top: 20px; padding: 10px; background-color: #dff0d8; border: 1px solid #d6e9c6; border-radius: 4px; color: #3c763d;">
                <strong>用户 ${settings.username} 处理完成!</strong><br>
                所有操作已执行结束。
            </div>
        `;

        // 提示消息
        showMessage(`用户 ${settings.username} 处理完成!`, 'success');
    }

    // 更新步骤状态
    function updateStepStatus(stepId, status, statusText) {
        const stepElement = document.getElementById(stepId);

        // 移除所有状态类
        stepElement.classList.remove('active', 'completed', 'error');

        // 添加当前状态类
        stepElement.classList.add(status);

        // 更新状态文本
        stepElement.querySelector('.progress-status').textContent = statusText;
    }

    // 显示用户页面模态框
    function showUserPagesModal() {
        const content = `
            <div style="margin-bottom: 15px;">
                <label for="username">用户名:</label>
                <input type="text" id="username" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;" placeholder="输入用户名(不含User:前缀)">
            </div>

            <div style="margin-bottom: 15px;">
                <label for="date-limit">时间限制(可选):</label>
                <input type="date" id="date-limit" style="padding: 8px; margin-top: 5px; border: 1px solid #ddd;">
                <small style="display: block; margin-top: 5px; color: #666;">只加载此日期之后创建的页面。留空表示加载所有页面。</small>
            </div>

            <!-- 修改:封禁用户选项 - 删除阻止用户发送邮件选项 -->
            <div style="margin-top: 15px; margin-bottom: 15px;">
                <div>
                    <input type="checkbox" id="ban-user-checkbox" style="margin-right: 5px;">
                    <label for="ban-user-checkbox" style="font-weight: bold; color: #d9534f;">在获取页面前封禁该用户</label>
                </div>

                <div id="ban-options" class="ban-options disabled" style="margin-top: 10px;">
                    <div style="margin-bottom: 10px;">
                        <label for="ban-reason">封禁原因:</label>
                        <input type="text" id="ban-reason" value="破坏行为" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                    </div>

                    <div style="margin-bottom: 10px;">
                        <label for="ban-duration">封禁期限:</label>
                        <select id="ban-duration" style="padding: 5px;">
                            <option value="1 day">1天</option>
                            <option value="3 days">3天</option>
                            <option value="1 week">1周</option>
                            <option value="2 weeks">2周</option>
                            <option value="1 month">1个月</option>
                            <option value="3 months">3个月</option>
                            <option value="6 months">6个月</option>
                            <option value="1 year">1年</option>
                            <option value="infinite">永久</option>
                        </select>
                    </div>

                    <div>
                        <input type="checkbox" id="ban-autoblock" checked style="margin-right: 5px;">
                        <label for="ban-autoblock">自动封禁最后使用的IP地址</label>
                    </div>

                    <div>
                        <input type="checkbox" id="ban-talk-page" style="margin-right: 5px;">
                        <label for="ban-talk-page">阻止用户编辑自己的讨论页</label>
                    </div>
                </div>
            </div>

            ${createCollapsibleSection('命名空间选项', `
                <div style="margin-top: 5px;">
                    <input type="checkbox" id="namespace-main" checked>
                    <label for="namespace-main">主命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="namespace-user">
                    <label for="namespace-user">用户命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="namespace-template">
                    <label for="namespace-template">模板命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="namespace-category">
                    <label for="namespace-category">分类命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="namespace-file">
                    <label for="namespace-file">文件命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="namespace-other">
                    <label for="namespace-other">其他命名空间</label>
                </div>
            `, true)}

            <button id="load-user-pages-button-modal" style="padding: 8px 15px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer; margin-top: 15px;">加载用户创建的页面</button>

            <div id="user-pages-results" style="margin-top: 15px;"></div>
        `;

        showModal('加载用户创建的页面', content);

        // 监听封禁选项复选框
        document.getElementById('ban-user-checkbox').addEventListener('change', function() {
            const banOptions = document.getElementById('ban-options');
            if (this.checked) {
                banOptions.classList.remove('disabled');
            } else {
                banOptions.classList.add('disabled');
            }
        });

        document.getElementById('load-user-pages-button-modal').addEventListener('click', function() {
            const username = document.getElementById('username').value.trim();
            if (!username) {
                showMessage('请输入有效的用户名', 'error');
                return;
            }

            const dateLimit = document.getElementById('date-limit').value;

            // 获取选中的命名空间
            const namespaces = [];
            if (document.getElementById('namespace-main').checked) namespaces.push(0);
            if (document.getElementById('namespace-user').checked) namespaces.push(2, 3);
            if (document.getElementById('namespace-template').checked) namespaces.push(10, 11);
            if (document.getElementById('namespace-category').checked) namespaces.push(14, 15);
            if (document.getElementById('namespace-file').checked) namespaces.push(6, 7);
            if (document.getElementById('namespace-other').checked) namespaces.push(4, 5, 8, 9, 12, 13);

            // 检查是否需要封禁用户
            const shouldBanUser = document.getElementById('ban-user-checkbox').checked;

            if (shouldBanUser) {
                // 获取封禁参数
                const banReason = document.getElementById('ban-reason').value;
                const banDuration = document.getElementById('ban-duration').value;
                const autoBlock = document.getElementById('ban-autoblock').checked;
                const disallowTalkPage = document.getElementById('ban-talk-page').checked;

                // 显示封禁状态
                document.getElementById('user-pages-results').innerHTML = '<p>正在封禁用户 ' + username + ',请稍候...</p>';

                // 执行封禁
                banUser(username, banReason, banDuration, autoBlock, disallowTalkPage, function(success, message) {
                    if (success) {
                        document.getElementById('user-pages-results').innerHTML = '<div style="color: #3c763d; margin-bottom: 15px;"><strong>✓ 用户 ' + username + ' 已成功封禁</strong></div>';
                        // 封禁成功后加载页面
                        loadUserCreatedPages(username, dateLimit, namespaces);
                    } else {
                        document.getElementById('user-pages-results').innerHTML = '<div style="color: #a94442; margin-bottom: 15px;"><strong>✗ 封禁用户 ' + username + ' 失败: ' + message + '</strong></div>';
                    }
                });
            } else {
                // 直接加载页面
                document.getElementById('user-pages-results').innerHTML = '<p>正在加载用户创建的页面,请稍候...</p>';
                loadUserCreatedPages(username, dateLimit, namespaces);
            }
        });
    }

    // 显示回退用户编辑模态框
    function showRollbackModal() {
        const content = `
            <div style="margin-bottom: 15px;">
                <label for="rollback-username">用户名:</label>
                <input type="text" id="rollback-username" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;" placeholder="输入要回退编辑的用户名(不含User:前缀)">
            </div>

            <div style="margin-bottom: 15px;">
                <label for="rollback-date-limit">时间限制(可选):</label>
                <input type="date" id="rollback-date-limit" style="padding: 8px; margin-top: 5px; border: 1px solid #ddd;">
                <small style="display: block; margin-top: 5px; color: #666;">只加载此日期之后的编辑。留空表示加载所有编辑。</small>
            </div>

            <div class="rollback-options" style="margin-top: 15px; margin-bottom: 15px;">
                <div style="margin-bottom: 10px;">
                    <label for="rollback-reason">回退原因:</label>
                    <input type="text" id="rollback-reason" value="回退破坏性编辑" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                </div>

                <div style="margin-bottom: 10px;">
                    <label for="rollback-limit">最大处理数量:</label>
                    <input type="number" id="rollback-limit" value="100" min="1" max="500" style="width: 100px; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
                    <small style="display: block; margin-top: 5px; color: #666;">建议不超过200,以避免API限制</small>
                </div>
            </div>

            ${createCollapsibleSection('命名空间选项', `
                <div style="margin-top: 5px;">
                    <input type="checkbox" id="rollback-namespace-main" checked>
                    <label for="rollback-namespace-main">主命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="rollback-namespace-user">
                    <label for="rollback-namespace-user">用户命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="rollback-namespace-template">
                    <label for="rollback-namespace-template">模板命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="rollback-namespace-category">
                    <label for="rollback-namespace-category">分类命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="rollback-namespace-file">
                    <label for="rollback-namespace-file">文件命名空间</label>
                </div>
                <div>
                    <input type="checkbox" id="rollback-namespace-other">
                    <label for="rollback-namespace-other">其他命名空间</label>
                </div>
            `, true)}

            <button id="load-user-edits-button" style="padding: 8px 15px; background-color: #5bc0de; color: white; border: none; border-radius: 3px; cursor: pointer; margin-top: 15px;">加载用户编辑</button>

            <div id="rollback-results" style="margin-top: 15px;"></div>
        `;

        showModal('回退用户编辑', content);

        document.getElementById('load-user-edits-button').addEventListener('click', function() {
            const username = document.getElementById('rollback-username').value.trim();
            if (!username) {
                showMessage('请输入有效的用户名', 'error');
                return;
            }

            const dateLimit = document.getElementById('rollback-date-limit').value;
            const limit = parseInt(document.getElementById('rollback-limit').value) || 100;

            // 获取选中的命名空间
            const namespaces = [];
            if (document.getElementById('rollback-namespace-main').checked) namespaces.push(0);
            if (document.getElementById('rollback-namespace-user').checked) namespaces.push(2, 3);
            if (document.getElementById('rollback-namespace-template').checked) namespaces.push(10, 11);
            if (document.getElementById('rollback-namespace-category').checked) namespaces.push(14, 15);
            if (document.getElementById('rollback-namespace-file').checked) namespaces.push(6, 7);
            if (document.getElementById('rollback-namespace-other').checked) namespaces.push(4, 5, 8, 9, 12, 13);

            document.getElementById('rollback-results').innerHTML = '<p>正在加载用户编辑,请稍候...</p>';
            loadUserEdits(username, dateLimit, namespaces, limit);
        });
    }

    // 加载用户编辑
    function loadUserEdits(username, dateLimit, namespaces, limit) {
        const api = new mw.Api();
        const resultContainer = document.getElementById('rollback-results');

        // 构建参数
        let params = {
            action: 'query',
            list: 'usercontribs',
            ucuser: username,
            uclimit: Math.min(limit, 500), // API限制通常为500
            ucprop: 'title|timestamp|comment|ids',
            format: 'json'
        };

        // 添加日期限制
        if (dateLimit) {
            params.ucend = dateLimit + 'T00:00:00Z'; // 转换为ISO格式
        }

        // 添加命名空间限制
        if (namespaces && namespaces.length > 0) {
            params.ucnamespace = namespaces.join('|');
        }

        // 显示加载状态
        resultContainer.innerHTML = '<p>正在查询用户编辑,这可能需要一些时间...</p>';

        // 保存找到的编辑
        const userEdits = [];

        // 获取用户编辑记录
        api.get(params).done(function(data) {
            if (data.query && data.query.usercontribs) {
                data.query.usercontribs.forEach(function(contrib) {
                    userEdits.push({
                        title: contrib.title,
                        revid: contrib.revid,
                        timestamp: contrib.timestamp,
                        comment: contrib.comment
                    });
                });

                // 显示结果
                displayUserEditsResults(username, userEdits);
            } else {
                // 没有找到贡献或出现错误
                resultContainer.innerHTML = `<p>未找到用户 "${username}" 的编辑。</p>`;
            }
        }).fail(function(code, result) {
            resultContainer.innerHTML = `<p>查询用户贡献失败: ${result.error ? result.error.info : code}</p>`;
        });
    }

    // 显示用户编辑结果
    function displayUserEditsResults(username, edits) {
        const resultContainer = document.getElementById('rollback-results');

        if (edits.length === 0) {
            resultContainer.innerHTML = `<p>未找到用户 "${username}" 的编辑。</p>`;
            return;
        }

        // 创建折叠区域的内容
        let editsContent = `
            <div style="margin-bottom: 10px;">
                <input type="checkbox" id="select-all-edits" checked>
                <label for="select-all-edits">全选/取消全选</label>
            </div>

            <div class="page-list-container">
        `;

        edits.forEach((edit, index) => {
            // 格式化时间戳为可读格式
            const date = new Date(edit.timestamp);
            const formattedDate = date.toLocaleString();

            // 处理可能为空的编辑摘要
            const summary = edit.comment ? `(${edit.comment})` : '(无编辑摘要)';

            editsContent += `
                <div class="edit-item">
                    <div class="edit-info">
                        <input type="checkbox" id="edit-${index}" class="edit-checkbox"
                               data-title="${edit.title}" data-revid="${edit.revid}" checked>
                        <label for="edit-${index}">${edit.title}</label>
                        <small style="margin-left: 5px; color: #666;">${formattedDate} ${summary}</small>
                    </div>
                </div>
            `;
        });

        editsContent += `</div>`;

        // 创建固定底部的操作按钮
        const actionButtons = `
            <div class="action-buttons">
                <button id="rollback-selected-button" style="padding: 6px 12px; background-color: #d9534f; color: white; border: none; border-radius: 3px; cursor: pointer;">回退选中编辑</button>
            </div>
        `;

        // 组合内容
        const html = `
            <h4>找到 ${edits.length} 个由 "${username}" 进行的编辑:</h4>
            ${createCollapsibleSection('编辑列表', editsContent)}
            ${actionButtons}
        `;

        resultContainer.innerHTML = html;

        // 添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();

        // 添加全选/取消全选功能
        document.getElementById('select-all-edits').addEventListener('change', function() {
            const checkboxes = document.querySelectorAll('#rollback-results .edit-checkbox');
            checkboxes.forEach(cb => {
                cb.checked = this.checked;
            });
        });

        // 添加回退功能
        document.getElementById('rollback-selected-button').addEventListener('click', function() {
            const selectedEdits = [];
            document.querySelectorAll('#rollback-results .edit-checkbox:checked').forEach(cb => {
                selectedEdits.push({
                    title: cb.dataset.title,
                    revid: cb.dataset.revid
                });
            });

            if (selectedEdits.length === 0) {
                showMessage('请至少选择一个编辑', 'error');
                return;
            }

            // 获取回退原因
            const reason = document.getElementById('rollback-reason').value;

            // 确认对话框
            if (confirm(`您即将回退 ${selectedEdits.length} 个编辑。是否继续?`)) {
                // 关闭模态框
                closeModal();

                // 显示进度条
                document.getElementById('deletion-status').style.display = 'block';
                document.getElementById('progress').style.width = '0%';
                document.getElementById('progress-text').textContent = '准备回退编辑...';

                // 清空结果区
                const resultsElement = document.getElementById('deletion-results');
                resultsElement.innerHTML = '';

                // 开始回退
                const processingRate = parseFloat(document.getElementById('processing-rate').value) * 1000; // 转换为毫秒
                processRollback(selectedEdits, username, 0, reason, processingRate);
            }
        });
    }

    // 处理回退流程
    function processRollback(edits, username, index, reason, processingRate) {
        if (index >= edits.length) {
            // 所有编辑处理完毕
            document.getElementById('progress-text').textContent = '完成! 回退操作已结束。';
            return;
        }

        const edit = edits[index];
        const progressElement = document.getElementById('progress');
        const progressTextElement = document.getElementById('progress-text');
        const resultsElement = document.getElementById('deletion-results');

        // 更新进度
        const progressPercentage = Math.round((index / edits.length) * 100);
        progressElement.style.width = progressPercentage + '%';
        progressTextElement.textContent = `正在回退: ${edit.title} (${index + 1}/${edits.length}, ${progressPercentage}%)`;

        // 执行回退API调用
        rollbackEdit(edit.title, username, reason, function(success, message) {
            // 添加结果到列表
            const resultItem = document.createElement('div');
            if (success) {
                resultItem.style.color = '#3c763d';
                resultItem.textContent = `✓ 成功回退: ${edit.title}`;
            } else {
                resultItem.style.color = '#a94442';
                resultItem.textContent = `✗ 回退失败: ${edit.title} - ${message}`;
            }
            resultsElement.appendChild(resultItem);

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processRollback(edits, username, index + 1, reason, processingRate);
            }, processingRate);
        });
    }

    // 回退编辑实现
    function rollbackEdit(title, user, reason, callback) {
        const api = new mw.Api();

        // 使用postWithToken方法,但使用'rollback'令牌类型
        api.postWithToken('rollback', {
            action: 'rollback',
            title: title,
            user: user,
            summary: reason,
            format: 'json'
        }).done(function(data) {
            if (data.rollback) {
                callback(true, '回退成功');
            } else {
                callback(false, '回退操作没有返回预期结果');
            }
        }).fail(function(code, result) {
            callback(false, result.error ? result.error.info : code);
        });
    }

    // 封禁用户功能
    function banUser(username, reason, duration, autoBlock, disallowTalkPage, callback) {
        const api = new mw.Api();

        // 转换封禁期限为MediaWiki API接受的格式
        const expiry = convertBanDurationToTimestamp(duration);

        // 执行封禁API调用
        api.postWithToken('csrf', {
            action: 'block',
            user: username,
            reason: reason,
            expiry: expiry,
            format: 'json',
            allowusertalk: disallowTalkPage ? undefined : true, // 阻止用户编辑自己的讨论页
            autoblock: autoBlock ? true : undefined // 自动封禁最后使用的IP地址
        })
        .done(function(data) {
            if (data.block) {
                callback(true, '封禁成功');
            } else {
                callback(false, '封禁操作没有返回预期结果');
            }
        }).fail(function(code, result) {
            callback(false, result.error ? result.error.info : code);
        });
    }

    // 转换封禁期限为时间戳格式
    function convertBanDurationToTimestamp(duration) {
        // 如果是永久封禁,直接返回
        if (duration === 'infinite') {
            return 'infinite';
        }

        // 获取当前日期
        const now = new Date();

        // 根据选择的选项计算到期日期
        switch (duration) {
            case '1 day':
                now.setDate(now.getDate() + 1);
                break;
            case '3 days':
                now.setDate(now.getDate() + 3);
                break;
            case '1 week':
                now.setDate(now.getDate() + 7);
                break;
            case '2 weeks':
                now.setDate(now.getDate() + 14);
                break;
            case '1 month':
                now.setMonth(now.getMonth() + 1);
                break;
            case '3 months':
                now.setMonth(now.getMonth() + 3);
                break;
            case '6 months':
                now.setMonth(now.getMonth() + 6);
                break;
            case '1 year':
                now.setFullYear(now.getFullYear() + 1);
                break;
            default:
                // 如果无法识别选项,默认为一天
                now.setDate(now.getDate() + 1);
        }

        // 将日期格式化为MediaWiki API接受的格式:YYYY-MM-DDThh:mm:ssZ
        return now.toISOString().replace(/\.\d+Z$/, 'Z');
    }

    // 加载用户创建的页面
    function loadUserCreatedPages(username, dateLimit, namespaces) {
        const api = new mw.Api();
        const resultContainer = document.getElementById('user-pages-results');

        // 构建参数
        let params = {
            action: 'query',
            list: 'usercontribs',
            ucuser: username,
            uclimit: 500,
            ucprop: 'title|timestamp',
            ucshow: 'new', // 只显示创建新页面的贡献
            format: 'json'
        };

        // 添加日期限制
        if (dateLimit) {
            params.ucend = dateLimit + 'T00:00:00Z'; // 转换为ISO格式
        }

        // 添加命名空间限制
        if (namespaces && namespaces.length > 0) {
            params.ucnamespace = namespaces.join('|');
        }

        // 显示加载状态
        resultContainer.innerHTML = '<p>正在查询用户创建的页面,这可能需要一些时间...</p>';

        // 保存找到的页面
        const userPages = [];

        // 递归函数获取所有页面
        function getUserContributions(continueParam) {
            if (continueParam) {
                // 添加continue参数
                for (let prop in continueParam) {
                    params[prop] = continueParam[prop];
                }
            }

            api.get(params).done(function(data) {
                if (data.query && data.query.usercontribs) {
                    data.query.usercontribs.forEach(function(contrib) {
                        userPages.push({
                            title: contrib.title,
                            timestamp: contrib.timestamp
                        });
                    });

                    // 更新状态信息
                    resultContainer.innerHTML = `<p>已找到 ${userPages.length} 个由 ${username} 创建的页面,正在继续搜索...</p>`;

                    // 如果有更多结果,继续查询
                    if (data.continue) {
                        getUserContributions(data.continue);
                    } else {
                        // 完成所有查询
                        displayUserPagesResults(username, userPages);
                    }
                } else {
                    // 没有找到贡献或出现错误
                    if (userPages.length === 0) {
                        resultContainer.innerHTML = `<p>未找到用户 "${username}" 创建的页面。</p>`;
                    } else {
                        displayUserPagesResults(username, userPages);
                    }
                }
            }).fail(function(code, result) {
                resultContainer.innerHTML = `<p>查询用户贡献失败: ${result.error ? result.error.info : code}</p>`;
            });
        }

        // 开始查询
        getUserContributions();
    }

    // 显示用户创建的页面结果
    function displayUserPagesResults(username, pages) {
        const resultContainer = document.getElementById('user-pages-results');

        if (pages.length === 0) {
            resultContainer.innerHTML = `<p>未找到用户 "${username}" 创建的页面。</p>`;
            return;
        }

        // 按时间倒序排序(最新的在前)
        pages.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));

        // 创建折叠区域的内容
        let pagesContent = `
            <div style="margin-bottom: 10px;">
                <input type="checkbox" id="select-all-user-pages" checked>
                <label for="select-all-user-pages">全选/取消全选</label>
            </div>

            <div class="page-list-container">
        `;

        pages.forEach((page, index) => {
            // 格式化时间戳为可读格式
            const date = new Date(page.timestamp);
            const formattedDate = date.toLocaleString();

            pagesContent += `
                <div style="margin: 5px 0;">
                    <input type="checkbox" id="user-page-${index}" class="page-checkbox" value="${page.title}" checked>
                    <label for="user-page-${index}">${page.title}</label>
                    <small style="margin-left: 5px; color: #666;">(创建于 ${formattedDate})</small>
                </div>
            `;
        });

        pagesContent += `</div>`;

        // 创建固定底部的操作按钮
        const actionButtons = `
            <div class="action-buttons">
                <button id="add-user-pages-button" style="padding: 6px 12px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">将选中页面添加到删除列表</button>
            </div>
        `;

        // 组合内容
        const html = `
            <h4>找到 ${pages.length} 个由 "${username}" 创建的页面:</h4>
            ${createCollapsibleSection('页面列表', pagesContent)}
            ${actionButtons}
        `;

        resultContainer.innerHTML = html;

        // 修复:添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();

        // 添加全选/取消全选功能
        document.getElementById('select-all-user-pages').addEventListener('change', function() {
            const checkboxes = document.querySelectorAll('#user-pages-results .page-checkbox');
            checkboxes.forEach(cb => {
                cb.checked = this.checked;
            });
        });

        // 添加添加到列表功能
        document.getElementById('add-user-pages-button').addEventListener('click', function() {
            const selectedPages = [];
            document.querySelectorAll('#user-pages-results .page-checkbox:checked').forEach(cb => {
                selectedPages.push(cb.value);
            });

            if (selectedPages.length === 0) {
                showMessage('请至少选择一个页面', 'error');
                return;
            }

            const textarea = document.getElementById('pages-to-delete');
            const existingText = textarea.value.trim();
            const newText = selectedPages.join('\n');
            textarea.value = existingText ? existingText + '\n' + newText : newText;

            // 更新删除原因以包含用户名
            const reasonInput = document.getElementById('delete-reason');
            if (reasonInput.value === '批量清理') {
                reasonInput.value = `清理用户 ${username} 创建的页面`;
            }

            closeModal();
            showMessage(`已添加 ${selectedPages.length} 个页面到删除列表`, 'success');
        });
    }

    // 显示正则匹配模态框
    function showRegexModal() {
        // 获取命名空间列表
        const namespaces = [
            {id: '0', name: '(主命名空间)'},
            {id: '1', name: 'Talk'},
            {id: '2', name: 'User'},
            {id: '3', name: 'User talk'},
            {id: '4', name: 'Project'},
            {id: '6', name: 'File'},
            {id: '10', name: 'Template'},
            {id: '14', name: 'Category'},
            {id: '110', name: 'Forum'},
            {id: '828', name: 'Module'}
        ];

        let namespaceOptions = '';
        namespaces.forEach(ns => {
            namespaceOptions += `<option value="${ns.id}">${ns.name}</option>`;
        });

        const content = `
            <div style="margin-bottom: 15px;">
                <label for="regex-pattern">正则表达式模式:</label>
                <input type="text" id="regex-pattern" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;" placeholder="例如: ^User:.+/沙盒$">
                <small style="display: block; margin-top: 5px; color: #666;">提示:使用JavaScript正则表达式语法,例如 ^Template:Test.* 将匹配所有以"Template:Test"开头的页面。</small>
            </div>

            ${createCollapsibleSection('高级选项', `
                <div style="margin-bottom: 15px;">
                    <label for="regex-namespace">在此命名空间中搜索:</label>
                    <select id="regex-namespace" style="padding: 8px; margin-left: 5px;">
                        <option value="all">所有命名空间</option>
                        ${namespaceOptions}
                    </select>
                </div>

                <div style="margin-bottom: 15px;">
                    <label for="regex-flags">正则表达式标志:</label>
                    <input type="text" id="regex-flags" style="width: 100px; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;" value="i" placeholder="例如: i">
                    <small style="display: block; margin-top: 5px; color: #666;">i = 忽略大小写, g = 全局匹配, m = 多行匹配</small>
                </div>

                <div style="margin-bottom: 15px;">
                    <input type="checkbox" id="regex-case-sensitive" style="margin-right: 5px;">
                    <label for="regex-case-sensitive">区分大小写</label>
                </div>
            `, true)}

            <button id="load-regex-pages-button" style="padding: 8px 15px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer; margin-top: 15px;">搜索匹配页面</button>

            <div id="regex-results" style="margin-top: 15px;"></div>
        `;

        showModal('使用正则表达式匹配页面', content);

        // 更新flags值的处理
        document.getElementById('regex-case-sensitive').addEventListener('change', function() {
            const flagsInput = document.getElementById('regex-flags');
            if (this.checked) {
                // 移除i标志
                flagsInput.value = flagsInput.value.replace(/i/g, '');
            } else if (!flagsInput.value.includes('i')) {
                // 添加i标志
                flagsInput.value += 'i';
            }
        });

        document.getElementById('load-regex-pages-button').addEventListener('click', function() {
            const pattern = document.getElementById('regex-pattern').value.trim();
            const namespace = document.getElementById('regex-namespace').value;
            const flags = document.getElementById('regex-flags').value.trim();

            if (!pattern) {
                showMessage('请输入有效的正则表达式', 'error');
                return;
            }

            document.getElementById('regex-results').innerHTML = '<p>正在搜索匹配页面,请稍候...</p>';
            searchPagesByRegex(pattern, namespace, flags);
        });
    }

    // 使用正则表达式搜索页面
    function searchPagesByRegex(pattern, namespace, flags) {
        const api = new mw.Api();
        const resultContainer = document.getElementById('regex-results');

        try {
            // 测试正则表达式是否有效
            new RegExp(pattern, flags);
        } catch (e) {
            resultContainer.innerHTML = `<p style="color: #a94442;">正则表达式无效: ${e.message}</p>`;
            return;
        }

        // 构建查询参数
        let params = {
            action: 'query',
            list: 'allpages',
            aplimit: 500,
            format: 'json'
        };

        // 只有在选择了特定命名空间时才添加命名空间参数
        if (namespace !== 'all') {
            params.apnamespace = namespace;
        }

        // 创建正则表达式对象
        const regex = new RegExp(pattern, flags);

        // 显示加载状态
        resultContainer.innerHTML = '<p>正在加载页面,这可能需要一些时间...</p>';

        // 保存匹配的页面
        let matchedPages = [];

        // 执行递归API调用来获取所有页面
        function getAllPages(continueParam) {
            if (continueParam) {
                // 添加continue参数
                for (let prop in continueParam) {
                    params[prop] = continueParam[prop];
                }
            }

            api.get(params).done(function(data) {
                if (data.query && data.query.allpages) {
                    // 过滤匹配正则表达式的页面
                    const pages = data.query.allpages;
                    pages.forEach(function(page) {
                        if (regex.test(page.title)) {
                            matchedPages.push(page.title);
                        }
                    });

                    // 更新状态
                    resultContainer.innerHTML = `<p>已找到 ${matchedPages.length} 个匹配页面,正在继续搜索...</p>`;

                    // 如果有更多页面,继续获取
                    if (data.continue) {
                        getAllPages(data.continue);
                    } else {
                        // 最终完成
                        displayRegexResults(matchedPages, pattern, flags);
                    }
                } else {
                    displayRegexResults(matchedPages, pattern, flags);
                }
            }).fail(function() {
                resultContainer.innerHTML = '<p>获取页面列表失败,请重试。</p>';
            });
        }

        // 开始获取页面
        getAllPages();
    }

    // 显示正则匹配结果
    function displayRegexResults(pages, pattern, flags) {
        const resultContainer = document.getElementById('regex-results');

        if (pages.length === 0) {
            resultContainer.innerHTML = `<p>没有找到匹配正则表达式 "${pattern}" 的页面。</p>`;
            return;
        }

        // 创建折叠区域的内容
        let pagesContent = `
            <div style="margin-bottom: 10px;">
                <input type="checkbox" id="select-all-regex" checked>
                <label for="select-all-regex">全选/取消全选</label>
            </div>

            <div class="page-list-container">
        `;

        pages.forEach((page, index) => {
            pagesContent += `
                <div style="margin: 5px 0;">
                    <input type="checkbox" id="regex-page-${index}" class="page-checkbox" value="${page}" checked>
                    <label for="regex-page-${index}">${page}</label>
                </div>
            `;
        });

        pagesContent += `</div>`;

        // 创建固定底部的操作按钮
        const actionButtons = `
            <div class="action-buttons">
                <button id="add-regex-pages-button" style="padding: 6px 12px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">将选中页面添加到删除列表</button>
            </div>
        `;

        // 组合内容
        const html = `
            <h4>找到 ${pages.length} 个匹配正则表达式 /${pattern}/${flags} 的页面:</h4>
            ${createCollapsibleSection('页面列表', pagesContent)}
            ${actionButtons}
        `;

        resultContainer.innerHTML = html;

        // 修复:添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();

        // 添加全选/取消全选功能
        document.getElementById('select-all-regex').addEventListener('change', function() {
            const checkboxes = document.querySelectorAll('#regex-results .page-checkbox');
            checkboxes.forEach(cb => {
                cb.checked = this.checked;
            });
        });

        // 添加添加到列表功能
        document.getElementById('add-regex-pages-button').addEventListener('click', function() {
            const selectedPages = [];
            document.querySelectorAll('#regex-results .page-checkbox:checked').forEach(cb => {
                selectedPages.push(cb.value);
            });

            if (selectedPages.length === 0) {
                showMessage('请至少选择一个页面', 'error');
                return;
            }

            const textarea = document.getElementById('pages-to-delete');
            const existingText = textarea.value.trim();
            const newText = selectedPages.join('\n');
            textarea.value = existingText ? existingText + '\n' + newText : newText;

            closeModal();
            showMessage(`已添加 ${selectedPages.length} 个页面到删除列表`, 'success');
        });
    }

    // 显示分类模态框
    function showCategoryModal() {
        const content = `
            <div style="margin-bottom: 15px;">
                <label for="category-name">分类名称(不包含Category:前缀):</label>
                <input type="text" id="category-name" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
            </div>

            <div style="margin-bottom: 15px;">
                <label for="category-depth">包含子分类:</label>
                <select id="category-depth" style="padding: 8px; margin-left: 5px;">
                    <option value="0">否</option>
                    <option value="1">是,深度 1</option>
                    <option value="2">是,深度 2</option>
                    <option value="3">是,深度 3</option>
                </select>
            </div>

            <button id="load-category-pages-button" style="padding: 8px 15px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">加载分类页面</button>

            <div id="category-results" style="margin-top: 15px;"></div>
        `;

        showModal('从分类加载页面', content);

        document.getElementById('load-category-pages-button').addEventListener('click', function() {
            const categoryName = document.getElementById('category-name').value.trim();
            const depth = parseInt(document.getElementById('category-depth').value);

            if (!categoryName) {
                showMessage('请输入有效的分类名称', 'error');
                return;
            }

            document.getElementById('category-results').innerHTML = '<p>正在加载分类页面,请稍候...</p>';
            loadPagesFromCategory(categoryName, depth);
        });
    }

    // 显示前缀模态框
    function showPrefixModal() {
        // 获取命名空间列表
        const namespaces = [
            {id: '0', name: '(主命名空间)'},
            {id: '1', name: 'Talk'},
            {id: '2', name: 'User'},
            {id: '3', name: 'User talk'},
            {id: '4', name: 'Project'},
            {id: '6', name: 'File'},
            {id: '10', name: 'Template'},
            {id: '14', name: 'Category'},
            {id: '110', name: 'Forum'},
            {id: '828', name: 'Module'}
        ];

        let namespaceOptions = '';
        namespaces.forEach(ns => {
            namespaceOptions += `<option value="${ns.id}">${ns.name}</option>`;
        });

        const content = `
            <div style="margin-bottom: 15px;">
                <label for="prefix-name">页面标题前缀:</label>
                <input type="text" id="prefix-name" style="width: 100%; padding: 8px; box-sizing: border-box; margin-top: 5px; border: 1px solid #ddd;">
            </div>

            <div style="margin-bottom: 15px;">
                <label for="namespace-select">命名空间:</label>
                <select id="namespace-select" style="padding: 8px; margin-left: 5px;">
                    ${namespaceOptions}
                </select>
            </div>

            <button id="load-prefix-pages-button" style="padding: 8px 15px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">加载前缀页面</button>

            <div id="prefix-results" style="margin-top: 15px;"></div>
        `;

        showModal('从前缀加载页面', content);

        document.getElementById('load-prefix-pages-button').addEventListener('click', function() {
            const prefix = document.getElementById('prefix-name').value.trim();
            const namespace = document.getElementById('namespace-select').value;

            if (!prefix) {
                showMessage('请输入有效的页面前缀', 'error');
                return;
            }

            document.getElementById('prefix-results').innerHTML = '<p>正在加载前缀页面,请稍候...</p>';
            loadPagesFromPrefix(prefix, namespace);
        });
    }

    // 从分类加载页面
    function loadPagesFromCategory(categoryName, depth) {
        const api = new mw.Api();

        api.get({
            action: 'query',
            list: 'categorymembers',
            cmtitle: 'Category:' + categoryName,
            cmlimit: 500,
            cmnamespace: '*',
            cmtype: 'page|subcat',
            format: 'json'
        }).done(function(data) {
            const pages = [];
            const subcats = [];

            if (data.query && data.query.categorymembers) {
                data.query.categorymembers.forEach(function(member) {
                    if (member.ns === 14) {
                        // 这是子分类
                        subcats.push(member.title.replace('Category:', ''));
                    } else {
                        // 这是页面
                        pages.push(member.title);
                    }
                });

                // 显示结果
                displayCategoryResults(categoryName, pages);

                // 如果需要处理子分类并且深度大于0
                if (depth > 0 && subcats.length > 0) {
                    loadSubcategories(subcats, pages, depth - 1);
                }
            } else {
                document.getElementById('category-results').innerHTML = '<p>在分类 "' + categoryName + '" 中未找到页面。</p>';
            }
        }).fail(function() {
            document.getElementById('category-results').innerHTML = '<p>无法加载分类页面。请检查分类名称后重试。</p>';
        });
    }

    // 递归加载子分类
    function loadSubcategories(subcats, allPages, remainingDepth) {
        if (subcats.length === 0 || remainingDepth < 0) return;

        const currentCat = subcats.shift();
        const api = new mw.Api();

        api.get({
            action: 'query',
            list: 'categorymembers',
            cmtitle: 'Category:' + currentCat,
            cmlimit: 500,
            cmnamespace: '*',
            cmtype: 'page|subcat',
            format: 'json'
        }).done(function(data) {
            const newSubcats = [];

            if (data.query && data.query.categorymembers) {
                data.query.categorymembers.forEach(function(member) {
                    if (member.ns === 14) {
                        // 这是子分类
                        newSubcats.push(member.title.replace('Category:', ''));
                    } else {
                        // 这是页面
                        allPages.push(member.title);
                    }
                });

                // 更新显示
                displayCategoryResults('所有分类', allPages);

                // 处理任何新发现的子分类
                if (remainingDepth > 0) {
                    subcats.push(...newSubcats);
                }

                // 继续处理队列中的下一个子分类
                if (subcats.length > 0) {
                    loadSubcategories(subcats, allPages, remainingDepth);
                }
            }
        });
    }

    // 显示分类结果
    function displayCategoryResults(categoryName, pages) {
        const resultContainer = document.getElementById('category-results');

        if (pages.length === 0) {
            resultContainer.innerHTML = '<p>在分类 "' + categoryName + '" 中未找到页面。</p>';
            return;
        }

        // 创建折叠区域的内容
        let pagesContent = `
            <div style="margin-bottom: 10px;">
                <input type="checkbox" id="select-all-category" checked>
                <label for="select-all-category">全选/取消全选</label>
            </div>

            <div class="page-list-container">
        `;

        pages.forEach((page, index) => {
            pagesContent += `
                <div style="margin: 5px 0;">
                    <input type="checkbox" id="cat-page-${index}" class="page-checkbox" value="${page}" checked>
                    <label for="cat-page-${index}">${page}</label>
                </div>
            `;
        });

        pagesContent += `</div>`;

        // 创建固定底部的操作按钮
        const actionButtons = `
            <div class="action-buttons">
                <button id="add-category-pages-button" style="padding: 6px 12px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">将选中页面添加到删除列表</button>
            </div>
        `;

        // 组合内容
        const html = `
            <h4>在分类 "${categoryName}" 中找到 ${pages.length} 个页面:</h4>
            ${createCollapsibleSection('页面列表', pagesContent)}
            ${actionButtons}
        `;

        resultContainer.innerHTML = html;

        // 修复:添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();

        // 添加全选/取消全选功能
        document.getElementById('select-all-category').addEventListener('change', function() {
            const checkboxes = document.querySelectorAll('#category-results .page-checkbox');
            checkboxes.forEach(cb => {
                cb.checked = this.checked;
            });
        });

        // 添加添加到列表功能
        document.getElementById('add-category-pages-button').addEventListener('click', function() {
            const selectedPages = [];
            document.querySelectorAll('#category-results .page-checkbox:checked').forEach(cb => {
                selectedPages.push(cb.value);
            });

            if (selectedPages.length === 0) {
                showMessage('请至少选择一个页面', 'error');
                return;
            }

            const textarea = document.getElementById('pages-to-delete');
            const existingText = textarea.value.trim();
            const newText = selectedPages.join('\n');
            textarea.value = existingText ? existingText + '\n' + newText : newText;

            closeModal();
            showMessage(`已添加 ${selectedPages.length} 个页面到删除列表`, 'success');
        });
    }

    // 从前缀加载页面
    function loadPagesFromPrefix(prefix, namespace) {
        const api = new mw.Api();

        api.get({
            action: 'query',
            list: 'allpages',
            apprefix: prefix,
            apnamespace: namespace,
            aplimit: 500,
            format: 'json'
        }).done(function(data) {
            const pages = [];

            if (data.query && data.query.allpages) {
                data.query.allpages.forEach(function(page) {
                    pages.push(page.title);
                });

                // 显示结果
                displayPrefixResults(prefix, namespace, pages);
            } else {
                document.getElementById('prefix-results').innerHTML = '<p>使用前缀 "' + prefix + '" 未找到页面。</p>';
            }
        }).fail(function() {
            document.getElementById('prefix-results').innerHTML = '<p>无法加载前缀页面。请检查前缀后重试。</p>';
        });
    }

    // 显示前缀结果
    function displayPrefixResults(prefix, namespace, pages) {
        const resultContainer = document.getElementById('prefix-results');

        if (pages.length === 0) {
            resultContainer.innerHTML = '<p>使用前缀 "' + prefix + '" 未找到页面。</p>';
            return;
        }

        const namespaceText = document.querySelector('#namespace-select option[value="' + namespace + '"]')?.textContent || namespace;

        // 创建折叠区域的内容
        let pagesContent = `
            <div style="margin-bottom: 10px;">
                <input type="checkbox" id="select-all-prefix" checked>
                <label for="select-all-prefix">全选/取消全选</label>
            </div>

            <div class="page-list-container">
        `;

        pages.forEach((page, index) => {
            pagesContent += `
                <div style="margin: 5px 0;">
                    <input type="checkbox" id="prefix-page-${index}" class="page-checkbox" value="${page}" checked>
                    <label for="prefix-page-${index}">${page}</label>
                </div>
            `;
        });

        pagesContent += `</div>`;

        // 创建固定底部的操作按钮
        const actionButtons = `
            <div class="action-buttons">
                <button id="add-prefix-pages-button" style="padding: 6px 12px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer;">将选中页面添加到删除列表</button>
            </div>
        `;

        // 组合内容
        const html = `
            <h4>在命名空间 "${namespaceText}" 中找到 ${pages.length} 个以 "${prefix}" 开头的页面:</h4>
            ${createCollapsibleSection('页面列表', pagesContent)}
            ${actionButtons}
        `;

        resultContainer.innerHTML = html;

        // 修复:添加折叠区域的事件监听器
        addCollapsibleSectionsEventListeners();

        // 添加全选/取消全选功能
        document.getElementById('select-all-prefix').addEventListener('change', function() {
            const checkboxes = document.querySelectorAll('#prefix-results .page-checkbox');
            checkboxes.forEach(cb => {
                cb.checked = this.checked;
            });
        });

        // 添加添加到列表功能
        document.getElementById('add-prefix-pages-button').addEventListener('click', function() {
            const selectedPages = [];
            document.querySelectorAll('#prefix-results .page-checkbox:checked').forEach(cb => {
                selectedPages.push(cb.value);
            });

            if (selectedPages.length === 0) {
                showMessage('请至少选择一个页面', 'error');
                return;
            }

            const textarea = document.getElementById('pages-to-delete');
            const existingText = textarea.value.trim();
            const newText = selectedPages.join('\n');
            textarea.value = existingText ? existingText + '\n' + newText : newText;

            closeModal();
            showMessage(`已添加 ${selectedPages.length} 个页面到删除列表`, 'success');
        });
    }

    // 预览页面
    function previewPages() {
        const pagesText = document.getElementById('pages-to-delete').value.trim();
        if (!pagesText) {
            showMessage('请先添加要删除的页面', 'error');
            return;
        }

        // 将文本分割成页面数组
        const pagesToDelete = pagesText.split('\n')
            .map(page => page.trim())
            .filter(page => page.length > 0);

        if (pagesToDelete.length === 0) {
            showMessage('没有找到有效的页面标题', 'error');
            return;
        }

        const protectEnabled = document.getElementById('protect-after-delete').checked;
        const processingRate = document.getElementById('processing-rate').value;
        let protectionInfo = '';

        if (protectEnabled) {
            const protectionLevel = document.getElementById('protection-level').value;
            const protectionExpiry = document.getElementById('protection-expiry').value;
            const protectionReason = document.getElementById('protection-reason').value;

            // 转换保护期限为人类可读形式
            let readableExpiry = protectionExpiry;
            if (protectionExpiry === 'infinite') {
                readableExpiry = '永久';
            }

            protectionInfo = `
                <div style="margin-top: 10px; padding: 8px; background-color: #d9edf7; border: 1px solid #bce8f1; border-radius: 4px;">
                    <strong>删除后将保护这些页面:</strong><br>
                    保护级别: ${protectionLevel === 'sysop' ? '仅管理员' : '仅自动确认用户'}<br>
                    保护期限: ${readableExpiry}<br>
                    保护原因: ${protectionReason}
                </div>
            `;
        }

        // 计算预计完成时间
        const totalSeconds = pagesToDelete.length * parseFloat(processingRate);
        const minutes = Math.floor(totalSeconds / 60);
        const seconds = Math.round(totalSeconds % 60);
        const estimatedTime = minutes > 0 ?
            `${minutes}分${seconds}秒` :
            `${seconds}秒`;

        // 显示预览
        const content = `
            <div>
                <strong>总页面数:</strong> ${pagesToDelete.length}<br>
                <strong>删除原因:</strong> ${document.getElementById('delete-reason').value}<br>
                <strong>处理速率:</strong> ${processingRate} 秒/页面<br>
                <strong>预计完成时间:</strong> 约 ${estimatedTime}
            </div>

            ${protectionInfo}

            ${createCollapsibleSection('页面列表', `
                <div class="page-list-container">
                    <ol>
                        ${pagesToDelete.map(page => `<li>${page}</li>`).join('')}
                    </ol>
                </div>
            `)}

            <div style="margin-top: 15px; padding: 10px; background-color: #fcf8e3; border: 1px solid #faebcc; color: #8a6d3b; border-radius: 4px;">
                <strong>警告:</strong> 请确认以上列表。点击"开始删除"后,这些页面将被删除。
            </div>
        `;

        showModal('预览删除列表', content);
    }

    // 开始删除
    function startDeletion() {
        const pagesText = document.getElementById('pages-to-delete').value.trim();
        if (!pagesText) {
            showMessage('请先添加要删除的页面', 'error');
            return;
        }

        // 将文本分割成页面数组
        const pagesToDelete = pagesText.split('\n')
            .map(page => page.trim())
            .filter(page => page.length > 0);

        if (pagesToDelete.length === 0) {
            showMessage('没有找到有效的页面标题', 'error');
            return;
        }

        // 删除确认
        if (!confirm('您即将删除 ' + pagesToDelete.length + ' 个页面。是否继续?')) {
            return;
        }

        // 准备删除
        const reason = document.getElementById('delete-reason').value;
        const processingRate = parseFloat(document.getElementById('processing-rate').value) * 1000; // 转换为毫秒

        // 获取保护设置
        const protectEnabled = document.getElementById('protect-after-delete').checked;
        let protectionParams = null;

        if (protectEnabled) {
            // 保护参数
            protectionParams = {
                level: document.getElementById('protection-level').value,
                expiry: convertExpiryToTimestamp(document.getElementById('protection-expiry').value),
                reason: document.getElementById('protection-reason').value
            };
        }

        const statusContainer = document.getElementById('deletion-status');
        statusContainer.style.display = 'block';

        const resultsElement = document.getElementById('deletion-results');
        resultsElement.innerHTML = '';

        // 开始删除过程
        processPageDeletion(pagesToDelete, 0, reason, protectionParams, processingRate);
    }

    // 转换保护期限为MediaWiki API接受的格式
    function convertExpiryToTimestamp(expiryOption) {
        // 如果是infinite(永久),直接返回
        if (expiryOption === 'infinite') {
            return 'infinite';
        }

        // 获取当前日期
        const now = new Date();

        // 根据选择的选项计算到期日期
        switch (expiryOption) {
            case '1 week':
                now.setDate(now.getDate() + 7);
                break;
            case '1 month':
                now.setMonth(now.getMonth() + 1);
                break;
            case '3 months':
                now.setMonth(now.getMonth() + 3);
                break;
            case '6 months':
                now.setMonth(now.getMonth() + 6);
                break;
            case '1 year':
                now.setFullYear(now.getFullYear() + 1);
                break;
            default:
                // 如果无法识别选项,默认为一周
                now.setDate(now.getDate() + 7);
        }

        // 将日期格式化为MediaWiki API接受的格式:YYYY-MM-DDThh:mm:ssZ
        return now.toISOString().replace(/\.\d+Z$/, 'Z');
    }

    // 处理页面删除(递归)- 修改为使用自定义速率
    function processPageDeletion(pages, index, reason, protectionParams, processingRate) {
        if (index >= pages.length) {
            // 所有页面处理完毕
            document.getElementById('progress-text').textContent = '完成! 删除操作已结束。';
            return;
        }

        const page = pages[index];
        const progressElement = document.getElementById('progress');
        const progressTextElement = document.getElementById('progress-text');
        const resultsElement = document.getElementById('deletion-results');

        // 更新进度
        const progressPercentage = Math.round((index / pages.length) * 100);
        progressElement.style.width = progressPercentage + '%';
        progressTextElement.textContent = '正在处理: ' + page + ' (' + (index + 1) + '/' + pages.length + ', ' + progressPercentage + '%)';

        // 执行删除API调用
        const api = new mw.Api();
        api.postWithToken('csrf', {
            action: 'delete',
            title: page,
            reason: reason,
            format: 'json'
        }).done(function() {
            // 删除成功
            const resultItem = document.createElement('div');
            resultItem.style.color = '#3c763d';
            resultItem.textContent = '✓ 成功删除: ' + page;
            resultsElement.appendChild(resultItem);

            // 如果需要保护页面
            if (protectionParams) {
                protectDeletedPage(page, protectionParams, resultsElement);
            }

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processPageDeletion(pages, index + 1, reason, protectionParams, processingRate);
            }, processingRate); // 使用自定义处理速率
        }).fail(function(code, result) {
            // 删除失败
            const resultItem = document.createElement('div');
            resultItem.style.color = '#a94442';
            resultItem.textContent = '✗ 删除失败: ' + page + ' - ' + (result.error ? result.error.info : code);
            resultsElement.appendChild(resultItem);

            // 使用自定义速率延迟继续下一个
            setTimeout(function() {
                processPageDeletion(pages, index + 1, reason, protectionParams, processingRate);
            }, processingRate); // 使用自定义处理速率
        });
    }

    // 保护已删除的页面 - 修改为支持新的回调方法
    function protectDeletedPage(page, protectionParams, resultsElementOrCallbacks) {
        const api = new mw.Api();
        api.postWithToken('csrf', {
            action: 'protect',
            title: page,
            protections: 'create=' + protectionParams.level,
            expiry: protectionParams.expiry,
            reason: protectionParams.reason,
            format: 'json'
        }).done(function() {
            // 保护成功
            if (typeof resultsElementOrCallbacks === 'object' && resultsElementOrCallbacks.onSuccess) {
                // 使用回调方法
                resultsElementOrCallbacks.onSuccess();
            } else {
                // 使用传统DOM更新
                const resultItem = document.createElement('div');
                resultItem.style.color = '#3a87ad';
                resultItem.textContent = '🔒 成功保护: ' + page;
                resultsElementOrCallbacks.appendChild(resultItem);
            }
        }).fail(function(code, result) {
            // 保护失败
            const errorMessage = result.error ? result.error.info : code;

            if (typeof resultsElementOrCallbacks === 'object' && resultsElementOrCallbacks.onFail) {
                // 使用回调方法
                resultsElementOrCallbacks.onFail(errorMessage);
            } else {
                // 使用传统DOM更新
                const resultItem = document.createElement('div');
                resultItem.style.color = '#8a6d3b';
                resultItem.textContent = '⚠ 保护失败: ' + page + ' - ' + errorMessage;
                resultsElementOrCallbacks.appendChild(resultItem);
            }
        });
    }

    // 检查页面是否存在
    function checkPageExists(pageName, callback) {
        const api = new mw.Api();
        api.get({
            action: 'query',
            titles: pageName,
            format: 'json'
        }).done(function(data) {
            if (data.query && data.query.pages) {
                // 页面ID为负数表示不存在
                const pageId = Object.keys(data.query.pages)[0];
                callback(parseInt(pageId) > 0);
            } else {
                callback(false);
            }
        }).fail(function() {
            callback(false);
        });
    }

    // 工具初始化
    function initTool() {
        console.log('正在初始化Fandom批量删除与保护工具...');
        createInterface();
        console.log('Fandom批量删除与保护工具已加载。');
    }

    // 在DOM加载完成后初始化工具
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTool);
    } else {
        initTool();
    }
})();