您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动加载所有未读消息并标记为已读
// ==UserScript== // @name HHCLUB-收件箱批量已读处理 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 自动加载所有未读消息并标记为已读 // @author You // @match https://hhanclub.top/messages.php* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; let isProcessing = false; let shouldStop = false; const STORAGE_KEY = 'autoReadState'; // 状态管理 function saveState(data) { localStorage.setItem(STORAGE_KEY, JSON.stringify({...data, time: Date.now()})); } function getSavedState() { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { const data = JSON.parse(saved); return (Date.now() - data.time < 300000) ? data : null; } return null; } function clearState() { localStorage.removeItem(STORAGE_KEY); } // 创建控制面板 function createPanel() { const existing = document.getElementById('msgPanel'); if (existing) existing.remove(); const panel = document.createElement('div'); panel.id = 'msgPanel'; panel.innerHTML = ` <div id="header" style="cursor:move;font-weight:bold;text-align:center;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid rgba(255,255,255,0.3)">📬 消息处理助手</div> <div id="count" style="margin-bottom:10px;padding:8px;background:rgba(255,255,255,0.2);border-radius:5px;text-align:center">检测中...</div> <div id="status" style="margin-bottom:10px;padding:6px;background:rgba(0,0,0,0.2);border-radius:5px;font-size:12px">点击开始处理</div> <div id="progress" style="display:none;margin-bottom:10px"> <div id="progressText" style="font-size:11px;margin-bottom:3px">准备中...</div> <div style="background:rgba(255,255,255,0.3);height:6px;border-radius:3px;margin:5px 0"> <div id="progressBar" style="background:#4CAF50;height:100%;width:0%;border-radius:3px;transition:width 0.3s"></div> </div> </div> <div style="display:flex;gap:8px;margin-top:10px"> <button id="startBtn" style="background:#4CAF50;color:white;border:none;padding:8px 12px;border-radius:5px;cursor:pointer;flex:1;font-size:12px">🚀 开始</button> <button id="stopBtn" style="display:none;background:#f44336;color:white;border:none;padding:8px 12px;border-radius:5px;cursor:pointer;flex:1;font-size:12px">⏹️ 停止</button> </div> `; panel.style.cssText = ` position: fixed !important; top: 50% !important; right: 20px !important; transform: translateY(-50%) !important; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white !important; padding: 15px !important; border-radius: 10px !important; font-size: 13px !important; width: 250px !important; box-shadow: 0 8px 20px rgba(0,0,0,0.5) !important; z-index: 999999 !important; font-family: Arial, sans-serif !important; border: 2px solid rgba(255,255,255,0.3) !important; `; document.body.appendChild(panel); setTimeout(() => makeDraggable(panel), 100); return panel; } // 拖拽功能 function makeDraggable(el) { let pos1=0,pos2=0,pos3=0,pos4=0; const header = document.getElementById('header'); if (header) { header.onmousedown = (e) => { e.preventDefault(); pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = () => { document.onmouseup = document.onmousemove = null; }; document.onmousemove = (e) => { pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; el.style.top = Math.max(0, Math.min(window.innerHeight-el.offsetHeight, el.offsetTop-pos2)) + "px"; el.style.left = Math.max(0, Math.min(window.innerWidth-el.offsetWidth, el.offsetLeft-pos1)) + "px"; el.style.right = 'auto'; el.style.transform = 'none'; }; }; } } // 更新显示函数 function updateStatus(msg) { const statusEl = document.getElementById('status'); if (statusEl) statusEl.textContent = msg; console.log(`[消息处理] ${msg}`); } function updateCount() { const el = document.querySelector('div[style="margin:auto auto;"]'); const count = el ? parseInt(el.textContent) || 0 : 0; const countEl = document.getElementById('count'); if (countEl) countEl.innerHTML = `📩 未读:<b>${count}</b> 条`; return count; } function updateProgress(current, total, text) { const container = document.getElementById('progress'); const bar = document.getElementById('progressBar'); const textEl = document.getElementById('progressText'); if (container && bar && textEl) { if (total > 0) { container.style.display = 'block'; textEl.textContent = text; bar.style.width = (current/total*100) + '%'; } else { container.style.display = 'none'; } } } // 点击未读短讯 async function clickUnreadMessages() { const labels = document.querySelectorAll('label'); for (let label of labels) { if (label.textContent.includes('未读短讯')) { updateStatus('点击未读短讯...'); label.click(); return true; } } return false; } // 点击加载更多 async function clickLoadMore() { if (shouldStop) return false; const btn = document.querySelector('button[onclick="loadMail()"]'); if (btn && !btn.disabled) { updateStatus('点击加载更多...'); btn.click(); return new Promise(resolve => { const check = setInterval(() => { if (shouldStop) { clearInterval(check); resolve(false); return; } const loading = document.getElementById('mail-loading'); if (!loading || loading.style.display === 'none') { clearInterval(check); setTimeout(() => resolve(true), 300); } }, 100); }); } return false; } // 正确的全选功能 async function clickSelectAll() { if (shouldStop) return false; updateStatus('正在查找全选按钮...'); // 根据提供的元素信息查找全选按钮 const selectAllBtn = document.querySelector('input[type="button"][value="全选"][onclick*="check(form"]'); if (!selectAllBtn) { updateStatus('❌ 未找到全选按钮'); return false; } console.log('找到全选按钮:', selectAllBtn); updateStatus('找到全选按钮,当前文字: ' + selectAllBtn.value); // 检查按钮当前状态 if (selectAllBtn.value === '全选') { updateStatus('点击全选按钮...'); selectAllBtn.click(); // 等待按钮状态改变 await new Promise(resolve => setTimeout(resolve, 1000)); // 检查按钮文字是否变成了"全不选" if (selectAllBtn.value === '全不选') { updateStatus('✅ 全选成功!按钮已变为: ' + selectAllBtn.value); return true; } else { updateStatus('❌ 全选可能失败,按钮文字仍为: ' + selectAllBtn.value); // 再次尝试点击 selectAllBtn.click(); await new Promise(resolve => setTimeout(resolve, 1000)); if (selectAllBtn.value === '全不选') { updateStatus('✅ 第二次尝试全选成功!'); return true; } else { updateStatus('❌ 全选失败,按钮文字: ' + selectAllBtn.value); return false; } } } else if (selectAllBtn.value === '全不选') { updateStatus('✅ 已经是全选状态 (按钮显示: 全不选)'); return true; } else { updateStatus('❌ 未知的按钮状态: ' + selectAllBtn.value); return false; } } // 等待并显示倒计时 async function waitWithCountdown(seconds, message) { for (let i = seconds; i > 0; i--) { if (shouldStop) return false; updateStatus(`${message} (${i}秒)`); await new Promise(resolve => setTimeout(resolve, 1000)); } return true; } // 继续处理 async function continueProcess(count) { const clickTimes = Math.ceil(count / 10); updateStatus(`开始处理 ${count} 条消息,需加载 ${clickTimes} 次`); // 加载更多消息 for (let i = 0; i < clickTimes; i++) { if (shouldStop) return; updateProgress(i + 1, clickTimes + 2, `加载 ${i+1}/${clickTimes}`); const success = await clickLoadMore(); if (!success) break; } if (shouldStop) return; // 等待页面稳定 updateStatus('等待页面稳定...'); await new Promise(resolve => setTimeout(resolve, 2000)); // 全选消息 - 使用正确的全选逻辑 updateProgress(clickTimes + 1, clickTimes + 2, '全选消息'); const selectAllSuccess = await clickSelectAll(); if (!selectAllSuccess) { updateStatus('❌ 全选失败,无法继续'); return; } // 等待3秒确保全选完全生效 if (shouldStop) return; if (!(await waitWithCountdown(3, '等待全选完全生效'))) return; // 设为已读 updateProgress(clickTimes + 2, clickTimes + 2, '标记已读'); const markReadBtn = document.querySelector('input[name="markread"][value="设为已读"]'); if (markReadBtn) { updateStatus('点击设为已读...'); markReadBtn.click(); await new Promise(resolve => setTimeout(resolve, 1000)); clearState(); updateStatus('✅ 处理完成!'); setTimeout(updateCount, 2000); } else { updateStatus('❌ 未找到设为已读按钮'); } } // 主处理函数 async function processMessages() { if (isProcessing) return; isProcessing = true; shouldStop = false; const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); if (startBtn) startBtn.style.display = 'none'; if (stopBtn) stopBtn.style.display = 'block'; try { const count = updateCount(); if (count === 0) { updateStatus('✅ 没有未读消息'); return; } saveState({phase: 'afterUnread', count}); updateProgress(1, 4, '点击未读短讯'); if (await clickUnreadMessages()) { updateStatus('页面刷新中...'); return; } await continueProcess(count); } catch(e) { updateStatus('❌ 错误: ' + e.message); console.error('处理错误:', e); } finally { resetUI(); } } function stopProcess() { shouldStop = true; clearState(); updateStatus('❌ 用户停止操作'); resetUI(); } function resetUI() { isProcessing = false; shouldStop = false; setTimeout(() => { const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); if (startBtn) startBtn.style.display = 'block'; if (stopBtn) stopBtn.style.display = 'none'; updateProgress(0, 0, ''); }, 2000); } // 初始化 function init() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); return; } createPanel(); const saved = getSavedState(); if (saved && saved.phase === 'afterUnread') { isProcessing = true; const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); if (startBtn) startBtn.style.display = 'none'; if (stopBtn) stopBtn.style.display = 'block'; updateStatus('🔄 页面刷新后继续处理...'); setTimeout(() => continueProcess(saved.count), 2000); } setTimeout(() => { const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); if (startBtn) startBtn.onclick = processMessages; if (stopBtn) stopBtn.onclick = stopProcess; updateCount(); updateStatus('🎯 准备就绪'); }, 100); } init(); })();