Greasy Fork

Greasy Fork is available in English.

ChatGPT 身份认证全自动 (V21.1 增强版)

加强版,自动从页面提取数据并填充表单,支持一键导出数据

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         ChatGPT 身份认证全自动 (V21.1 增强版)
// @namespace    http://tampermonkey.net/
// @version      21.1.2
// @description  加强版,自动从页面提取数据并填充表单,支持一键导出数据
// @author       CreatorEdition
// @match        https://gravelocator.cem.va.gov/*
// @match        https://www.vlm.cem.va.gov/*
// @match        https://www.cmohs.org/recipients/*
// @match        https://services.sheerid.com/*
// @match        https://chatgpt.com/veterans-claim/*
// @match        https://chatgpt.com/veterans-claim
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- 核心配置 ---
    const DEFAULT_EMAIL = "[email protected]"; // 默认备用邮箱
    const MIN_BIRTH_YEAR = 1930;
    const FILL_DELAY = 1000; // 在 sheerid 页面延迟1秒填写

    // --- 获取当前使用的邮箱 ---
    function getCurrentEmail() {
        return GM_getValue('custom_target_email', DEFAULT_EMAIL);
    }
    // --- 设置新邮箱 ---
    function setNewEmail(email) {
        GM_setValue('custom_target_email', email);
    }

    const FIELD_MAP = {
        status: '#sid-military-status',
        branch: '#sid-branch-of-service',
        firstName: '#sid-first-name',
        lastName: '#sid-last-name',
        bMonth: '#sid-birthdate__month',
        bDay: '#sid-birthdate-day',
        bYear: '#sid-birthdate-year',
        dMonth: '#sid-discharge-date__month',
        dDay: '#sid-discharge-date-day',
        dYear: '#sid-discharge-date-year',
        email: '#sid-email'
    };
    const SUBMIT_BTN_SELECTOR = '#sid-submit-btn-collect-info';
    const RESULT_TABLE_SELECTOR = '#searchResults tbody';
    const ERROR_BUTTON_SELECTOR = '.sid-error-button-container a.sid-btn';
    // 固定配置
    const FIXED_STATUS = "Military Veteran or Retiree";
    const FIXED_DISCHARGE_YEAR = "2025";
    const MONTH_MAP = {
        "01": "January", "02": "February", "03": "March", "04": "April",
        "05": "May", "06": "June", "07": "July", "08": "August",
        "09": "September", "10": "October", "11": "November", "12": "December"
    };
    // --- ✅ VLM 页面月份缩写映射 ---
    const MONTH_ABBR_MAP = {
        Jan: "January", Feb: "February", Mar: "March", Apr: "April",
        May: "May", Jun: "June", Jul: "July", Aug: "August",
        Sep: "September", Oct: "October", Nov: "November", Dec: "December"
    };
    function normalizeMonthName(m) {
        if (!m) return "";
        const s = String(m).trim();
        // 兼容 "10"/"01" 这种
        if (/^\d{1,2}$/.test(s)) {
            const mm = s.padStart(2, "0");
            return MONTH_MAP[mm] || "";
        }
        // 兼容 "Oct"/"October"
        const key = s.slice(0, 3);
        if (MONTH_ABBR_MAP[key]) return MONTH_ABBR_MAP[key];
        return s;
    }

    // --- 随机工具函数 (用于生成1-25的日期) ---
    function getRandomDay1to25() {
        return Math.floor(Math.random() * 25) + 1;
    }
    function getRandomMonth() {
        const months = Object.values(MONTH_MAP);
        return months[Math.floor(Math.random() * months.length)];
    }

    // --- 状态管理 ---
    function getQueue() { return GM_getValue('global_auth_queue', []); }
    function saveQueue(arr) { GM_setValue('global_auth_queue', arr); updateUI(); }
    function getCurrentTask() { return GM_getValue('current_active_task', null); }
    function setCurrentTask(task) { GM_setValue('current_active_task', task); }
    function getSubmitState() { return GM_getValue('is_submitting_flag', false); }
    function setSubmitState(bool) { GM_setValue('is_submitting_flag', bool); }
    function getIsRunning() { return GM_getValue('is_script_running', false); }
    function setIsRunning(bool) { GM_setValue('is_script_running', bool); updateUI(); }
    function getFillingStage() { return GM_getValue('filling_stage', 0); }
    function setFillingStage(stage) { GM_setValue('filling_stage', stage); }
    function getWaitingForRetry() { return GM_getValue('waiting_for_retry', false); }
    function setWaitingForRetry(bool) { GM_setValue('waiting_for_retry', bool); }
    function getClaimPageAttempts() { return GM_getValue('claim_page_attempts', 0); }
    function setClaimPageAttempts(count) { GM_setValue('claim_page_attempts', count); }
    function getInitialFillDelay() { return GM_getValue('initial_fill_delay_done', false); }
    function setInitialFillDelay(bool) { GM_setValue('initial_fill_delay_done', bool); }
    function getLastClickedUrl() { return GM_getValue('last_clicked_url', ''); }
    function setLastClickedUrl(url) { GM_setValue('last_clicked_url', url); }

    // --- 🔥 错误检测和自动重试 ---
    function checkForErrorAndRetry() {
        const errorBtn = document.querySelector(ERROR_BUTTON_SELECTOR);
        if (errorBtn) {
            const href = errorBtn.getAttribute('href');
            log('⚠️ 检测到错误页面,准备重试...', '#ff6b6b');
            statusArea.innerHTML = "🔄 检测到错误,自动重试中...";
            // 标记为等待重试状态
            setWaitingForRetry(true);
            setClaimPageAttempts(0);
            // 点击 Try Again 按钮
            setTimeout(() => {
                log('🔄 点击 Try Again 按钮...', '#ffc107');
                errorBtn.click();
            }, 500);
            return true;
        }
        return false;
    }

    // --- 🔥 在 veterans-claim 页面持续尝试点击"验证资格条件"按钮 ---
    function checkClaimPageButton() {
        const currentUrl = window.location.href;
        if (!currentUrl.includes('chatgpt.com/veterans-claim')) {
            return false;
        }
        const isRunning = getIsRunning();
        const isWaitingRetry = getWaitingForRetry();
        if (!isRunning && !isWaitingRetry) {
            return false;
        }
        // 查找"验证资格条件"按钮
        const buttons = Array.from(document.querySelectorAll('button.btn.relative.btn-primary'));
        let targetBtn = null;

        for (let btn of buttons) {
            const text = btn.textContent.trim();
            if (text.includes('验证资格条件') || text.includes('验证') || text.includes('领取优惠') || text.includes('Verify')) {
                targetBtn = btn;
                break;
            }
        }
        if (targetBtn) {
            const isDisabled = targetBtn.disabled ||
                               targetBtn.hasAttribute('disabled') ||
                               targetBtn.classList.contains('cursor-not-allowed') ||
                               targetBtn.getAttribute('data-visually-disabled') !== null;

            const attempts = getClaimPageAttempts();
            if (isDisabled) {
                setClaimPageAttempts(attempts + 1);
                log(`⏳ 按钮加载中,等待... (尝试 ${attempts + 1})`, '#ffc107');
                statusArea.innerHTML = `🔄 等待按钮激活中...`;
                return true;
            } else {
                // 🔥 修改:点击1次后,2秒后还没有跳转重新点击 (无次数限制)
                const lastClickTs = GM_getValue('last_verify_click_ts', 0);
                // 如果距离上次点击不足 2000 毫秒 (2秒),则跳过本次,等待下一次循环
                if (Date.now() - lastClickTs < 2000) {
                     statusArea.innerHTML = "⏳ 等待跳转 (2s)...";
                     return true;
                }
                // 更新本次点击时间
                GM_setValue('last_verify_click_ts', Date.now());
                // 🔥 修改结束

                const lastUrl = getLastClickedUrl();
                if (lastUrl === currentUrl) {
                    setClaimPageAttempts(attempts + 1);
                    log(`🎯 点击按钮... (第 ${attempts + 1} 次)`, '#28a745');
                    statusArea.innerHTML = `🎯 点击按钮...`;
                } else {
                    log(`✅ 按钮已激活,准备点击`, '#28a745');
                    statusArea.innerHTML = "🎯 按钮已激活,正在点击...";
                    setClaimPageAttempts(0);
                }

                setLastClickedUrl(currentUrl);
                setTimeout(() => {
                    targetBtn.click();
                    log('🚀 已点击按钮,等待跳转...', '#0d6efd');
                }, 300);
                return true;
            }
        } else {
            const attempts = getClaimPageAttempts();
            setClaimPageAttempts(attempts + 1);
            log(`⏳ 等待页面加载按钮... (尝试 ${attempts + 1})`, '#6c757d');
            statusArea.innerHTML = `⏳ 等待页面加载...`;
            return true;
        }
    }

    // --- 🔥 检测是否成功跳转到 SheerID 页面 ---
    function checkIfLeftClaimPage() {
        const currentUrl = window.location.href;
        const lastUrl = getLastClickedUrl();

        if (lastUrl.includes('chatgpt.com/veterans-claim') && currentUrl.includes('services.sheerid.com')) {
            log('✅ 成功跳转到 SheerID 页面', '#28a745');
            setWaitingForRetry(false);
            setClaimPageAttempts(0);
            setFillingStage(0);
            setInitialFillDelay(false);
            setLastClickedUrl('');
            return true;
        }
        return false;
    }

    // --- 页面初始化 ---
    function initLogic() {
        const currentUrl = window.location.href;
        const justSubmitted = getSubmitState();
        if (justSubmitted) {
            console.log("✅ 提交完成,清除任务");
            setCurrentTask(null);
            setSubmitState(false);
            setFillingStage(0);
            setInitialFillDelay(false);
        }
        checkIfLeftClaimPage();
        checkForErrorAndRetry();
        if (currentUrl.includes('services.sheerid.com')) {
            const stage = getFillingStage();
            if (stage === 0 && !getInitialFillDelay()) {
                log('📍 SheerID 页面已加载,准备延迟填写...', '#0d6efd');
            }
        }
    }

    // --- UI 创建 (✅ 按照图片风格重写 + 增加最小化功能) ---
    function createPanel() {
        // --- 1. 恢复按钮(小圆球)---
        const restoreBtn = document.createElement('div');
        restoreBtn.id = 'gpt_auth_restore_btn';
        restoreBtn.style = `
            position: fixed;
            bottom: 50px;
            right: 20px;
            width: 50px;
            height: 50px;
            background: #C31D1A;
            border-radius: 50%;
            box-shadow: 0 4px 15px rgba(0,0,0,0.3);
            z-index: 999999;
            cursor: pointer;
            display: none; /* 默认隐藏 */
            align-items: center;
            justify-content: center;
            font-size: 24px;
            color: white;
            border: 2px solid #fff;
        `;
        restoreBtn.innerHTML = "🚀"; // 图案
        restoreBtn.title = "点击恢复面板";
        document.body.appendChild(restoreBtn);

        // --- 2. 主面板 ---
        const div = document.createElement('div');
        div.id = 'gpt_auth_main_panel';
        // 外部容器样式:红色圆角边框
        div.style = `
            position: fixed;
            bottom: 50px;
            right: 20px;
            width: 380px;
            background: #fff;
            border: 8px solid #C31D1A;
            box-shadow: 0 8px 30px rgba(0,0,0,0.25);
            z-index: 999999;
            padding: 15px;
            border-radius: 25px; /* 大圆角 */
            font-family: 'Microsoft YaHei', sans-serif;
            font-size: 13px;
            box-sizing: border-box;
            display: block; /* 默认显示 */
        `;

div.innerHTML = `
            <div id="btn_minimize" style="
                position: absolute;
                top: 0;
                left: 0;
                width: 30px;
                height: 30px;
                background: #C31D1A;
                color: white;
                font-size: 9px;
                line-height: 24px;
                font-weight: bold;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                z-index: 1000;
                border-bottom-right-radius: 8px; /*右下角一点圆角,美观*/
            ">最小化</div>

            <div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom: 5px; padding-left: 25px;">
                <div style="font-size:18px; font-weight:bold; color:#C31D1A; display:flex; align-items:center; gap:5px;">
                    <span>🚀</span>
                    <span>GPT认证 V21.1 增强版</span>
                </div>

                <div style="position:relative; text-align:right; display:flex; gap:10px; align-items:center;">
                     <span id="update_log_trigger" style="font-size:12px; color:#333; text-decoration:underline; cursor:pointer; font-weight:bold;">更新日志</span>
                     <div id="queue_count" style="display:inline-block; background:#D9363E; color:white; width:24px;
                     height:24px; line-height:24px; text-align:center; border-radius:50%; font-size:14px; font-weight:bold;">0</div>

                    <div id="update_tooltip" style="
                        display:none;
                        position: absolute;
                        top: -35px;
                        right: 0;
                        background: white;
                        border: 1px solid #ccc;
                        padding: 10px;
                        border-radius: 4px;
                        box-shadow: 0 2px 5px rgba(0,0,0,0.2);
                        white-space: nowrap;
                        color: #333;
                        font-size: 12px;
                        pointer-events: none;
                        text-align: left;
                        line-height: 1.5;
                        z-index: 1001;
                        ">
                        <strong style="text-decoration: underline;">哔站用户:chatgpt充值会员 制作此加强版本</strong><br>
                        →后续会更新,点油猴的管理面板,点这个脚本,点主页可以看到更新,也可以关注哔站<br>
                        <strong>注意事项:</strong><br>
                        ①<strong>注意要用美国ip!!</strong><br>
                        ②显示error是正常现象,换下一个人就行了<br><br>

                        <span style="color: #666;">加强版更新</span><br>
                        1,支持新大兵网站:https://www.vlm.cem.va.gov/<br>
                        2,支持新大兵网站:https://www.cmohs.org/recipients/page/5?action_year[start]=1964&deceased=No<br>
                        3,改进了稳定性,修复了第一列有时不选择的bug<br>
                        4,新增导出功能,可以导出数据到不同浏览器使用<br>
                        5,增加按钮不亮进行重新填写的功能<br>
                        6,增加绑定邮箱功能<br>
                        7,增加最小化功能
                    </div>
                </div>
            </div>

            <div style="background:#fff0f0;
            border:1px dashed #C31D1A; border-radius:8px; padding:8px; margin-bottom:12px;">

                <div style="font-size:12px;
                margin-bottom: 8px; border-bottom:1px solid #ffcccc; padding-bottom:8px;">
                    <span style="color:#000;
                    font-weight:500; font-weight:bold; text-decoration:underline;">普通充值Plus会员138一个月/新号115一个月</span>
                    <span style="color:#000;
                    font-weight:500;">→</span>
                    <a href="https://work.weixin.qq.com/ca/cawcde170dc32c3290" target="_blank" style="color:#0d6efd;
                    text-decoration:underline; cursor:pointer; font-weight:bold;">点击跳转</a>
                </div>

                <div style="font-weight:bold;
                color:#C31D1A; margin-bottom:4px; font-size:13px;">重要:输入你的邮箱</div>
                <div style="display:flex;
                gap:5px; margin-bottom:4px;">
                    <input id="input_custom_email" type="text" placeholder="[email protected]" style="flex:1;
                    padding:6px; border:1px solid #C31D1A; border-radius:4px; font-size:12px;">
                    <button id="btn_save_email" style="padding:4px 12px;
                    background:#C31D1A; color:white; border:none; border-radius:4px; cursor:pointer; font-weight:bold;">保存</button>
                </div>
                <div style="font-size:12px;
                color:#555;">
                    当前认证邮箱:<span id="current_email_display" style="font-weight:bold;
                    color:#d63384; text-decoration:underline;">${getCurrentEmail()}</span>
                </div>
            </div>

            <div id="status_area" style="font-weight:bold;
            color:#000; font-size:14px; margin-bottom: 10px;">等待操作...</div>

            <div style="background:#F0FDF4;
            border-left: 4px solid #28a745; color:#28a745; padding: 8px; font-size:12px; margin-bottom: 12px;
            border-radius: 2px;">
                ✅ 脚本已加载 V21.1 增强版<br>
                哔站用户:chatgpt充值会员 制作此加强版本
            </div>

            <div id="debug_area" style="display:none;"></div>

            <div style="display:flex;
            gap:10px; margin-bottom: 10px;">
                <button id="btn_toggle" style="
                    flex:2;
                    padding: 12px;
                    border: none;
                    border-radius: 15px;
                    font-weight: bold;
                    font-size: 16px;
                    cursor: pointer;
                    display:flex;
                    align-items:center;
                    justify-content:center;
                    gap: 5px;
                    background: #f1f3f5;
                    color: #dc3545;
                    transition: 0.2s;
                ">
                    <span>🚫</span> 无数据
                </button>

                <button id="btn_skip" style="
                    flex:1;
                    padding: 12px;
                    background: #FFC107;
                    color: #000;
                    border: none;
                    border-radius: 15px;
                    font-weight: bold;
                    font-size: 16px;
                    cursor: pointer;
                    display:flex;
                    align-items:center;
                    justify-content:center;
                    gap: 5px;
                ">
                    <span>⏭️</span> 跳过
                </button>
            </div>

            <button id="btn_auto_extract" style="
                width: 100%;
                padding: 12px;
                margin-bottom: 12px;
                cursor: pointer;
                background: #28a745;
                color: white;
                border: none;
                border-radius: 15px;
                font-weight: bold;
                font-size: 15px;
                display:flex;
                align-items:center;
                justify-content:center;
                gap: 8px;
            ">
                <span>🤖</span> 自动提取当前页面数据
            </button>

            <textarea id="bulk_input" placeholder="手动粘贴数据(支持原始文本 或 导出的JSON)..." style="
                width: 100%;
                height: 80px;
                margin-bottom: 10px;
                font-size: 12px;
                border: 1px solid #ccc;
                border-radius: 4px;
                padding: 8px;
                display: block;
                box-sizing: border-box;
                resize: none;
                font-family: monospace;
            "></textarea>

            <div style="display:flex;
            gap:8px;">
                <button id="btn_export" style="flex:1;
                padding: 10px; cursor: pointer; background:#6f42c1; color:white; border:none; border-radius:12px; font-weight:bold; display:flex; justify-content:center; align-items:center;
                gap:4px;">
                    <span>📤</span> 导出
                </button>
                <button id="btn_import" style="flex:1;
                padding: 10px; cursor: pointer; background:#0d6efd; color:white; border:none; border-radius:12px; font-weight:bold; display:flex; justify-content:center; align-items:center;
                gap:4px;">
                    <span>📥</span> 导入
                </button>
                <button id="btn_reset" style="flex:1;
                padding: 10px; cursor: pointer; background:#dc3545; color:white; border:none; border-radius:12px; font-weight:bold; display:flex; justify-content:center; align-items:center;
                gap:4px;">
                    <span>🗑️</span> 清空
                </button>
            </div>
        `;


        document.body.appendChild(div);

        // --- ✅ 添加更新日志的悬停逻辑 ---
        const logTrigger = document.getElementById('update_log_trigger');
        const tooltip = document.getElementById('update_tooltip');
        if (logTrigger && tooltip) {
            logTrigger.addEventListener('mouseenter', () => {
                tooltip.style.display = 'block';
            });
            logTrigger.addEventListener('mouseleave', () => {
                tooltip.style.display = 'none';
            });
        }

        // --- ✅ 最小化/恢复逻辑 ---
        const btnMinimize = document.getElementById('btn_minimize');
        if (btnMinimize) {
            btnMinimize.onclick = () => {
                div.style.display = 'none';
                restoreBtn.style.display = 'flex';
            };
        }
        restoreBtn.onclick = () => {
            restoreBtn.style.display = 'none';
            div.style.display = 'block';
        };

        return div;
    }

    const panel = createPanel();
    const statusArea = document.getElementById('status_area');
    const debugArea = document.getElementById('debug_area');
    const queueCount = document.getElementById('queue_count');
    const inputArea = document.getElementById('bulk_input');
    const btnToggle = document.getElementById('btn_toggle');
    const btnSkip = document.getElementById('btn_skip');
    const btnAutoExtract = document.getElementById('btn_auto_extract');
    const btnExport = document.getElementById('btn_export');
    const btnImport = document.getElementById('btn_import');
    const btnReset = document.getElementById('btn_reset');
    // 邮箱相关元素
    const btnSaveEmail = document.getElementById('btn_save_email');
    const inputCustomEmail = document.getElementById('input_custom_email');
    const currentEmailDisplay = document.getElementById('current_email_display');
    // --- 调试日志 ---
    function log(msg, color = '#333') {
        console.log(msg);
        // debugArea.innerHTML = `<span style="color:${color}">${msg}</span>`;
    }

    // --- 🔥 自动提取页面数据函数 ---
    function autoExtractFromPage() {
        const tableBody = document.querySelector(RESULT_TABLE_SELECTOR);

        // 1. 尝试 CMOHS 页面提取
        const cmohsResult = extractFromCMOHSPage();
        if (cmohsResult && (cmohsResult.list.length > 0 || cmohsResult.skipped > 0)) {
             log(`✅ 从 CMOHS 页面提取 ${cmohsResult.list.length} 条记录`, '#28a745');
             return cmohsResult;
        }

        // 2. 尝试 VLM 页面提取
        if (!tableBody) {
            const vlmResult = extractFromVlmPage();
            if (vlmResult && (vlmResult.list.length > 0 || vlmResult.skipped > 0)) {
                log(`✅ 从 VLM 页面提取 ${vlmResult.list.length} 条记录`, '#28a745');
                return vlmResult;
            }
            alert("❌ 未找到搜索结果表格,也未识别到 VLM/CMOHS 纪念页信息!\n请确保在搜索结果页或 VLM/CMOHS 纪念页。");
            return null;
        }

        // 3. 原始表格提取
        const parsedList = [];
        let skippedCount = 0;
        const rows = Array.from(tableBody.querySelectorAll('tr'));
        let currentPerson = {};
        let recordCount = 0;
        rows.forEach(row => {
            const header = row.querySelector('th.row-header');
            const data = row.querySelector('td.results-info');
            if (!header || !data) return;
            const label = header.textContent.trim().replace(':', '');
            const value = data.textContent.trim();
            if (label === 'Name') {
                if (Object.keys(currentPerson).length > 0) {
                    processAndAddPerson(currentPerson, parsedList);
                    recordCount++;
                }
                currentPerson = { name: value };
            } else {
                currentPerson[label] = value;
            }
        });
        if (Object.keys(currentPerson).length > 0) {
            processAndAddPerson(currentPerson, parsedList);
            recordCount++;
        }
        log(`✅ 从页面提取 ${recordCount} 条记录`, '#28a745');
        return { list: parsedList, skipped: skippedCount };
    }

    function processAndAddPerson(person, list) {
        let lastName = "", firstName = "";
        if (person.name) {
            const parts = person.name.split(',').map(s => s.trim());
            lastName = parts[0] || "";
            firstName = parts[1] || "";
        }
        const branch = getExactBranch(person['Rank & Branch'] || "");
        const dob = person['Date of Birth'] || "";
        const dobParts = dob.split('/');
        const bMonth = dobParts[0] ? MONTH_MAP[dobParts[0]] : "";
        const bDay = dobParts[1] || "";
        const bYear = dobParts[2] || "";
        const dod = person['Date of Death'] || "";
        const dodParts = dod.split('/');
        const dMonth = dodParts[0] ? MONTH_MAP[dodParts[0]] : "";
        const dDay = dodParts[1] || "";
        if (bYear && parseInt(bYear, 10) < MIN_BIRTH_YEAR) {
            log(`⚠️ 跳过 ${lastName} (${bYear} < 1930)`, '#ffc107');
            return;
        }
        if (firstName && lastName && bMonth && bDay && bYear) {
            // 🔥 这里使用了动态获取的邮箱
            list.push([
                FIXED_STATUS,
                branch,
                firstName,
                lastName,
                bMonth,
                bDay,
                bYear,
                dMonth,
                dDay,
                FIXED_DISCHARGE_YEAR,
                getCurrentEmail() // <--- 关键修改
            ]);
            log(`✅ ${firstName} ${lastName} | ${branch}`, '#198754');
        }
    }

    // --- 军种识别 ---
    function getExactBranch(text) {
        const upper = text.toUpperCase();
        if (upper.includes("SPACE FORCE")) return "Space Force";
        if (upper.includes("AIR NATIONAL GUARD") || upper.includes("ANG")) return "Air National Guard";
        if (upper.includes("AIR FORCE RESERVE") || upper.includes("USAFR")) return "Air Force Reserve";
        if (upper.includes("AIR FORCE") || upper.includes("USAF")) return "Air Force";
        if (upper.includes("ARMY NATIONAL GUARD") || upper.includes("ARNG")) return "Army";
        if (upper.includes("ARMY RESERVE") || upper.includes("USAR")) return "Army Reserve";
        if (upper.includes("ARMY") || upper.includes("USA")) return "Army";
        if (upper.includes("COAST GUARD RESERVE")) return "Coast Guard Reserve";
        if (upper.includes("COAST GUARD") || upper.includes("USCG")) return "Coast Guard";
        if (upper.includes("MARINE CORPS FORCE RESERVE")) return "Marine Corps Force Reserve";
        if (upper.includes("MARINE") || upper.includes("USMC")) return "Marine Corps";
        if (upper.includes("NAVY RESERVE") || upper.includes("USNR")) return "Navy Reserve";
        if (upper.includes("NAVY") || upper.includes("USN")) return "Navy";
        return "Army";
    }

// --- ✅ CMOHS 页面数据提取 (V21.2 修复名字匹配版) ---
    function extractFromCMOHSPage() {
        const currentUrl = window.location.href;
        // 1. 检查网址是否匹配
        if (!/cmohs\.org\/recipients/i.test(currentUrl)) return null;

        // --- A. 增强名字提取逻辑 (修复 "Stories of Sacrifice" 问题) ---
        let fullName = "";

        // 3. (兜底方案) 如果还是没找到,从网页标题 (document.title) 提取
        // 网页标题通常是: "Earl D. Plumlee | Medal of Honor Recipient | CMOHS"
        if (!fullName || fullName.includes("Stories of Sacrifice")) {
            const pageTitle = document.title;
            if (pageTitle.includes("|")) {
                fullName = pageTitle.split('|')[0].trim(); // 取竖线前面的部分
            } else {
                fullName = pageTitle;
            }
        }

        // 清理名字中的换行符和多余空格
        fullName = fullName.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();

        if (!fullName) return null;

        // --- B. 处理名字: "LAST, FIRST" 或 "FIRST LAST" ---
        let lastName = "", firstName = "";
        if (fullName.includes(',')) {
            const parts = fullName.split(',').map(s => s.trim());
            lastName = parts[0];
            const firstParts = parts[1] ? parts[1].split(' ') : [];
            firstName = firstParts[0] || "";
        } else {
            const parts = fullName.split(' ');
            if (parts.length > 0) {
                // 处理后缀如 Sr., Jr., III 等
                const lastPart = parts[parts.length - 1];
                if (/^(Jr\.|Sr\.|I{1,3}|IV)$/i.test(lastPart) && parts.length > 1) {
                    lastName = parts[parts.length - 2];
                } else {
                    lastName = lastPart;
                }
                firstName = parts[0];
            }
        }

    // --- C. 增强出生日期提取逻辑 ---
        const bodyText = document.body.innerText;

        // ✅ 修改点 1:针对 Born: 进行匹配
        const dateRegex = /Born:\s*[\s\S]{0,50}?([A-Za-z]{3,}|[0-9]{1,2})[\s\.\/-]+(\d{1,2})[\s,\.\/-]+(\d{4})/i;
        const bornMatch = bodyText.match(dateRegex);

        let bMonth = "", bDay = "", bYear = "";
        if (bornMatch) {
            bMonth = normalizeMonthName(bornMatch[1]);
            bDay = bornMatch[2];
            bYear = bornMatch[3];
        }

        // --- D. 军种提取 ---
        // ✅ 修改点 2:针对 Military Service Branch: 进行提取
        let branch = "Army";
        const branchMatch = bodyText.match(/Military Service Branch:\s*([^\n\r<]+)/i);

        if (branchMatch) {
            branch = getExactBranch(branchMatch[1]);
        } else {
            // 旧的模糊匹配作为备用
            if (/U\.?S\.?\s*Navy/i.test(bodyText)) branch = "Navy";
            else if (/U\.?S\.?\s*Marine/i.test(bodyText)) branch = "Marine Corps";
            else if (/U\.?S\.?\s*Air Force/i.test(bodyText)) branch = "Air Force";
            else if (/U\.?S\.?\s*Coast Guard/i.test(bodyText)) branch = "Coast Guard";
        }

        // --- E. 随机生成 Discharge Date ---
        const dDay = getRandomDay1to25();
        const dMonth = getRandomMonth();

        // 校验年份
        if (bYear && parseInt(bYear, 10) < MIN_BIRTH_YEAR) {
            log(`⚠️ CMOHS 跳过 ${lastName} (${bYear} < ${MIN_BIRTH_YEAR})`, '#ffc107');
            return { list: [], skipped: 1 };
        }

        if (firstName && lastName && bMonth && bDay && bYear) {
             log(`✅ 成功解析: ${firstName} ${lastName}`, '#28a745');
            return {
                list: [[
                    FIXED_STATUS, branch, firstName, lastName,
                    bMonth, bDay, bYear,
                    dMonth, dDay, FIXED_DISCHARGE_YEAR,
                    getCurrentEmail()
                ]],
                skipped: 0
            };
        }

        log(`❌ CMOHS 提取失败: Name=[${fullName}], DOB=[${bMonth}-${bDay}-${bYear}]`, '#dc3545');
        return { list: [], skipped: 1 };
    }

    // --- ✅ VLM 纪念页数据提取 ---
    function extractFromVlmPage() {
        const currentUrl = window.location.href;
        if (!/vlm\.cem\.va\.gov/i.test(currentUrl)) return null;
        const pageText = (document.body && document.body.innerText) ? document.body.innerText : "";
        let fullName = "";
        const h1 = document.querySelector("h1");
        if (h1 && h1.textContent && h1.textContent.trim()) {
            fullName = h1.textContent.trim();
        } else {
            fullName = (document.title || "").trim();
        }
        fullName = fullName.replace(/\s+/g, " ").trim();
        if (!fullName) return null;
        const dateRangeMatch = pageText.match(
            /\b([A-Za-z]{3,9})\s+(\d{1,2}),\s+(\d{4})\s*[-–—−]\s*([A-Za-z]{3,9})\s+(\d{1,2}),\s+(\d{4})\b/
        );
        if (!dateRangeMatch) return null;

        const bMonth = normalizeMonthName(dateRangeMatch[1]);
        const bDay = dateRangeMatch[2];
        const bYear = dateRangeMatch[3];
        const dMonth = normalizeMonthName(dateRangeMatch[4]);
        const dDay = dateRangeMatch[5];

        let branchRaw = "";
        const branchMatch = pageText.match(/\b(U\.?S\.?\s+AIR\s+FORCE|U\.?S\.?\s+ARMY|U\.?S\.?\s+NAVY|U\.?S\.?\s+MARINE\s+CORPS|U\.?S\.?\s+COAST\s+GUARD|SPACE\s+FORCE|AIR\s+FORCE|ARMY|NAVY|MARINE\s+CORPS|COAST\s+GUARD)\b/i);
        if (branchMatch) branchRaw = branchMatch[0];
        const branch = getExactBranch(branchRaw);

        const nameParts = fullName.split(" ").filter(Boolean);
        const lastName = nameParts.length ? nameParts[nameParts.length - 1] : "";
        const firstName = nameParts.length > 1 ?
            nameParts.slice(0, -1).join(" ") : (nameParts[0] || "");
        if (bYear && parseInt(bYear, 10) < MIN_BIRTH_YEAR) {
            log(`⚠️ VLM 跳过 ${fullName} (${bYear} < ${MIN_BIRTH_YEAR})`, '#ffc107');
            return { list: [], skipped: 1 };
        }

        if (firstName && lastName && bMonth && bDay && bYear) {
            return {
                list: [[
                    FIXED_STATUS,
                    branch,
                    firstName,
                    lastName,
                    bMonth,
                    bDay,
                    bYear,
                    dMonth,
                    dDay,
                    FIXED_DISCHARGE_YEAR,
                    getCurrentEmail() // <--- 关键修改
                ]],
                skipped: 0
            };
        }
        return { list: [], skipped: 1 };
    }

    // --- 手动解析数据 (兼容旧版文本格式) ---
    function parseRawData(text) {
        const parsedList = [];
        let skippedCount = 0;
        const blocks = text.split(/Name:\s*\n/g).filter(b => b.trim());
        for (let block of blocks) {
            const nameLine = block.split('\n')[0].trim();
            let lastName = "", firstName = "";
            if (nameLine.includes(',')) {
                const parts = nameLine.split(',').map(s => s.trim());
                lastName = parts[0];
                firstName = parts[1] || "";
            } else {
                lastName = nameLine;
            }
            const branch = getExactBranch(block);
            const dobMatch = block.match(/Date of Birth:\s*\n(\d{2})\/(\d{2})\/(\d{4})/);
            const bMonth = dobMatch ? MONTH_MAP[dobMatch[1]] : "";
            const bDay = dobMatch ? dobMatch[2] : "";
            const bYear = dobMatch ? dobMatch[3] : "";
            const dodMatch = block.match(/Date of Death:\s*\n(\d{2})\/(\d{2})\/(\d{4})/);
            const dMonth = dodMatch ? MONTH_MAP[dodMatch[1]] : "";
            const dDay = dodMatch ? dodMatch[2] : "";
            if (bYear && parseInt(bYear, 10) < MIN_BIRTH_YEAR) {
                skippedCount++;
                continue;
            }
            if (firstName && lastName && bMonth && bDay && bYear) {
                parsedList.push([
                    FIXED_STATUS, branch, firstName, lastName,
                    bMonth, bDay, bYear,
                    dMonth, dDay, FIXED_DISCHARGE_YEAR,
                    getCurrentEmail() // <--- 关键修改
                ]);
            } else {
                skippedCount++;
            }
        }
        return { list: parsedList, skipped: skippedCount };
    }

    // --- 表单填充函数 ---
    function simulateClick(element) {
        if (!element) return;
        element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
        element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
        element.click();
    }
    function setNativeValue(element, value) {
        if (!element) return;
        const lastValue = element.value;
        element.value = value;
        const tracker = element._valueTracker;
        if (tracker) tracker.setValue(lastValue);
        element.dispatchEvent(new Event('input', { bubbles: true }));
        element.dispatchEvent(new Event('change', { bubbles: true }));
        element.dispatchEvent(new Event('blur', { bubbles: true }));
    }
    async function selectDropdown(selector, value, waitTime = 300) {
        const el = document.querySelector(selector);
        if (!el) return false;

        // 1. 模拟用户点击,激活下拉框
        el.focus();
        simulateClick(el);
        await new Promise(r => setTimeout(r, 200));

        // 2. 检查是否为标准 <select> 标签 (SheerID常用)
        if (el.tagName === 'SELECT') {
            let found = false;
            // 遍历所有选项,查找文本匹配的一项
            for (let i = 0; i < el.options.length; i++) {
                const option = el.options[i];
                // 比较显示文本(text) 或 标签(label) 或 值(value)
                if (option.text.trim() === value || option.label === value || option.value === value) {
                    el.selectedIndex = i;
                    // 选中该项
                    el.dispatchEvent(new Event('change', { bubbles: true }));
                    // 触发变更事件
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    found = true;
                    log(`✅ 已选中选项: ${value}`, '#198754');
                    break;
                }
            }
            if (!found) {
                log(`⚠️ 未找到选项: ${value},尝试直接赋值`, '#ffc107');
                setNativeValue(el, value); // 降级处理
            }
        } else {
            // 3. 如果是自定义 div/input 下拉框
            setNativeValue(el, value);
            // 模拟下箭头和回车,尝试触发自动完成
            el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
            await new Promise(r => setTimeout(r, 100));
            el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
        }

        await new Promise(r => setTimeout(r, waitTime));
        return true;
    }

    // --- ⚡ 核心自动化逻辑 ---
    async function runAutomation() {
        const queue = getQueue();
        const isRunning = getIsRunning();
        const currentUrl = window.location.href;

        if (!isRunning) return;
        // 🔥 优先检查错误页面
        if (checkForErrorAndRetry()) {
            return;
        }
        // 🔥 优先检查 claim 页面按钮(持续尝试点击)
        if (checkClaimPageButton()) {
            return;
        }

        let currentTask = getCurrentTask();
        let stage = getFillingStage();
        // 如果在 SheerID 页面且有任务,先等待1秒
        if (currentUrl.includes('services.sheerid.com') && currentTask && stage === 0 && !getInitialFillDelay()) {
            statusArea.innerHTML = `⏳ SheerID 页面加载完成,等待 1 秒...`;
            log('⏳ 延迟 1 秒后开始填写...', '#ffc107');
            await new Promise(r => setTimeout(r, FILL_DELAY));
            setInitialFillDelay(true);
            log('✅ 延迟完成,开始填写表单', '#28a745');
        }

        // 1. 获取新任务
        if (!currentTask && queue.length > 0) {
            currentTask = queue.shift();
            saveQueue(queue);
            setCurrentTask(currentTask);
            setFillingStage(0);
            setInitialFillDelay(false);
            stage = 0;
            log(`🆕 载入: ${currentTask[2]} ${currentTask[3]}`, '#0d6efd');
            // 如果在 SheerID 页面,立即延迟
            if (currentUrl.includes('services.sheerid.com')) {
                statusArea.innerHTML = `⏳ 等待1秒后开始填写: <span style="color:#0d6efd">${currentTask[2]} ${currentTask[3]}</span>`;
                await new Promise(r => setTimeout(r, FILL_DELAY));
                setInitialFillDelay(true);
            }
        }

        // 2. 完成
        if (!currentTask) {
            statusArea.innerHTML = "✅ 所有数据已处理完毕";
            statusArea.style.color = "green";
            log('🎉 全部完成!', '#198754');
            setIsRunning(false);
            return;
        }

        statusArea.innerHTML = `处理中 (${stage + 1}/4): <span style="color:#0d6efd">${currentTask[2]} ${currentTask[3]}</span>`;
        const statusEl = document.querySelector(FIELD_MAP.status);
        const nameEl = document.querySelector(FIELD_MAP.firstName);

        // ===================== 🔴 新增代码开始 =====================
        // 只有在 SheerID 页面且处于第0步时,才检测这段文字
        if (currentUrl.includes('services.sheerid.com') && stage === 0) {
            const bodyText = document.body.innerText;
            // 如果页面不包含指定的文字 "Unlock this Military-Only Offer"
            if (!bodyText.includes("Unlock this Military-Only Offer")) {
                log('⏳ 等待页面出现 "Unlock this Military-Only Offer"...', '#ffc107');
                statusArea.innerHTML = "⏳ 等待识别关键文本...";
                return; // ⛔️ 强制结束本次循环,不往下执行,直到文字出现
            }
            log('✅ 已识别到关键文本,继续执行...', '#198754');
        }

      try {
            // ✅ 阶段 0: 设置 Status (身份)
            if (stage === 0) {
                // 修改:使用 currentTask[0] (提取的数据) 替代硬编码字符串
                // 确保数据里有值,如果没有则使用默认值
                const statusValue = currentTask[0] ||
                "Military Veteran or Retiree";
                log(`📝 1. 设置 Status: ${statusValue}`, '#0d6efd');
                if (statusEl) {
                    // 使用改进后的 selectDropdown,它会去列表里找匹配的字
                    await selectDropdown(FIELD_MAP.status, statusValue, 600);
                } else {
                    log('⚠️ 未找到 Status 下拉框,但仍继续流程', '#ffc107');
                }
                setFillingStage(1);
                // -> 去选 Branch
                return;
            }

            // ✅ 阶段 1: 设置 Branch (军种)
            if (stage === 1) {
                // 修改:明确使用 currentTask[1]
                const branchValue = currentTask[1];
                log(`📝 2. 设置 Branch: ${branchValue}`, '#0d6efd');

                // 这里增加等待,确保上一步的Status切换动画完成,选项加载出来
                await selectDropdown(FIELD_MAP.branch, branchValue, 500);
                setFillingStage(2); // -> 去填姓名
                return;
            }

            // ✅ 阶段 2: 填写姓名、日期、邮箱 (原阶段1的内容)
            if (stage === 2 && nameEl) {
                log('📝 3. 填充详细信息...', '#0d6efd');
                // 注意:这里删掉了原来的 selectDropdown(branch...),因为上面已经做过了
                setNativeValue(document.querySelector(FIELD_MAP.firstName), currentTask[2]);
                setNativeValue(document.querySelector(FIELD_MAP.lastName), currentTask[3]);
                await selectDropdown(FIELD_MAP.bMonth, currentTask[4], 150);
                setNativeValue(document.querySelector(FIELD_MAP.bDay), currentTask[5]);
                setNativeValue(document.querySelector(FIELD_MAP.bYear), currentTask[6]);
                await selectDropdown(FIELD_MAP.dMonth, currentTask[7], 150);
                setNativeValue(document.querySelector(FIELD_MAP.dDay), currentTask[8]);
                setNativeValue(document.querySelector(FIELD_MAP.dYear), currentTask[9]);
                setNativeValue(document.querySelector(FIELD_MAP.email), currentTask[10]);
                setFillingStage(3); // -> 去提交
                return;
            }

            // ✅ 阶段 3: 提交 (原阶段2)
            if (stage === 3) {
                const submitBtn = document.querySelector(SUBMIT_BTN_SELECTOR);
                if (submitBtn) {
                    const isDisabled = submitBtn.getAttribute('aria-disabled') === 'true' ||
                                     submitBtn.disabled ||
                                     submitBtn.classList.contains('disabled');

                    if (!isDisabled) {
                        // 按钮可用,正常提交
                        log('🚀 提交表单...', '#198754');
                        setSubmitState(true);
                        submitBtn.click();
                        setFillingStage(0); // 提交成功,重置准备下一个人
                        setInitialFillDelay(false);
                    } else {
                        // 🔴 核心修改点:按钮未激活,回退到 Status (Stage 0) 重新填写
                        log('⚠️ 提交按钮未激活,正在重新开始填写 (回到 Status)...', '#ff6b6b');
                        setFillingStage(0); // 强制重置步骤为 0
                    }
                }
            }
        } catch (e) {
            log(`❌ 错误: ${e.message}`, '#dc3545');
        }
    }

    // --- UI 更新 (✅ 适配新UI的按钮样式) ---
    function updateUI() {
        const queue = getQueue();
        const isRunning = getIsRunning();
        queueCount.innerText = queue.length;
        if (isRunning) {
            btnToggle.innerHTML = "<span>⏸️</span> 运行中";
            btnToggle.style.backgroundColor = "#28a745"; // 绿色
            btnToggle.style.color = "#fff";
        } else {
            if (queue.length > 0) {
                btnToggle.innerHTML = "<span>▶️</span> 启动";
                btnToggle.style.backgroundColor = "#0d6efd"; // 蓝色
                btnToggle.style.color = "#fff";
                statusArea.innerText = "⏸️ 已暂停";
            } else {
                // 默认状态:无数据 (灰色背景,红色文字和图标,仿图片)
                btnToggle.innerHTML = "<span>🚫</span> 无数据";
                btnToggle.style.backgroundColor = "#f1f3f5";
                btnToggle.style.color = "#dc3545";
            }
        }
    }

    // --- 按钮事件 ---
    btnToggle.onclick = () => {
        const queue = getQueue();
        if (queue.length === 0 && !getCurrentTask()) {
            alert("请先提取或导入数据!");
            return;
        }
        setIsRunning(!getIsRunning());
    };
    btnSkip.onclick = () => {
        const current = getCurrentTask();
        if (!current && getQueue().length === 0) {
            alert("没有任务可以跳过");
            return;
        }
        setCurrentTask(null);
        setSubmitState(false);
        setFillingStage(0);
        setWaitingForRetry(false);
        setClaimPageAttempts(0);
        setInitialFillDelay(false);
        setLastClickedUrl('');
        if (!getIsRunning()) {
            setIsRunning(true);
        }
        statusArea.innerHTML = "⏭️ 已跳过!正在载入下一位...";
        statusArea.style.color = "orange";
        setTimeout(runAutomation, 100);
    };
    btnAutoExtract.onclick = () => {
        const result = autoExtractFromPage();
        if (!result) return;
        const newData = result.list;
        const skipped = result.skipped;
        if (newData.length === 0) {
            alert("未提取到有效数据");
            return;
        }
        const currentQueue = getQueue();
        saveQueue(currentQueue.concat(newData));
        let msg = `✅ 成功提取 ${newData.length} 人`;
        if (skipped > 0) msg += `\n🚫 跳过 ${skipped} 人`;
        alert(msg);
        log(`✅ 提取完成: ${newData.length} 人`, '#28a745');
    };

    // --- ✅ 新增:保存邮箱事件 ---
    btnSaveEmail.onclick = () => {
        const val = inputCustomEmail.value.trim();
        if (val) {
            setNewEmail(val);
            currentEmailDisplay.innerText = val;
            alert(`✅ 邮箱已锁定为:\n${val}\n\n注意:此设置仅对【新提取】的数据生效,如果列表里已有旧数据,建议【清空】后重新提取。`);
        } else {
            alert("❌ 请输入有效的邮箱地址!");
        }
    };

    // --- ✅ 新增:导出数据功能 ---
    btnExport.onclick = () => {
        const queue = getQueue();
        if (queue.length === 0) {
            alert("当前队列为空,没有数据可以导出!\n请先提取数据后再试。");
            return;
        }
        // 将数据转换为 JSON 字符串
        const jsonStr = JSON.stringify(queue);
        // 复制到剪贴板
        navigator.clipboard.writeText(jsonStr).then(() => {
            alert(`✅ 已成功复制 ${queue.length} 条数据到剪贴板!\n\n使用方法:\n1. 发送给朋友\n2. 朋友复制内容\n3. 粘贴到插件输入框\n4. 点击【📥 导入】即可`);
        }).catch(err => {
            alert("❌ 复制失败,请手动复制控制台输出 (F12)");
            console.log("手动复制数据:", jsonStr);
        });
    };

    // --- ✅ 修改:导入数据功能 (支持文本 + JSON) ---
    btnImport.onclick = () => {
        const text = inputArea.value.trim();
        if (!text) return;

        try {
            let newData = [];
            let skipped = 0;

            // 1. 尝试检测是否为 JSON 格式 (导出格式)
            if (text.startsWith('[') && text.endsWith(']')) {
                try {
                    newData = JSON.parse(text);
                    if (!Array.isArray(newData)) throw new Error("JSON 格式不正确");
                    log(`✅ 检测到 JSON 数据包,直接载入`, '#6f42c1');
                } catch (jsonErr) {
                    alert("JSON 解析失败,请检查数据完整性");
                    return;
                }
            } else {
                // 2. 如果不是 JSON,尝试用旧的文本解析逻辑
                const result = parseRawData(text);
                newData = result.list;
                skipped = result.skipped;
            }

            if (newData.length === 0 && skipped === 0) {
                alert("无有效数据");
                return;
            }
            const currentQueue = getQueue();
            saveQueue(currentQueue.concat(newData));
            inputArea.value = "";
            let msg = `✅ 成功导入 ${newData.length} 人`;
            if (skipped > 0) msg += `\n🚫 跳过 ${skipped} 人`;
            alert(msg);
        } catch (e) {
            alert("解析错误: " + e.message);
        }
    };

    btnReset.onclick = () => {
        if(confirm("确定清空全部数据?")) {
            saveQueue([]);
            setCurrentTask(null);
            setSubmitState(false);
            setFillingStage(0);
            setIsRunning(false);
            setWaitingForRetry(false);
            setClaimPageAttempts(0);
            setInitialFillDelay(false);
            setLastClickedUrl('');
            log('🗑️ 已清空所有数据', '#dc3545');
            location.reload();
        }
    };
    // --- 初始化 ---
    initLogic();
    updateUI();
    function loop() {
        runAutomation();
        setTimeout(loop, 1500);
    }
    setTimeout(loop, 1000);
    log('✅ 脚本已加载 V21.1 增强版<br>哔站用户:chatgpt充值会员 制作此加强版本', '#198754');
})();