hhanclub自动抽奖增强版

自动执行hhanclub抽奖,支持数据持久化和统计分析

// ==UserScript==
// @name         hhanclub自动抽奖增强版
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  自动执行hhanclub抽奖,支持数据持久化和统计分析
// @author       Timi
// @match        https://hhanclub.top/lucky.php
// @grant        none
// @icon         https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAKEE2ie35c8Z7uFMM3o7kGs8JLlxdoAA-EZAAKUwPlULub89nlMf6Y2BA.ico
// @run-at       document-ready
// @license      MIT

// ==/UserScript==

(function () {
    'use strict';

    // 抽奖API配置
    const LOTTERY_API = 'https://hhanclub.top/plugin/lucky-draw';

    // 存储键名
    const STORAGE_KEY = 'hhanclub_lottery_stats';

    // 全局变量
    let singleCost = 2000; // 默认单次消耗
    let currentViewMode = 'current'; // current | total

    // 主控制逻辑变量
    let lotteryInterval = null;
    let consecutiveErrors = 0;
    let dynamicInterval = 7000;
    let currentRoundStartCount = 0; // 全局变量存储本轮起始计数

    // 统计数据变量
    let currentStats = {
        lotteryCount: 0,
        winCount: 0,
        cost: 0,
        beansWon: 0,
        invites: 0,
        rainbowDays: 0,
        vipDays: 0,
        makeupCards: 0,
        uploadGB: 0,
        prizeStats: {}
    };

    let totalStats = {
        totalLotteryCount: 0,
        totalWinCount: 0,
        totalCost: 0,
        totalBeansWon: 0,
        totalInvites: 0,
        totalRainbowDays: 0,
        totalVipDays: 0,
        totalMakeupCards: 0,
        totalUploadGB: 0,
        totalPrizeStats: {}
    };

    // 创建控制面板
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.id = 'lottery-control-panel';
        panel.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            width: 320px;
            min-width: 280px;
            max-width: 500px;
            min-height: 200px;
            background: #fff;
            border: 2px solid #007bff;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            z-index: 10000;
            font-family: Arial, sans-serif;
            padding: 15px;
            resize: both;
            overflow: auto;
        `;

        panel.innerHTML = `
            <div style="text-align: center; margin-bottom: 15px;">
                <h3 style="margin: 0; color: #007bff;">🎲 自动抽奖工具</h3>
            </div>
            <div style="margin-bottom: 10px; padding: 8px; background: #f8f9fa; border-radius: 4px; font-size: 12px;">
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <span>💰 憨豆余额: <span id="bean-balance" style="color: #28a745; font-weight: bold;">检测中...</span></span>
                </div>
                <div style="margin-top: 5px; display: flex; justify-content: space-between; align-items: center;">
                    <span>🎯 单次消耗: <span id="single-cost" style="color: #dc3545;">2000</span></span>
                    <span>📊 最多可抽: <span id="max-possible" style="color: #007bff; font-weight: bold;">-</span> 次</span>
                </div>
            </div>
            <div style="margin-bottom: 10px;">
                <label>抽奖间隔 (秒):</label>
                <input type="number" id="lottery-interval" value="7" min="3" max="300" style="width: 60px; margin-left: 10px;">
                <span style="font-size: 11px; color: #666; margin-left: 5px;">实际: <span id="current-interval">7</span>s</span>
            </div>
            <div style="margin-bottom: 10px;">
                <label>最大抽奖次数:</label>
                <input type="number" id="max-lottery-count" value="10" min="1" max="1000" style="width: 60px; margin-left: 10px;">
                <button id="set-max-possible" style="background: #17a2b8; color: white; border: none; padding: 4px 8px; border-radius: 3px; font-size: 11px; margin-left: 5px; cursor: pointer;">设为最大</button>
            </div>
            <div style="text-align: center; margin-bottom: 15px;">
                <button id="start-lottery" style="background: #28a745; color: white; border: none; padding: 8px 15px; border-radius: 4px; margin-right: 5px; cursor: pointer;">开始抽奖</button>
                <button id="stop-lottery" style="background: #dc3545; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer;" disabled>停止抽奖</button>
            </div>
            <div style="border-top: 1px solid #eee; padding-top: 10px;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
                    <div style="font-size: 12px; color: #666;">
                        状态: <span id="lottery-status" style="color: #28a745;">等待开始</span>
                    </div>
                    <select id="view-mode" style="padding: 2px 5px; font-size: 11px; border: 1px solid #ccc; border-radius: 3px;">
                        <option value="current">本次数据</option>
                        <option value="total">总计数据</option>
                    </select>
                </div>
                <div style="font-size: 12px; color: #666; margin-bottom: 5px;">
                    已抽奖: <span id="lottery-count">0</span> 次 | 中奖: <span id="win-count">0</span> 次 | 消耗: <span id="cost-beans">0</span> 憨豆
                </div>
                <div style="font-size: 12px; margin-bottom: 8px;">
                    <span style="color: #666;">盈亏: </span>
                    <span id="profit-loss" style="font-weight: bold;">-</span> 憨豆
                    <span style="color: #666; margin-left: 10px;">盈亏率: </span>
                    <span id="profit-rate" style="font-weight: bold;">-</span>
                </div>
                <div id="prize-stats" style="font-size: 11px; color: #666; margin-top: 5px; display: none; position: relative;">
                    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
                        <strong>🎁 奖品统计</strong>
                        <button id="toggle-detailed-stats" style="background: #6c757d; color: white; border: none; padding: 2px 6px; border-radius: 2px; font-size: 10px; cursor: pointer;">详细</button>
                    </div>
                    <div id="summary-stats" style="display: grid; grid-template-columns: 1fr 1fr; gap: 3px; margin-bottom: 5px; font-size: 10px;">
                        <div>💰 获得憨豆: <span id="total-beans-won" style="color: #28a745; font-weight: bold;">0</span></div>
                        <div>📧 邀请数: <span id="total-invites" style="color: #007bff; font-weight: bold;">0</span></div>
                        <div>🌈 彩虹ID: <span id="total-rainbow-days" style="color: #e83e8c; font-weight: bold;">0</span>天</div>
                        <div>🎫 VIP: <span id="total-vip-days" style="color: #fd7e14; font-weight: bold;">0</span>天</div>
                        <div>📝 补签卡: <span id="total-makeup-cards" style="color: #6f42c1; font-weight: bold;">0</span>个</div>
                        <div>⬆️ 上传量: <span id="total-upload" style="color: #20c997; font-weight: bold;">0</span>GB</div>
                    </div>
                    <div id="detailed-prize-list" style="max-height: 120px; overflow-y: auto; margin-top: 3px; border: 1px solid #ddd; border-radius: 3px; padding: 3px; resize: both; min-height: 40px; display: none;"></div>
                </div>
                <div style="text-align: center; margin-bottom: 8px; display: flex; justify-content: center; gap: 10px;">
                    <button id="reset-current-data"
                        style="background: #ffc107; color: #212529; border: none; padding: 4px 10px; border-radius: 3px; font-size: 11px; cursor: pointer;">
                        重置本次数据
                    </button>
                    <button id="clear-total-data"
                        style="background: #6c757d; color: white; border: none; padding: 4px 10px; border-radius: 3px; font-size: 11px; cursor: pointer;">
                        清空历史数据
                    </button>
                </div>
                <div id="lottery-log" style="max-height: 150px; overflow-y: auto; background: #f8f9fa; padding: 5px; border-radius: 4px; font-size: 11px; margin-top: 10px; display: none;">
                </div>
            </div>
        `;

        document.body.appendChild(panel);
        console.log('控制面板已添加:', document.getElementById('lottery-control-panel'));
        return panel;
    }

    // 动态获取单次消耗憨豆
    function getSingleCost() {
        const costElement = document.querySelector('.use-bean');
        if (costElement) {
            const match = costElement.textContent.match(/(\d+)/);
            if (match) {
                singleCost = parseInt(match[1]);
                document.getElementById('single-cost').textContent = singleCost;
                console.log('动态获取单次消耗:', singleCost);
                return singleCost;
            }
        }
        console.log('使用默认单次消耗:', singleCost);
        return singleCost;
    }

    // 获取憨豆余额
    function getBeanBalance() {
        const beanElement = document.querySelector('.bean-number');
        if (!beanElement) {
            console.error('未找到憨豆余额元素 (.bean-number)');
            addLog('❌ 无法获取憨豆余额', 'error');
            return 0;
        }
        const balance = parseFloat(beanElement.textContent.trim());
        return isNaN(balance) ? 0 : balance;
    }

    // 更新余额显示
    function updateBalanceDisplay() {
        const balance = getBeanBalance();
        const cost = getSingleCost();
        const maxPossible = Math.floor(balance / cost);

        const beanBalanceElement = document.getElementById('bean-balance');
        const maxPossibleElement = document.getElementById('max-possible');
        const startButton = document.getElementById('start-lottery');

        if (beanBalanceElement && maxPossibleElement && startButton) {
            beanBalanceElement.textContent = balance.toLocaleString();
            maxPossibleElement.textContent = maxPossible.toLocaleString();

            if (balance < cost) {
                startButton.disabled = true;
                startButton.textContent = '余额不足';
                startButton.style.background = '#6c757d';
            } else {
                startButton.disabled = false;
                startButton.textContent = '开始抽奖';
                startButton.style.background = '#28a745';
            }
        } else {
            console.error('余额显示元素未找到');
            addLog('❌ 余额显示元素未加载', 'error');
        }

        return maxPossible;
    }

    // 数据持久化相关
    function saveStatsData(data) {
        try {
            localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
        } catch (error) {
            console.error('保存数据失败:', error);
        }
    }

    function loadStatsData() {
        try {
            const data = localStorage.getItem(STORAGE_KEY);
            if (data) {
                return JSON.parse(data);
            }
        } catch (error) {
            console.error('加载数据失败:', error);
        }
        return {
            totalLotteryCount: 0,
            totalWinCount: 0,
            totalCost: 0,
            totalBeansWon: 0,
            totalInvites: 0,
            totalRainbowDays: 0,
            totalVipDays: 0,
            totalMakeupCards: 0,
            totalUploadGB: 0,
            totalPrizeStats: {}
        };
    }

    function clearTotalData() {
        if (confirm('确定要清空所有历史数据吗?此操作无法撤销!')) {
            localStorage.removeItem(STORAGE_KEY);
            totalStats = loadStatsData();
            updateDisplay();
            addLog('✅ 历史数据已清空', 'success');
        }
    }

    // 解码Unicode字符串
    function decodeUnicode(str) {
        try {
            return str.replace(/\\u[\dA-F]{4}/gi, function (match) {
                return String.fromCharCode(parseInt(match.replace(/\\u/g, ''), 16));
            });
        } catch (error) {
            return str;
        }
    }

    // 执行单次抽奖
    async function performLottery() {
        try {
            const response = await fetch(LOTTERY_API, {
                method: 'POST',
                headers: {
                    'accept': '*/*',
                    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
                    'content-length': '0',
                    'origin': 'https://hhanclub.top',
                    'priority': 'u=1, i',
                    'referer': 'https://hhanclub.top/lucky.php',
                    'sec-ch-ua': '"Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"',
                    'sec-ch-ua-arch': 'x86',
                    'sec-ch-ua-bitness': '64',
                    'sec-ch-ua-mobile': '?0',
                    'sec-ch-ua-platform': 'Windows',
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-origin',
                    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0',
                    'x-requested-with': 'XMLHttpRequest'
                }
            });

            const resultText = await response.text();

            let parsedResult = null;
            try {
                parsedResult = JSON.parse(resultText);
            } catch (e) {
                // 如果不是JSON格式,保持原文本
            }

            return {
                success: response.ok,
                status: response.status,
                data: resultText,
                parsed: parsedResult
            };
        } catch (error) {
            return {
                success: false,
                error: error.message
            };
        }
    }

    // 添加日志
    function addLog(message, type = 'info') {
        const logContainer = document.getElementById('lottery-log');
        if (!logContainer) {
            console.error('日志容器未找到');
            return;
        }
        logContainer.style.display = 'block';

        const timestamp = new Date().toLocaleTimeString();
        const logEntry = document.createElement('div');

        let color = '#666';
        switch (type) {
            case 'error': color = '#dc3545'; break;
            case 'success': color = '#28a745'; break;
            case 'warning': color = '#ffc107'; break;
            case 'info':
            default: color = '#666'; break;
        }

        logEntry.style.cssText = `margin-bottom: 3px; color: ${color};`;
        logEntry.textContent = `[${timestamp}] ${message}`;

        logContainer.appendChild(logEntry);
        logContainer.scrollTop = logContainer.scrollHeight;

        if (logContainer.children.length > 20) {
            logContainer.removeChild(logContainer.firstChild);
        }
    }

    // 解析奖品内容
    function parsePrizeText(prizeText) {
        const result = {
            type: 'unknown',
            name: prizeText,
            value: 0,
            unit: ''
        };

        if (prizeText.includes('魔力') || prizeText.includes('憨豆')) {
            const match = prizeText.match(/(\d+)/);
            if (match) {
                result.type = 'beans';
                result.value = parseInt(match[1]);
                result.name = '憨豆';
                result.unit = '';
            }
        }
        else if (prizeText.includes('邀请')) {
            const match = prizeText.match(/(\d+)/);
            if (match) {
                result.type = 'invite';
                result.value = parseInt(match[1]);
                result.name = '邀请';
                result.unit = '';
            }
        }
        else if (prizeText.includes('彩虹')) {
            const match = prizeText.match(/(\d+)/);
            if (match) {
                result.type = 'rainbow';
                result.value = parseInt(match[1]);
                result.name = '彩虹ID';
                result.unit = '天';
            }
        }
        else if (prizeText.includes('VIP')) {
            const match = prizeText.match(/(\d+)/);
            if (match) {
                result.type = 'vip';
                result.value = parseInt(match[1]);
                result.name = 'VIP';
                result.unit = '天';
            }
        }
        else if (prizeText.includes('补签卡')) {
            const match = prizeText.match(/(\d+)/);
            if (match) {
                result.type = 'makeup';
                result.value = parseInt(match[1]);
                result.name = '补签卡';
                result.unit = '个';
            }
        }
        else if (prizeText.includes('上传量')) {
            const match = prizeText.match(/(\d+(?:\.\d+)?)\s*GB/);
            if (match) {
                result.type = 'upload';
                result.value = parseFloat(match[1]);
                result.name = '上传量';
                result.unit = 'GB';
            }
        }

        return result;
    }

    // 更新显示
    function updateDisplay() {
        const viewMode = document.getElementById('view-mode')?.value || 'current';

        let displayData;
        if (viewMode === 'current') {
            displayData = {
                lotteryCount: currentStats.lotteryCount,
                winCount: currentStats.winCount,
                cost: currentStats.cost,
                beansWon: currentStats.beansWon,
                invites: currentStats.invites,
                rainbowDays: currentStats.rainbowDays,
                vipDays: currentStats.vipDays,
                makeupCards: currentStats.makeupCards,
                uploadGB: currentStats.uploadGB,
                prizeStats: currentStats.prizeStats
            };
        } else {
            displayData = {
                lotteryCount: totalStats.totalLotteryCount,
                winCount: totalStats.totalWinCount,
                cost: totalStats.totalCost,
                beansWon: totalStats.totalBeansWon,
                invites: totalStats.totalInvites,
                rainbowDays: totalStats.totalRainbowDays,
                vipDays: totalStats.totalVipDays,
                makeupCards: totalStats.totalMakeupCards,
                uploadGB: totalStats.totalUploadGB,
                prizeStats: totalStats.totalPrizeStats
            };
        }

        // 更新基本统计
        document.getElementById('lottery-count').textContent = displayData.lotteryCount;
        document.getElementById('win-count').textContent = displayData.winCount;
        document.getElementById('cost-beans').textContent = displayData.cost.toLocaleString();

        // 更新奖品统计
        document.getElementById('total-beans-won').textContent = displayData.beansWon.toLocaleString();
        document.getElementById('total-invites').textContent = displayData.invites.toLocaleString();
        document.getElementById('total-rainbow-days').textContent = displayData.rainbowDays.toLocaleString();
        document.getElementById('total-vip-days').textContent = displayData.vipDays.toLocaleString();
        document.getElementById('total-makeup-cards').textContent = displayData.makeupCards.toLocaleString();
        document.getElementById('total-upload').textContent = displayData.uploadGB.toLocaleString();

        // 更新盈亏
        updateProfitLoss(displayData);

        // 更新详细奖品列表
        updateDetailedPrizeList(displayData);
    }

    // 更新盈亏计算
    function updateProfitLoss(data) {
        const profit = data.beansWon - data.cost;
        const profitElement = document.getElementById('profit-loss');
        const rateElement = document.getElementById('profit-rate');

        if (profitElement && rateElement) {
            profitElement.textContent = profit.toLocaleString();
            if (profit > 0) {
                profitElement.style.color = '#28a745';
                profitElement.textContent = '+' + profit.toLocaleString();
            } else if (profit < 0) {
                profitElement.style.color = '#dc3545';
            } else {
                profitElement.style.color = '#666';
            }

            if (data.cost > 0) {
                const rate = (profit / data.cost * 100).toFixed(1);
                rateElement.textContent = rate + '%';
                if (parseFloat(rate) > 0) {
                    rateElement.style.color = '#28a745';
                } else if (parseFloat(rate) < 0) {
                    rateElement.style.color = '#dc3545';
                } else {
                    rateElement.style.color = '#666';
                }
            } else {
                rateElement.textContent = '-';
                rateElement.style.color = '#666';
            }
        }
    }

    // 更新详细奖品列表
    function updateDetailedPrizeList(data) {
        const prizeList = document.getElementById('detailed-prize-list');
        if (!prizeList) return;

        prizeList.innerHTML = '';

        // 计算总中奖次数用于百分比
        const totalWins = Object.values(data.prizeStats).reduce((sum, count) => sum + count, 0);

        if (totalWins === 0) {
            prizeList.innerHTML = '<div style="text-align: center; color: #999; padding: 10px;">暂无奖品数据</div>';
            return;
        }

        Object.entries(data.prizeStats)
            .sort((a, b) => b[1] - a[1])
            .forEach(([prize, count]) => {
                const percentage = ((count / totalWins) * 100).toFixed(1);
                const item = document.createElement('div');
                item.innerHTML = `
                    <div style="display: flex; justify-content: space-between; align-items: center;">
                        <span style="flex: 1; text-align: left;">${prize}</span>
                        <span style="color: #007bff; margin: 0 5px;">${count}次</span>
                        <span style="color: #28a745; font-size: 9px;">${percentage}%</span>
                    </div>
                `;
                item.style.cssText = 'margin: 1px 0; padding: 2px 3px; background: #e9ecef; border-radius: 2px; font-size: 10px;';
                prizeList.appendChild(item);
            });
    }

    // 更新奖品统计
    function updatePrizeStats(prizeText) {
        // 更新当前统计
        currentStats.winCount++;
        const prize = parsePrizeText(prizeText);

        switch (prize.type) {
            case 'beans':
                currentStats.beansWon += prize.value;
                totalStats.totalBeansWon += prize.value;
                break;
            case 'invite':
                currentStats.invites += prize.value;
                totalStats.totalInvites += prize.value;
                break;
            case 'rainbow':
                currentStats.rainbowDays += prize.value;
                totalStats.totalRainbowDays += prize.value;
                break;
            case 'vip':
                currentStats.vipDays += prize.value;
                totalStats.totalVipDays += prize.value;
                break;
            case 'makeup':
                currentStats.makeupCards += prize.value;
                totalStats.totalMakeupCards += prize.value;
                break;
            case 'upload':
                currentStats.uploadGB += prize.value;
                totalStats.totalUploadGB += prize.value;
                break;
        }

        // 更新奖品统计
        if (currentStats.prizeStats[prizeText]) {
            currentStats.prizeStats[prizeText]++;
        } else {
            currentStats.prizeStats[prizeText] = 1;
        }

        if (totalStats.totalPrizeStats[prizeText]) {
            totalStats.totalPrizeStats[prizeText]++;
        } else {
            totalStats.totalPrizeStats[prizeText] = 1;
        }

        // 更新总计
        totalStats.totalWinCount++;

        // 保存数据
        saveStatsData(totalStats);

        updateDisplay();
        document.getElementById('prize-stats').style.display = 'block';
    }

    // 更新消耗统计
    function updateCostStats() {
        currentStats.cost += singleCost;
        currentStats.lotteryCount++;

        totalStats.totalCost += singleCost;
        totalStats.totalLotteryCount++;

        saveStatsData(totalStats);
        updateDisplay();
        setTimeout(updateBalanceDisplay, 100);
    }

    // 执行单次抽奖
    async function performSingleLottery(maxCount) {
        // 计算本轮已抽次数
        const roundCount = currentStats.lotteryCount - currentRoundStartCount;

        if (roundCount >= maxCount) {
            stopLottery();
            addLog(`🎯 本轮达到最大抽奖次数 (${maxCount}),自动停止`, 'info');
            addLog(`📊 会话总计: ${currentStats.lotteryCount} 次抽奖,${currentStats.winCount} 次中奖`, 'info');
            return;
        }

        addLog(`🎯 执行第 ${currentStats.lotteryCount + 1} 次抽奖 (本轮第 ${roundCount + 1}/${maxCount}) (间隔: ${dynamicInterval / 1000}s)`, 'info');

        const result = await performLottery();

        if (result.success && result.parsed) {
            const data = result.parsed;

            if (data.ret === 0) {
                consecutiveErrors = 0;
                dynamicInterval = parseInt(document.getElementById('lottery-interval')?.value || 7) * 1000;
                document.getElementById('current-interval').textContent = dynamicInterval / 1000;

                if (lotteryInterval) {
                    clearInterval(lotteryInterval);
                    lotteryInterval = setInterval(() => {
                        performSingleLottery(maxCount);
                    }, dynamicInterval);
                }

                const prizeText = decodeUnicode(data.data.prize_text || '未知奖品');
                const recordId = data.data.winning_record_id || '';

                addLog(`🎉 恭喜!抽中了: ${prizeText} (记录ID: ${recordId})`, 'success');

                updatePrizeStats(prizeText);
                updateCostStats();

            } else if (data.ret === -1) {
                const errorMsg = decodeUnicode(data.msg || '未知错误');

                if (errorMsg.includes('重复点击') || errorMsg.includes('请稍后')) {
                    consecutiveErrors++;
                    if (consecutiveErrors >= 3) {
                        dynamicInterval = Math.min(dynamicInterval * 1.5, 30000);
                        document.getElementById('current-interval').textContent = Math.round(dynamicInterval / 1000);
                        addLog(`⚠️ ${errorMsg},已调整间隔至 ${Math.round(dynamicInterval / 1000)} 秒`, 'warning');

                        if (lotteryInterval) {
                            clearInterval(lotteryInterval);
                            lotteryInterval = setInterval(() => {
                                performSingleLottery(maxCount);
                            }, dynamicInterval);
                        }
                    } else {
                        addLog(`⚠️ ${errorMsg},将在下次继续尝试 (${consecutiveErrors}/3)`, 'warning');
                    }
                } else if (errorMsg.includes('次数') || errorMsg.includes('用完') || errorMsg.includes('余额不足')) {
                    addLog(`❌ ${errorMsg},已停止抽奖`, 'error');
                    stopLottery();
                    return;
                } else {
                    consecutiveErrors++;
                    addLog(`❌ ${errorMsg} (${consecutiveErrors}/3)`, 'error');
                    updateCostStats();
                }
            } else {
                consecutiveErrors++;
                addLog(`⚠️ 未知响应状态: ret=${data.ret}, msg=${decodeUnicode(data.msg || '')}`, 'warning');
                updateCostStats();
            }
        } else if (result.success) {
            addLog(`✅ 抽奖完成,响应: ${result.data.substring(0, 100)}...`, 'success');
            consecutiveErrors = 0;
            updateCostStats();
        } else {
            consecutiveErrors++;
            addLog(`❌ 请求失败: ${result.error || result.status} (${consecutiveErrors}/3)`, 'error');
            if (consecutiveErrors < 3) {
                updateCostStats();
            }
        }
    }

    function stopLottery() {
        if (lotteryInterval) {
            clearInterval(lotteryInterval);
            lotteryInterval = null;
        }

        document.getElementById('lottery-status').textContent = '已停止';
        document.getElementById('lottery-status').style.color = '#dc3545';
        document.getElementById('start-lottery').disabled = false;
        document.getElementById('stop-lottery').disabled = true;

        const baseInterval = parseInt(document.getElementById('lottery-interval')?.value || 7);
        document.getElementById('current-interval').textContent = baseInterval;

        addLog('🛑 抽奖已停止', 'info');
    }

    function startLottery() {
        const intervalInput = document.getElementById('lottery-interval');
        const maxCountInput = document.getElementById('max-lottery-count');

        if (!intervalInput || !maxCountInput) {
            addLog('❌ 控制面板未正确加载,无法开始抽奖', 'error');
            console.error('缺少必要的输入元素:', { intervalInput, maxCountInput });
            return;
        }

        const maxCount = parseInt(maxCountInput.value) || 10;
        dynamicInterval = parseInt(intervalInput.value) * 1000 || 7000;

        // 不再重置当前统计 - 保持会话期间的累计数据
        consecutiveErrors = 0;

        // 记录本轮抽奖的起始次数,用于判断是否达到本轮最大次数
        currentRoundStartCount = currentStats.lotteryCount;

        document.getElementById('current-interval').textContent = dynamicInterval / 1000;

        document.getElementById('lottery-status').textContent = '运行中...';
        document.getElementById('lottery-status').style.color = '#ffc107';
        document.getElementById('start-lottery').disabled = true;
        document.getElementById('stop-lottery').disabled = false;

        addLog(`🚀 开始抽奖,本轮最大次数: ${maxCount},基础间隔: ${dynamicInterval / 1000}秒`, 'info');
        addLog(`📊 当前会话已累计: ${currentStats.lotteryCount} 次抽奖,${currentStats.winCount} 次中奖`, 'info');

        performSingleLottery(maxCount);
        lotteryInterval = setInterval(() => {
            performSingleLottery(maxCount);
        }, dynamicInterval);
    }

    // 重置本次数据
    function resetCurrentData() {
        if (lotteryInterval) {
            addLog('⚠️ 请先停止抽奖再重置数据', 'warning');
            return;
        }

        if (confirm('确定要重置本次会话的数据吗?这将清空当前显示的所有本次统计数据!')) {
            currentStats = {
                lotteryCount: 0,
                winCount: 0,
                cost: 0,
                beansWon: 0,
                invites: 0,
                rainbowDays: 0,
                vipDays: 0,
                makeupCards: 0,
                uploadGB: 0,
                prizeStats: {}
            };

            updateDisplay();
            document.getElementById('prize-stats').style.display = 'none';
            addLog('✅ 本次会话数据已重置', 'success');
        }
    }

    // 初始化
    function init() {
        // 加载历史数据
        totalStats = loadStatsData();

        const panel = createControlPanel();
        if (!panel || !document.getElementById('lottery-control-panel')) {
            console.error('控制面板创建失败');
            addLog('❌ 控制面板创建失败', 'error');
            return;
        }

        // 绑定事件
        document.getElementById('start-lottery').addEventListener('click', startLottery);
        document.getElementById('stop-lottery').addEventListener('click', stopLottery);

        document.getElementById('set-max-possible').addEventListener('click', () => {
            const maxPossible = updateBalanceDisplay();
            document.getElementById('max-lottery-count').value = maxPossible;
        });

        document.getElementById('view-mode').addEventListener('change', updateDisplay);

        document.getElementById('clear-total-data').addEventListener('click', clearTotalData);

        document.getElementById('reset-current-data').addEventListener('click', resetCurrentData);

        document.getElementById('toggle-detailed-stats').addEventListener('click', () => {
            const detailedList = document.getElementById('detailed-prize-list');
            const button = document.getElementById('toggle-detailed-stats');

            if (detailedList.style.display === 'none') {
                detailedList.style.display = 'block';
                button.textContent = '隐藏';
            } else {
                detailedList.style.display = 'none';
                button.textContent = '详细';
            }
        });

        // 面板拖拽功能
        let isDragging = false;
        let dragOffset = { x: 0, y: 0 };

        const titleBar = panel.querySelector('h3').parentElement;
        titleBar.style.cursor = 'move';
        titleBar.style.userSelect = 'none';

        titleBar.addEventListener('mousedown', (e) => {
            isDragging = true;
            dragOffset.x = e.clientX - panel.offsetLeft;
            dragOffset.y = e.clientY - panel.offsetTop;
        });

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                panel.style.left = (e.clientX - dragOffset.x) + 'px';
                panel.style.top = (e.clientY - dragOffset.y) + 'px';
                panel.style.right = 'auto';
            }
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
        });

        console.log('🎲 hhanclub自动抽奖增强版脚本已加载!');

        // 初始化显示
        updateBalanceDisplay();
        updateDisplay();

        // 定期更新余额
        setInterval(() => {
            updateBalanceDisplay();
            getSingleCost(); // 定期检查单次消耗
        }, 10000);

        addLog('增强版脚本已就绪!支持数据持久化、本次/总计切换、动态消耗检测和详细统计分析', 'success');
        addLog('💡 提示:可通过下拉框切换查看本次数据或历史总计数据', 'info');
        addLog('🔄 说明:本次数据会在整个会话期间累计,多次开始/停止抽奖不会重置', 'info');
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();