跳转到内容

User:Heihaheihaha-test/test2.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
// ==UserScript==
// @name         维基百科AI巡查助手 (Gemini)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  利用Gemini AI辅助维基百科巡查员分析新页面,识别问题并提供处理建议。
// @author       (Your Name) & Gemini
// @match        https://zh.wikipedia.org/wiki/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      generativelanguage.googleapis.com
// @updateURL    https://.../your-script.user.js  // Optional: Add your script's update URL
// @downloadURL  https://.../your-script.user.js // Optional: Add your script's download URL
// ==/UserScript==

(function() {
    'use strict';

    // --- 配置 ---
    const SCRIPT_ID_PREFIX = 'wpAiPatrolHelperGemini_';
    const WIKIPEDIA_ARTICLE_URL_REGEX = /^https:\/\/zh\.wikipedia\.org\/wiki\/[^:]+$/;
    const MAIN_CONTENT_SELECTOR = '#mw-content-text .mw-parser-output';
    const SELECTORS_TO_REMOVE_FROM_CONTENT = [
        '.toc', '.mw-editsection', '.navbox', '#catlinks', '.noprint',
        '#coordinates', 'table.ambox', '.gallery', 'figure.mw-halign-right',
        'figure.mw-halign-left', 'figure.mw-halign-center', 'div.thumb',
        'table.infobox', '.wikitable.plainlinks.metadata.ambox.ambox-style',
        '.mw-stack.selflink', 'div.printfooter', 'div.mw-hidden-catlinks'
    ];
    const MAX_ARTICLE_TEXT_LENGTH = 30000; // 限制发送给API的文本长度

    // --- 全局变量 ---
    let actionButton = null;
    let resultDialog = null;
    let isLoading = false;
    let aiConfig = null;

    // --- 样式 ---
    const SCRIPT_CSS = `
        #${SCRIPT_ID_PREFIX}actionButton {
            padding: 5px 10px; font-size: 0.85em; background-color: #008080; color: white;
            border: 1px solid #006666; border-radius: 4px; cursor: pointer; margin-left: 8px;
            line-height: normal;
        }
        #${SCRIPT_ID_PREFIX}actionButton:hover { background-color: #006666; }
        #${SCRIPT_ID_PREFIX}actionButton:disabled { background-color: #cccccc; cursor: not-allowed; }
        
        /* 在左侧“工具”栏中的样式 */
        #p-tb #${SCRIPT_ID_PREFIX}actionButton {
            all: unset;
            color: #0645ad;
            cursor: pointer;
            font-size: inherit;
        }
        #p-tb #${SCRIPT_ID_PREFIX}actionButton:hover {
            text-decoration: underline;
        }
        #p-tb #${SCRIPT_ID_PREFIX}actionButton:disabled {
             color: #a2a9b1;
             cursor: not-allowed;
             text-decoration: none;
        }

        #${SCRIPT_ID_PREFIX}resultDialog {
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
            width: 800px; max-width: 95vw; max-height: 85vh;
            background-color: #fdfdfd; border: 1px solid #bdc3c7;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3); z-index: 2000;
            display: none; border-radius: 6px; overflow: hidden;
            flex-direction: column; font-size: 14px;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-header {
            padding: 12px 18px; background-color: #e0e7e7; border-bottom: 1px solid #c8d0d0;
            display: flex; justify-content: space-between; align-items: center; cursor: grab;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-header h3 {
            margin: 0; font-size: 1.3em; color: #205050;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-close-btn {
            background: none; border: none; font-size: 2em; font-weight: bold;
            color: #507070; cursor: pointer; padding: 0 8px; line-height: 1;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-close-btn:hover { color: #205050; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content {
            padding: 15px 20px; overflow-y: auto; line-height: 1.65; color: #333;
            flex-grow: 1; background-color: #fff;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content pre {
            white-space: pre-wrap; word-wrap: break-word; background-color: #f0f0f0;
            border: 1px solid #e0e0e0; padding: 10px 12px; border-radius: 4px;
            font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
            font-size: 0.9em; max-height: 400px; overflow-y: auto;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content code {
            font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
            background-color: #f0f0f0; padding: 0.15em 0.4em; border-radius: 3px; font-size: 0.9em;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content pre code {
            background-color: transparent; padding: 0; font-size: inherit;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h1, #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h2,
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h3, #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h4 {
             margin-top: 1.2em; margin-bottom: 0.6em; color: #1a4040; line-height: 1.3;
             padding-bottom: 0.1em; border-bottom: 1px solid #e0e7e7;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h1 { font-size: 1.7em; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h2 { font-size: 1.5em; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content h3 { font-size: 1.3em; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content ul, #${SCRIPT_ID_PREFIX}resultDialog .dialog-content ol {
            padding-left: 25px; margin-bottom: 1em;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content p { margin-bottom: 1em; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content strong { font-weight: bold; }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content table {
            border-collapse: collapse; margin: 1.2em 0; width: 100%;
            border: 1px solid #c8d0d0; box-shadow: 0 1px 2px rgba(0,0,0,0.05);
            font-size: 0.95em;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content th,
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content td {
            border: 1px solid #d8e0e0; padding: 8px 12px; text-align: left;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content th {
            background-color: #eaf3f3; font-weight: bold; color: #205050;
        }
        #${SCRIPT_ID_PREFIX}resultDialog .dialog-content tr:nth-child(even) td {
            background-color: #f8fbfb;
        }
        #${SCRIPT_ID_PREFIX}configWarning {
            background-color: #fff3cd; color: #856404; padding: 10px;
            border: 1px solid #ffeeba; border-radius: 4px; margin: 10px 0;
            text-align: center; font-size: 0.9em;
        }
    `;

    /**
     * 将CSS注入页面
     */
    function injectStyles() {
        if (typeof GM_addStyle !== 'undefined') {
            GM_addStyle(SCRIPT_CSS);
        } else {
            const styleElement = document.createElement('style');
            styleElement.id = `${SCRIPT_ID_PREFIX}styles`;
            styleElement.textContent = SCRIPT_CSS;
            document.head.appendChild(styleElement);
        }
    }

    /**
     * 加载并验证AI配置
     */
    function loadAiConfig() {
        try {
            const storedConfig = localStorage.getItem('wpAiPatrolHelperGeminiConfig');
            if (storedConfig) {
                aiConfig = JSON.parse(storedConfig);
            } else if (typeof GM_getValue !== 'undefined') {
                const gmStoredConfig = GM_getValue('wpAiPatrolHelperGeminiConfig');
                if (gmStoredConfig) aiConfig = JSON.parse(gmStoredConfig);
            }

            if (!aiConfig || !aiConfig.apiKey || !aiConfig.modelName) {
                displayConfigWarning();
                return false;
            }
            const warningDiv = document.getElementById(`${SCRIPT_ID_PREFIX}configWarning`);
            if (warningDiv) warningDiv.style.display = 'none';
            return true;
        } catch (e) {
            displayConfigWarning('加载Gemini AI配置时出错。');
            console.error("Error loading AI config:", e);
            return false;
        }
    }

    /**
     * 显示配置缺失的警告信息
     */
    function displayConfigWarning(specificMessage = '') {
        let warningDiv = document.getElementById(`${SCRIPT_ID_PREFIX}configWarning`);
        if (!warningDiv) {
            warningDiv = document.createElement('div');
            warningDiv.id = `${SCRIPT_ID_PREFIX}configWarning`;
            const firstHeading = document.getElementById('firstHeading');
            if (firstHeading) {
                firstHeading.parentNode.insertBefore(warningDiv, firstHeading.nextSibling);
            } else {
                const contentDiv = document.getElementById('content');
                if (contentDiv) contentDiv.prepend(warningDiv);
            }
        }
        const generalMessage = 'AI巡查助手(Gemini)配置不完整或缺失。请在浏览器开发者控制台 (F12) 中运行指令来设置API密钥及模型名称。详情请参考脚本的安装说明。';
        warningDiv.textContent = generalMessage + (specificMessage ? ` (${specificMessage})` : '');
        warningDiv.style.display = 'block';

        console.info("To configure AI Patrol Helper (Gemini), run the following in your browser's developer console on any zh.wikipedia.org page:\n" +
            "localStorage.setItem('wpAiPatrolHelperGeminiConfig', JSON.stringify({\n" +
            "  apiKey: 'YOUR_GEMINI_API_KEY_HERE',\n" +
            "  modelName: 'gemini-1.5-flash-latest' \n" +
            "}));\n" +
            "Then refresh the page.");
    }

    /**
     * 检查当前是否为有效的中文维基百科条目页面
     */
    function isChineseWikipediaArticlePage() {
        return WIKIPEDIA_ARTICLE_URL_REGEX.test(window.location.href) &&
               document.querySelector(MAIN_CONTENT_SELECTOR) &&
               !document.getElementById('noarticletext');
    }

    /**
     * 提取并清理条目正文内容
     */
    function getArticleContentText() {
        const contentElement = document.querySelector(MAIN_CONTENT_SELECTOR);
        if (!contentElement) return null;

        const clonedContent = contentElement.cloneNode(true);
        SELECTORS_TO_REMOVE_FROM_CONTENT.forEach(selector => {
            clonedContent.querySelectorAll(selector).forEach(el => el.remove());
        });

        // 优先使用结构化文本提取,以保留段落
        let text = "";
        clonedContent.querySelectorAll('p, h1, h2, h3, h4, h5, h6, li, pre, blockquote, dl, dd, dt').forEach(el => {
            const trimmedText = (el.innerText || el.textContent || "").trim();
            if (trimmedText) {
                text += trimmedText + "\n\n";
            }
        });

        // 如果结构化提取失败,使用纯文本
        if (!text.trim()) {
            text = (clonedContent.innerText || clonedContent.textContent || "").trim();
        }

        text = text.replace(/\[编辑\]/g, '').replace(/\[\d+\]/g, '').replace(/\n\s*\n/g, '\n\n').trim();
        return text.length > MAX_ARTICLE_TEXT_LENGTH ? text.substring(0, MAX_ARTICLE_TEXT_LENGTH) + "\n\n[条目内容过长,已被截断]" : text;
    }

    /**
     * 显示或隐藏加载状态
     */
    function showLoadingState(show) {
        isLoading = show;
        if (actionButton) {
            actionButton.textContent = show ? '处理中...' : 'AI巡查助手 (Gemini)';
            actionButton.disabled = show;
        }
        if (show && !resultDialog) {
            createResultDialog();
        }
        if (resultDialog) {
            const contentDiv = resultDialog.querySelector(`#${SCRIPT_ID_PREFIX}resultDialog .dialog-content`);
            contentDiv.innerHTML = show ? '<p style="text-align:center; padding: 20px;"><i>AI分析中,请稍候...</i></p>' : '';
            if (show) resultDialog.style.display = 'flex';
        }
    }

    /**
     * 将Markdown格式的AI响应转换为HTML
     */
    function escapeHtml(unsafeStr) {
        if (typeof unsafeStr !== 'string') return '';
        return unsafeStr.replace(/[&<>"']/g, match => ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'
        }[match]));
    }

    function processInlineMarkdown(text) {
        text = escapeHtml(text);
        text = text.replace(/\*\*(.*?)\*\*|__(.*?)__/g, '<strong>$1$2</strong>'); // Bold
        text = text.replace(/(?<!\*)\*(?!\s)(.*?[^\s])\*(?!\*)|_(.*?)_/g, '<em>$1$2</em>'); // Italic
        text = text.replace(/`([^`]+)`/g, '<code>$1</code>'); // Inline code
        return text;
    }

    function parseMarkdownTableRow(rowLine) {
        const trimmed = rowLine.trim();
        if (trimmed.startsWith('|') && trimmed.endsWith('|')) {
            return trimmed.slice(1, -1).split('|').map(cell => cell.trim());
        }
        return trimmed.split('|').map(cell => cell.trim());
    }

    function basicMarkdownToHtml(md) {
        let html = '';
        const lines = md.split('\n');
        let inListType = null; // 'ul' or 'ol'
        let inTable = false;

        function closeOpenTags() {
            if (inListType) {
                html += (inListType === 'ul' ? '</ul>\n' : '</ol>\n');
                inListType = null;
            }
            if (inTable) {
                html += '</tbody></table>\n';
                inTable = false;
            }
        }

        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];

            // Headings
            const headingMatch = line.match(/^(#{1,4})\s+(.*)/);
            if (headingMatch) {
                closeOpenTags();
                const level = headingMatch[1].length;
                html += `<h${level}>${processInlineMarkdown(headingMatch[2])}</h${level}>\n`;
                continue;
            }

            // Table
            const tableRowMatch = line.match(/^\|.*\|$/);
            if (tableRowMatch) {
                // Check for separator line to start a table
                const nextLine = lines[i + 1] || '';
                if (nextLine.match(/^\|(?:\s*:?-+:?\s*\|)+$/)) {
                    closeOpenTags();
                    inTable = true;
                    const headers = parseMarkdownTableRow(line);
                    html += '<table>\n<thead>\n<tr>\n';
                    headers.forEach(header => {
                        html += `<th>${processInlineMarkdown(header)}</th>\n`;
                    });
                    html += '</tr>\n</thead>\n<tbody>\n';
                    i++; // Skip separator line
                    continue;
                }
                // If already in a table, process as a row
                if (inTable) {
                    const cells = parseMarkdownTableRow(line);
                    html += '<tr>\n';
                    cells.forEach(cell => {
                        html += `<td>${processInlineMarkdown(cell)}</td>\n`;
                    });
                    html += '</tr>\n';
                    continue;
                }
            }

            // If line is not a table row, but we were in a table, close it.
            if (inTable && !tableRowMatch) {
                 html += '</tbody></table>\n';
                 inTable = false;
            }

            // Lists
            const ulMatch = line.match(/^\s*[-*+]\s+(.*)/);
            const olMatch = line.match(/^\s*\d+\.\s+(.*)/);
            if (ulMatch) {
                if (inListType !== 'ul') { closeOpenTags(); html += '<ul>\n'; inListType = 'ul'; }
                html += `<li>${processInlineMarkdown(ulMatch[1])}</li>\n`;
                continue;
            }
            if (olMatch) {
                if (inListType !== 'ol') { closeOpenTags(); html += '<ol>\n'; inListType = 'ol'; }
                html += `<li>${processInlineMarkdown(olMatch[1])}</li>\n`;
                continue;
            }

            // If it's not a list item, but we were in a list, close it
            if (inListType && !ulMatch && !olMatch) {
                 closeOpenTags();
            }

            // Paragraphs
            if (line.trim()) {
                closeOpenTags(); // A paragraph breaks any open blocks
                html += `<p>${processInlineMarkdown(line)}</p>\n`;
            }
        }

        closeOpenTags(); // Close any remaining open tags at the end
        return html;
    }

    /**
     * 显示分析结果或错误信息
     */
    function displayAnalysisResult(analysisText, isError = false) {
        showLoadingState(false);
        if (!resultDialog) createResultDialog();

        const contentDiv = resultDialog.querySelector(`#${SCRIPT_ID_PREFIX}resultDialog .dialog-content`);
        if (isError) {
            contentDiv.innerHTML = `<p style="color: red; font-weight: bold;">处理出错:</p><pre>${escapeHtml(analysisText)}</pre>`;
        } else {
            contentDiv.innerHTML = basicMarkdownToHtml(analysisText);
        }
        resultDialog.style.display = 'flex';
    }

    /**
     * 调用Gemini API
     */
    async function makeAiApiCall(prompt) {
        if (!aiConfig) throw new Error("Gemini AI配置未加载。");

        const endpointUrl = `https://generativelanguage.googleapis.com/v1beta/models/${aiConfig.modelName}:generateContent?key=${aiConfig.apiKey}`;
        const requestBody = {
            contents: [{ role: "user", parts: [{ text: prompt }] }],
            generationConfig: {
                "maxOutputTokens": 8192,
                "temperature": 0.4, // Lower temperature for more consistent, factual responses
            },
        };

        try {
            const response = await fetch(endpointUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(requestBody)
            });

            const data = await response.json();

            if (!response.ok) {
                const errorMsg = data?.error?.message || response.statusText || `HTTP Error ${response.status}`;
                throw new Error(`Gemini API调用失败: ${errorMsg}`);
            }

            if (data.candidates && data.candidates[0]?.content?.parts) {
                return data.candidates[0].content.parts.map(part => part.text).join("\n");
            }

            if (data.promptFeedback?.blockReason) {
                throw new Error(`请求被安全设置阻止 (Gemini): ${data.promptFeedback.blockReason}. ${data.promptFeedback.blockReasonMessage || ''}`);
            }

            throw new Error('未能从Gemini API获取有效回复。请检查控制台的API响应详情。');

        } catch (error) {
            console.error("API Call Error:", error);
            throw error;
        }
    }

    /**
     * 处理“AI巡查助手”按钮点击事件
     */
    async function handlePatrolCheckAction() {
        if (isLoading) return;
        if (!loadAiConfig()) {
            displayAnalysisResult("无法执行操作:AI配置不正确或缺失。请检查浏览器控制台中的设置说明。", true);
            return;
        }

        const articleText = getArticleContentText();
        const articleTitle = (document.querySelector('#firstHeading .mw-page-title-main') || document.querySelector('#firstHeading') || {}).innerText || document.title.replace(' - 维基百科,自由的百科全书', '');

        if (!articleText) {
            displayAnalysisResult("无法提取条目内容进行分析。", true);
            return;
        }

        showLoadingState(true);

        const patrolPrompt = `
你是一位经验丰富、认真负责的中文维基百科巡查员。你的任务是基于新页面巡查的常见标准,分析一个新创建的条目,并向人类巡查员提供清晰、可行的处理建议。

请严格按照以下结构,以Markdown格式输出你的分析报告:

### 1. 总体评估
(在这里用一两句话简要概括条目的整体状况、主题和主要问题。)

### 2. 问题分析与处理建议
(以表格形式呈现。如果某个标准没有发现显著问题,可以不在此列出或简单说明“基本符合要求”。)

| 问题类型 | 分析与说明 | 建议操作 |
| --- | --- | --- |
| **知名度 (Notability)** | (评估主题是否符合通用关注度指引。是否有迹象表明其关注度不足?例如,主题是否仅为地方性、缺乏深度报道等。) | (如果关注度存疑,建议添加 \`{{Notability|||||time=2025-06-10T16:04:00+00:00}}\` 并提报存废讨论。如果明显不符,可建议快速删除,并给出合适的速删理由,如 G11。) |
| **来源 (Sourcing)** | (评估条目是否提供了参考文献。参考文献的质量如何?是可靠来源吗?关键事实是否有引用支持?) | (如果完全没有来源,建议添加 \`{{Unreferenced|time=2025-06-10T16:04:00+00:00}}\`。如果来源不足,建议 \`{{Refimprove|time=2025-06-10T16:04:00+00:00}}\`。) |
| **中立性与语调 (NPOV & Tone)** | (评估条目的语调是否中立、客观。是否存在宣传、广告、粉丝网站或原创研究的语气?) | (如果像爱好者网站,建议添加 \`{{fansite}}\`。如果含宣传语调,可建议 \`{{Cleanup|reason=|time=2025-06-10T16:04:00+00:00}}\` 或速删 G11。) |
| **内容质量与格式** | (评估内容是否为极短的小小作品、劣质翻译、非中文内容,或格式混乱需要维基化。) | (小于50字建议 \`{{Substub|time=2025-06-10T16:04:00+00:00}}\`。机器翻译建议 \`{{RoughTranslation}}\`。非中文内容建议 \`{{NotMandarin|time=2025-06-10T16:04:00+00:00}}\`。格式问题建议 \`{{Wikify|time=2025-06-10T16:04:00+00:00}}\`。) |
| **版权 (Copyright)** | (根据文本内容和行文风格,初步判断是否存在直接复制粘贴的可能。注意:这只是初步怀疑,无法定论。) | (如果高度怀疑,建议巡查员手动使用工具检查。可提示:“文本风格疑似直接复制自……,建议使用查重工具进行核对。”) |

### 3. 最终建议
(根据以上分析,给出一个明确的最终操作建议。例如:“**综合建议:悬挂知名度模板,并提报页面存废讨论。**” 或 “**综合建议:条目基本合格,添加维基化和来源请求模板后可巡查通过。**” 或 “**综合建议:符合快速删除标准G11,建议立即提报速删。**”)

---
现在,请分析以下维基百科条目:

**条目名称**:“${articleTitle}

**条目内容**(可能已截断):
\`\`\`
${articleText}
\`\`\`
`;

        try {
            const analysis = await makeAiApiCall(patrolPrompt);
            displayAnalysisResult(analysis);
        } catch (error) {
            displayAnalysisResult(error.message, true);
        }
    }

    /**
     * 创建操作按钮并放置到页面上
     */
    function createActionButton() {
        if (document.getElementById(`${SCRIPT_ID_PREFIX}actionButton`)) return;

        actionButton = document.createElement('button');
        actionButton.textContent = 'AI巡查助手 (Gemini)';
        actionButton.id = `${SCRIPT_ID_PREFIX}actionButton`;
        actionButton.title = '使用Gemini AI辅助分析条目质量并提供巡查建议';
        actionButton.addEventListener('click', handlePatrolCheckAction);

        const toolbarSelectors = [
            '#p-tb ul',                                         // [优先] Vector皮肤的“工具”栏
            '#p-views ul',                                       // Vector皮肤的顶部标签栏
            '.vector-feature-page-tools .vector-menu-content ul',// Vector-2022皮肤的“工具”下拉菜单
            '#p-cactions .vector-menu-content ul'                // 旧版Vector皮肤的“更多”下拉菜单
        ];

        let targetToolbar = toolbarSelectors.map(s => document.querySelector(s)).find(el => el);

        if (targetToolbar) {
            const newListItem = document.createElement('li');
            newListItem.id = `t-aipatrol`; // 为项目设置ID
            newListItem.appendChild(actionButton);
            targetToolbar.appendChild(newListItem);
        } else {
            // 如果找不到工具栏,则作为悬浮按钮
            actionButton.style.position = 'fixed';
            actionButton.style.top = '100px';
            actionButton.style.right = '20px';
            actionButton.style.zIndex = '1500';
            document.body.appendChild(actionButton);
            console.warn("Could not find a standard Wikipedia toolbar. Falling back to a fixed button.");
        }
    }

    /**
     * 创建用于显示结果的对话框
     */
    function createResultDialog() {
        if (document.getElementById(`${SCRIPT_ID_PREFIX}resultDialog`)) return;

        resultDialog = document.createElement('div');
        resultDialog.id = `${SCRIPT_ID_PREFIX}resultDialog`;
        resultDialog.style.display = 'flex';
        resultDialog.innerHTML = `
            <div class="dialog-header">
                <h3>AI巡查助手 (Gemini)</h3>
                <button class="dialog-close-btn" title="关闭">&times;</button>
            </div>
            <div class="dialog-content"></div>
        `;
        document.body.appendChild(resultDialog);

        resultDialog.querySelector('.dialog-close-btn').addEventListener('click', () => {
            resultDialog.style.display = 'none';
        });

        // 添加拖拽功能
        const header = resultDialog.querySelector('.dialog-header');
        let isDragging = false;
        let currentX, currentY, initialX, initialY, xOffset = 0, yOffset = 0;

        header.addEventListener('mousedown', e => {
            if (e.target.classList.contains('dialog-close-btn')) return;
            initialX = e.clientX - xOffset;
            initialY = e.clientY - yOffset;
            isDragging = true;
            header.style.cursor = 'grabbing';
        });

        document.addEventListener('mousemove', e => {
            if (isDragging) {
                e.preventDefault();
                currentX = e.clientX - initialX;
                currentY = e.clientY - initialY;
                xOffset = currentX;
                yOffset = currentY;
                resultDialog.style.transform = `translate(-50%, -50%) translate(${currentX}px, ${currentY}px)`;
            }
        });

        document.addEventListener('mouseup', () => {
            if (isDragging) {
                isDragging = false;
                header.style.cursor = 'grab';
            }
        });
    }

    /**
     * 初始化脚本
     */
    function initializeScript() {
        if (mw && mw.config && mw.config.get('wgIsProbablyEditable') && isChineseWikipediaArticlePage()) {
            injectStyles();
            createActionButton();
            // 首次加载时检查配置,但不阻塞页面
            // 点击按钮时会再次进行严格检查
            setTimeout(loadAiConfig, 1000);
        }
    }

    // 等待MediaWiki核心模块加载完毕后执行
    mw.loader.using(['mediawiki.util']).then(initializeScript);

})();