// ==UserScript== // @name 亳州学院校园网自动登录 // @namespace http://scriptcat.org/ // @version 2.3 // @description ✨ 自动检测校园网登录页面,自动填充账号密码并登录,支持多账号、断网自动重连、后台定时检测 | 🎯 专为亳州学院gWiFi打造 | 💬 微信:daishuawangke88 // @author 微信:daishuawangke88 // @match http://10.15.1.4/* // @match http://10.15.1.4/gportal/* // @match *://*.baidu.com/* // @match *://*.google.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_openInTab // @grant GM_notification // @grant GM_xmlhttpRequest // @connect * // @run-at document-start // @license MIT // ==/UserScript== /** * ╔══════════════════════════════════════════════════════════════╗ * ║ 🎓 亳州学院校园网自动登录脚本 v2.3 ║ * ╠══════════════════════════════════════════════════════════════╣ * ║ ✨ 功能特性: ║ * ║ ✅ 自动检测登录页面并登录 ║ * ║ ✅ 支持保存多个账号(最多9个) ║ * ║ ✅ 断网自动打开登录页面并登录 ║ * ║ ✅ 登录失败自动切换账号 ║ * ║ ✅ 脚本猫后台定时任务 + 本地定时检测 ║ * ║ ✅ 登录状态准确检测 ║ * ╠══════════════════════════════════════════════════════════════╣ * ║ 💖 觉得好用?欢迎请作者喝杯奶茶! ║ * ║ 📱 微信:daishuawangke88 ║ * ║ 🌟 您的支持是我持续更新的动力! ║ * ╚══════════════════════════════════════════════════════════════╝ * * 📢 【脚本猫用户】设置后台定时任务: * 1️⃣ 点击脚本猫图标 → 找到本脚本 → 点击设置 * 2️⃣ 添加定时任务:选择"后台脚本" * 3️⃣ 设置执行频率(建议每5-10分钟) * 4️⃣ 脚本会自动检测网络并在断网时打开登录页 * * 💬 问题反馈/功能建议/技术交流:微信 daishuawangke88 */ (function () { 'use strict'; // ============================================= // 🎯 常量配置 // ============================================= const CONFIG = { LOGIN_URL: 'http://10.15.1.4/', // 登录页面主地址 LOGIN_URL_FULL: 'http://10.15.1.4/gportal/web/login', // 完整登录路径 MAX_ACCOUNTS: 9, CHECK_INTERVAL: 30000, // 检测间隔:30秒 CHECK_TIMEOUT: 5000, // 检测超时:5秒 LOGIN_WAIT: 3000, // 登录等待:3秒 PAGE_LOAD_WAIT: 2000, // 页面加载等待:2秒 MAX_AUTO_RETRY: 3, // 每个账号最多重试次数 AUTHOR_WECHAT: 'daishuawangke88', }; // ============================================= // 💬 鼓励语录库 // ============================================= const QUOTES = { success: [ '🎉 太棒了!登录成功!今天也要元气满满哦~', '✨ 哇塞!顺利连网!你的运气正在加载中...', '🚀 登录成功!冲鸭!今天又是充满希望的一天!', '🌟 搞定!网络已连接,你的梦想也在同步加载!', '💪 登录成功!每一次连接都是新的开始!', '🎊 恭喜!顺利上线!今天也会是幸运的一天!', '🔥 完美!网络畅通无阻,你也是!', '💖 登录成功!愿你的每一天都像网络一样顺畅!', ], failure: [ '💪 跌倒了就爬起来!人生如此,网络也如此~再试一次!', '🌈 别灰心!风雨过后总会有彩虹,断网之后总会有连接!', '🔥 失败是成功之母,这次不行下次一定行!', '🌟 没关系!每个困难都是成长的机会!', '🦋 蝴蝶破茧前也要挣扎,成功前的困难都是礼物!', '💫 黑暗之后是黎明,断网之后是连接!', '🌻 向日葵也会遇到阴天,但总会等到阳光!', '⚡ 每一次尝试都是进步,继续加油!', ], switchAccount: [ '🔄 账号登录失败,正在切换下一个账号...', '🔁 换一个试试,说不定这个能用!', '🔀 不行就换!总有一个能连上的!', ], allFailed: [ '😢 所有账号都尝试过了,还是没成功...', '💔 很遗憾,所有账号都无法登录', '😅 账号们都在休息,明天再试吧...', ], networkOk: [ '🌐 网络畅通无阻!今天也要好好上网哦~', '✅ 网络状态良好!冲冲冲!', '📶 信号满格!你的好心情也是!', ], networkFail: [ '📡 网络好像开小差了...正在帮你召唤登录页面!', '🔌 哎呀,网络走丢了!别急,马上帮你找回!', '🤔 网络君似乎在休息,马上叫醒它!', ], }; // 随机获取语录 function getRandomQuote(type) { const quotes = QUOTES[type] || QUOTES.success; return quotes[Math.floor(Math.random() * quotes.length)]; } // 生成带联系信息的完整消息 function makeMessage(quote, showContact = true) { if (showContact) { return `${quote}\n\n💖 觉得脚本好用?欢迎微信联系:${CONFIG.AUTHOR_WECHAT}\n🍵 请作者喝杯奶茶,支持持续更新!`; } return quote; } // ============================================= // 📦 存储管理 // ============================================= const Storage = { get(key, defaultValue = null) { try { return GM_getValue(key, defaultValue); } catch (e) { console.error('[存储读取失败]', e); return defaultValue; } }, set(key, value) { try { GM_setValue(key, value); return true; } catch (e) { console.error('[存储写入失败]', e); return false; } }, getAccounts() { return this.get('accounts', []) || []; }, saveAccounts(accounts) { return this.set('accounts', accounts); }, getCurrentIndex() { return this.get('currentAccountIndex', 0); }, setCurrentIndex(index) { return this.set('currentAccountIndex', index); }, getCurrentAccount() { const accounts = this.getAccounts(); const index = this.getCurrentIndex(); return accounts[index] || null; }, // 获取当前账号的重试次数 getRetryCount() { return this.get('retryCount', 0); }, // 增加重试次数 incrementRetryCount() { const count = this.getRetryCount() + 1; this.set('retryCount', count); return count; }, // 重置重试次数 resetRetryCount() { this.set('retryCount', 0); }, getStats() { return this.get('stats', { loginCount: 0, lastLogin: '从未', lastCheck: '从未' }); }, updateStats() { const stats = this.getStats(); stats.loginCount++; stats.lastLogin = new Date().toLocaleString(); this.set('stats', stats); return stats; }, }; // ============================================= // 📝 日志工具 // ============================================= const Log = { prefix: '[亳州学院校园网]', info(msg) { console.log(`${this.prefix} ℹ️ ${new Date().toLocaleTimeString()} ${msg}`); }, success(msg) { console.log(`${this.prefix} ✅ ${new Date().toLocaleTimeString()} ${msg}`); }, warn(msg) { console.warn(`${this.prefix} ⚠️ ${new Date().toLocaleTimeString()} ${msg}`); }, error(msg) { console.error(`${this.prefix} ❌ ${new Date().toLocaleTimeString()} ${msg}`); }, }; // ============================================= // 🌐 网络检测工具 // ============================================= const Network = { async check() { if (typeof GM_xmlhttpRequest !== 'undefined') { return await this.checkWithGM(); } return await this.checkWithFetch(); }, checkWithGM() { return new Promise((resolve) => { const timeout = setTimeout(() => resolve(false), CONFIG.CHECK_TIMEOUT); try { GM_xmlhttpRequest({ method: 'GET', url: 'http://www.baidu.com/favicon.ico', timeout: CONFIG.CHECK_TIMEOUT, onload: () => { clearTimeout(timeout); resolve(true); }, onerror: () => { clearTimeout(timeout); resolve(false); }, ontimeout: () => { clearTimeout(timeout); resolve(false); }, }); } catch (e) { clearTimeout(timeout); resolve(false); } }); }, checkWithFetch() { return new Promise((resolve) => { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), CONFIG.CHECK_TIMEOUT); fetch('http://www.baidu.com/favicon.ico', { mode: 'no-cors', signal: controller.signal, cache: 'no-store', }).then(() => { clearTimeout(timeout); resolve(true); }).catch(() => { clearTimeout(timeout); resolve(false); }); }); }, openLoginPage(closeOthers = false) { Log.info('🚪 正在打开登录页面...'); try { if (typeof GM_openInTab !== 'undefined') { GM_openInTab(CONFIG.LOGIN_URL, { active: true, insert: closeOthers }); } else { window.open(CONFIG.LOGIN_URL, '_blank'); } const quote = getRandomQuote('networkFail'); this.sendNotification('🔌 网络断开了', `${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); return true; } catch (e) { Log.error('打开登录页面失败: ' + e.message); return false; } }, sendNotification(title, text) { try { if (typeof GM_notification !== 'undefined') { GM_notification({ title: title, text: text, timeout: 8000, }); } } catch (e) { } }, }; // ============================================= // 🔐 登录功能 // ============================================= const Login = { usernameSelectors: [ '#username', 'input[name="username"]', 'input[name="user"]', 'input[name="account"]', 'input[name="userName"]', 'input[name="user_name"]', 'input[type="text"][placeholder*="用户"]', 'input[type="text"][placeholder*="学号"]', 'input[type="text"][placeholder*="账号"]', 'input[type="text"][placeholder*="手机"]', 'input[id*="user" i]', 'input[id*="account" i]', '.username-input', '.user-input', 'input[type="text"]', ], passwordSelectors: [ '#password', 'input[name="password"]', 'input[name="pass"]', 'input[name="pwd"]', 'input[name="userPwd"]', 'input[type="password"]', 'input[id*="pass" i]', 'input[id*="pwd" i]', '.password-input', ], buttonSelectors: [ '#login', '#btnLogin', '#login-btn', '#submit', 'button[type="submit"]', 'input[type="submit"]', 'button.login-btn', 'a.login-btn', '.login-btn', 'button.btn-primary', 'button[class*="login" i]', 'input[value*="登录"]', 'input[value*="Login"]', ], isOnLoginPage() { return location.href.includes('10.15.1.4'); }, async checkLoginStatus() { if (!this.isOnLoginPage()) { return true; } const bodyText = document.body?.innerText || ''; const successKeywords = ['登录成功', '上线成功', '已在线', '欢迎', '成功登', '在线时长']; for (const keyword of successKeywords) { if (bodyText.includes(keyword)) { return true; } } await this.sleep(500); const hasPasswordInput = document.querySelector('input[type="password"]'); if (!hasPasswordInput && document.readyState === 'complete') { return await Network.check(); } return false; }, async execute(showAlert = false) { const account = Storage.getCurrentAccount(); if (!account) { Log.warn('❌ 未配置账号'); if (showAlert) { alert(`⚠️ 请先添加账号!\n\n点击油猴图标 → 添加账号\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } return { success: false, reason: 'no_account' }; } if (!this.isOnLoginPage()) { Log.info('📍 不在登录页面'); return { success: false, reason: 'not_login_page' }; } if (document.readyState !== 'complete') { await new Promise(r => window.addEventListener('load', r)); } await this.sleep(CONFIG.PAGE_LOAD_WAIT); // 检查是否已登录 if (await this.checkLoginStatus()) { Log.success('✅ 已经登录'); this.updateUI('✅ 已登录'); Storage.resetRetryCount(); if (showAlert) { const quote = getRandomQuote('success'); alert(makeMessage(quote)); } return { success: true, reason: 'already_logged_in' }; } // 查找表单元素 const usernameInput = this.findElement(this.usernameSelectors); const passwordInput = this.findElement(this.passwordSelectors); const loginButton = this.findLoginButton(); Log.info(`🔍 表单检测: 用户名=${!!usernameInput}, 密码=${!!passwordInput}, 按钮=${!!loginButton}`); if (!usernameInput || !passwordInput) { Log.error('❌ 未找到登录表单'); this.updateUI('❌ 未找到表单'); if (showAlert) { const quote = getRandomQuote('failure'); alert(`❌ 未找到登录表单\n\n${quote}\n\n💬 问题反馈微信:${CONFIG.AUTHOR_WECHAT}`); } return { success: false, reason: 'form_not_found' }; } // 填充账号密码 this.setInputValue(usernameInput, account.username); this.setInputValue(passwordInput, account.password); Log.info(`📝 已填充账号: ${account.name} (${account.username.substring(0, 3)}***)`); // 提交登录 if (loginButton) { loginButton.click(); Log.info('🔘 已点击登录按钮'); } else { const form = usernameInput.closest('form') || document.querySelector('form'); if (form) { form.submit(); Log.info('📋 已提交表单'); } else { passwordInput.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', keyCode: 13, bubbles: true })); Log.info('⌨️ 已模拟回车提交'); } } this.updateUI('🔄 登录中...'); // 等待登录结果 await this.sleep(CONFIG.LOGIN_WAIT); // 验证结果 const success = await this.checkLoginStatus(); if (success) { Log.success('🎉 登录成功!'); this.updateUI('🎉 登录成功'); Storage.updateStats(); Storage.resetRetryCount(); if (showAlert) { const quote = getRandomQuote('success'); alert(makeMessage(quote)); } return { success: true, reason: 'login_success' }; } else { Log.warn('❌ 登录失败'); this.updateUI('❌ 登录失败'); return { success: false, reason: 'login_failed' }; } }, findElement(selectors) { for (const sel of selectors) { try { const el = document.querySelector(sel); if (el) { const style = window.getComputedStyle(el); if (style.display !== 'none' && style.visibility !== 'hidden') { return el; } } } catch (e) { } } return null; }, findLoginButton() { let btn = this.findElement(this.buttonSelectors); if (btn) return btn; const elements = document.querySelectorAll('button, input[type="submit"], input[type="button"], a, [role="button"], .btn'); for (const el of elements) { const text = (el.textContent || el.value || '').trim(); if (text.includes('登录') || text.includes('Login') || text === '登 录') { return el; } } return null; }, setInputValue(input, value) { const nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set; if (nativeSetter) { nativeSetter.call(input, value); } else { input.value = value; } ['input', 'change', 'blur'].forEach(event => { input.dispatchEvent(new Event(event, { bubbles: true })); }); }, updateUI(status) { Storage.set('lastStatus', status); Storage.set('lastCheck', new Date().toLocaleString()); const statusEl = document.getElementById('campus-login-status-text'); if (statusEl) { statusEl.textContent = status; } }, sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, /** * 切换到下一个账号 * @returns {object} 切换后的账号信息 */ switchToNextAccount() { const accounts = Storage.getAccounts(); if (accounts.length <= 1) { return null; } let currentIndex = Storage.getCurrentIndex(); let nextIndex = (currentIndex + 1) % accounts.length; Storage.setCurrentIndex(nextIndex); Storage.resetRetryCount(); const nextAccount = accounts[nextIndex]; Log.info(`🔄 已切换账号: ${nextAccount.name} (${nextAccount.username.substring(0, 3)}***)`); const quote = getRandomQuote('switchAccount'); Network.sendNotification('🔄 切换账号', `${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); return nextAccount; }, /** * 自动尝试所有账号登录 * @param {boolean} showNotification 是否显示通知 * @returns {object} 登录结果 */ async tryAllAccounts(showNotification = true) { const accounts = Storage.getAccounts(); if (accounts.length === 0) { if (showNotification) { alert(`⚠️ 请先添加账号!\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } return { success: false, reason: 'no_account' }; } let triedAccounts = []; let success = false; let lastError = ''; // 先尝试当前账号 const currentIndex = Storage.getCurrentIndex(); triedAccounts.push(currentIndex); // 尝试当前账号 Log.info(`🔄 尝试当前账号 (${accounts[currentIndex].name})...`); Storage.setCurrentIndex(currentIndex); let result = await this.execute(false); if (result.success) { success = true; } else { lastError = result.reason; // 尝试其他账号 for (let i = 0; i < accounts.length - 1; i++) { if (triedAccounts.includes(Storage.getCurrentIndex())) { this.switchToNextAccount(); } triedAccounts.push(Storage.getCurrentIndex()); Log.info(`🔄 切换到账号 ${accounts[Storage.getCurrentIndex()].name},重试登录...`); result = await this.execute(false); if (result.success) { success = true; break; } else { lastError = result.reason; } } } if (success) { const quote = getRandomQuote('success'); Log.success('🎉 某个账号登录成功!'); if (showNotification) { alert(makeMessage(quote)); } return { success: true, reason: 'login_success' }; } else { Log.error('❌ 所有账号都登录失败'); if (showNotification) { const quote = getRandomQuote('allFailed'); alert(`${quote}\n\n尝试过的账号:${triedAccounts.length} 个\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } // 回到第一个账号 Storage.setCurrentIndex(0); return { success: false, reason: 'all_failed', triedCount: triedAccounts.length }; } }, }; // ============================================= // 🎨 状态指示器UI // ============================================= function addStatusIndicator() { if (!Login.isOnLoginPage()) return; if (document.getElementById('campus-login-status-box')) return; const div = document.createElement('div'); div.id = 'campus-login-status-box'; div.innerHTML = `
🎓 亳州学院校园网自动登录
${Storage.get('lastStatus', '🚀 就绪')}
💬 微信:${CONFIG.AUTHOR_WECHAT}
`; div.style.cssText = ` position: fixed; top: 12px; right: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; padding: 14px 18px; border-radius: 12px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; z-index: 2147483647; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); min-width: 200px; backdrop-filter: blur(10px); `; document.body.appendChild(div); } // ============================================= // 📋 菜单命令 // ============================================= function registerMenus() { // ➕ 添加账号 GM_registerMenuCommand('➕ 添加账号', () => { const accounts = Storage.getAccounts(); if (accounts.length >= CONFIG.MAX_ACCOUNTS) { alert(`⚠️ 最多支持 ${CONFIG.MAX_ACCOUNTS} 个账号!\n\n💬 需要更多?微信联系:${CONFIG.AUTHOR_WECHAT}`); return; } const username = prompt('📝 请输入学号:'); if (!username) return; const password = prompt('🔑 请输入密码:'); if (!password) return; const name = prompt('🏷️ 备注名(如:移动、电信):') || `账号${accounts.length + 1}`; accounts.push({ username, password, name, createTime: new Date().toLocaleString() }); Storage.saveAccounts(accounts); if (accounts.length === 1) Storage.setCurrentIndex(0); const quote = getRandomQuote('success'); alert(`✅ 账号 "${name}" 添加成功!\n\n当前共 ${accounts.length} 个账号\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); }); // 🔄 切换账号 GM_registerMenuCommand('🔄 切换账号', () => { const accounts = Storage.getAccounts(); if (accounts.length === 0) { alert(`⚠️ 暂无账号,请先添加!\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); return; } let msg = '🔢 请输入序号切换账号:\n\n'; accounts.forEach((acc, i) => { const cur = i === Storage.getCurrentIndex() ? '✅ ' : ' '; msg += `${cur}${i + 1}. ${acc.name} (${acc.username.substring(0, 3)}***)\n`; }); msg += `\n💬 微信:${CONFIG.AUTHOR_WECHAT}`; const input = prompt(msg); if (!input) return; const index = parseInt(input) - 1; if (index >= 0 && index < accounts.length) { Storage.setCurrentIndex(index); Storage.resetRetryCount(); const quote = getRandomQuote('success'); alert(`✅ 已切换到: ${accounts[index].name}\n\n${quote}`); } }); // 📋 管理账号 GM_registerMenuCommand('📋 管理账号', () => { const accounts = Storage.getAccounts(); if (accounts.length === 0) { if (confirm('⚠️ 暂无账号,是否添加?')) { const username = prompt('📝 请输入学号:'); if (!username) return; const password = prompt('🔑 请输入密码:'); if (!password) return; const name = prompt('🏷️ 备注名:') || '账号1'; accounts.push({ username, password, name, createTime: new Date().toLocaleString() }); Storage.saveAccounts(accounts); Storage.setCurrentIndex(0); const quote = getRandomQuote('success'); alert(`✅ 账号 "${name}" 添加成功!\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } return; } let msg = '📋 账号列表:\n\n'; accounts.forEach((acc, i) => { const cur = i === Storage.getCurrentIndex() ? '✅ ' : ' '; msg += `${cur}${i + 1}. ${acc.name}\n 📌 学号: ${acc.username}\n 🕐 添加: ${acc.createTime}\n\n`; }); msg += '───────────────\n'; msg += '🗑️ 输入序号删除账号\n'; msg += '🚫 输入 0 取消\n\n'; msg += `💬 微信:${CONFIG.AUTHOR_WECHAT}`; const input = prompt(msg); if (!input || input === '0') return; const index = parseInt(input) - 1; if (index >= 0 && index < accounts.length) { if (confirm(`🗑️ 确定删除 "${accounts[index].name}"?`)) { accounts.splice(index, 1); Storage.saveAccounts(accounts); if (Storage.getCurrentIndex() >= accounts.length) { Storage.setCurrentIndex(Math.max(0, accounts.length - 1)); } const quote = getRandomQuote('failure'); alert(`✅ 已删除\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } } }); // 🚀 立即登录 GM_registerMenuCommand('🚀 立即登录', async () => { const account = Storage.getCurrentAccount(); if (!account) { alert(`⚠️ 请先添加账号!\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); return; } if (!Login.isOnLoginPage()) { Network.openLoginPage(); const quote = getRandomQuote('networkFail'); alert(`🚪 已打开登录页面,请稍候...\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } else { await Login.execute(true); } }); // 🔄 尝试所有账号 GM_registerMenuCommand('🔄 尝试所有账号', async () => { if (!Login.isOnLoginPage()) { Network.openLoginPage(); alert(`🚪 已打开登录页面,页面加载后将自动尝试所有账号...\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); return; } await Login.tryAllAccounts(true); }); // 🔍 检测网络 GM_registerMenuCommand('🔍 检测网络', async () => { const quote = getRandomQuote('networkOk'); alert(`🔍 正在检测网络...\n\n${quote}`); const isOnline = await Network.check(); if (isOnline) { const quote = getRandomQuote('networkOk'); alert(`✅ 网络正常!\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); } else { const quote = getRandomQuote('networkFail'); alert(`❌ 网络异常!\n\n${quote}\n\n💬 微信:${CONFIG.AUTHOR_WECHAT}`); Network.openLoginPage(); } }); // 📊 查看状态 GM_registerMenuCommand('📊 查看状态', () => { const accounts = Storage.getAccounts(); const current = Storage.getCurrentAccount(); const stats = Storage.getStats(); const idx = Storage.getCurrentIndex(); let list = accounts.map((a, i) => `${i === idx ? '✅' : ' '} ${i + 1}. ${a.name}` ).join('\n') || '暂无账号'; alert(` ╔════════════════════════════╗ ║ 🎓 亳州学院校园网自动登录 v2.3 ║ ╚════════════════════════════╝ 📌 当前账号:${current ? current.name : '未设置'} 📝 学号:${current ? current.username : '-'} 📋 账号列表 (${accounts.length}/${CONFIG.MAX_ACCOUNTS}): ${list} 📊 统计信息: 🔢 登录次数:${stats.loginCount} 🕐 上次登录:${stats.lastLogin} 🕐 上次检测:${stats.lastCheck} ════════════════════════════ 💬 问题反馈/功能建议/请喝奶茶 📱 微信:${CONFIG.AUTHOR_WECHAT} 💖 您的支持是我持续更新的动力! ════════════════════════════ `.trim()); }); // ☕ 请作者喝茶 GM_registerMenuCommand('☕ 请作者喝茶', () => { alert(` 💖 感谢您的支持! 如果您觉得这个脚本好用 欢迎请作者喝杯奶茶 ☕ 这会成为我持续更新的动力 💪 ═══════════════════════ 📱 微信:${CONFIG.AUTHOR_WECHAT} 🌟 添加时备注:校园网脚本 ═══════════════════════ 🙏 感谢每一位支持者! `.trim()); }); } // ============================================= // 🕐 后台检测任务 // ============================================= async function backgroundCheck() { Log.info('🕐 执行后台定时检测...'); Storage.set('lastCheck', new Date().toLocaleString()); const isOnline = await Network.check(); if (isOnline) { Log.success('✅ 网络正常'); return { status: 'online' }; } else { Log.warn('⚠️ 网络异常,打开登录页面'); Network.openLoginPage(); return { status: 'offline', action: 'opened_login_page' }; } } // ============================================= // 🔄 本地定时检测(不依赖脚本猫后台) // ============================================= let checkIntervalId = null; function startLocalCheckLoop() { if (checkIntervalId) { clearInterval(checkIntervalId); } Log.info(`🔄 启动本地定时检测,间隔 ${CONFIG.CHECK_INTERVAL / 1000} 秒`); checkIntervalId = setInterval(async () => { // 只有在登录页面才执行自动登录 if (Login.isOnLoginPage()) { Log.info('📍 在登录页面,执行自动登录...'); const result = await Login.tryAllAccounts(false); if (result.success) { Log.success('✅ 登录成功,停止本次检测'); } else { Log.warn('⚠️ 所有账号登录失败'); } } }, CONFIG.CHECK_INTERVAL); } function stopLocalCheckLoop() { if (checkIntervalId) { clearInterval(checkIntervalId); checkIntervalId = null; Log.info('⏹️ 已停止本地定时检测'); } } // 暴露给外部的接口 window.campusNetAutoLogin = { backgroundCheck, checkNetwork: Network.check.bind(Network), login: Login.execute.bind(Login), tryAllAccounts: Login.tryAllAccounts.bind(Login), switchAccount: Login.switchToNextAccount.bind(Login), storage: Storage, config: CONFIG, startLocalCheck: startLocalCheckLoop, stopLocalCheck: stopLocalCheckLoop, }; // ============================================= // 🚀 主初始化 // ============================================= async function init() { Log.info('🚀 脚本启动 v2.3'); Log.info(`📍 当前URL: ${location.href}`); registerMenus(); const account = Storage.getCurrentAccount(); if (!account) { Log.warn('⚠️ 未配置账号'); if (Login.isOnLoginPage()) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { addStatusIndicator(); Login.updateUI('⚠️ 请先添加账号'); }); } else { addStatusIndicator(); Login.updateUI('⚠️ 请先添加账号'); } } // 启动本地检测循环(用于检测到断网时提示用户) startLocalCheckLoop(); return; } if (Login.isOnLoginPage()) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', async () => { addStatusIndicator(); Login.updateUI('🔄 正在登录...'); await Login.sleep(1000); // 自动尝试所有账号 await Login.tryAllAccounts(false); }); } else { addStatusIndicator(); Login.updateUI('🔄 正在登录...'); // 自动尝试所有账号 await Login.tryAllAccounts(false); } // 启动本地检测循环 startLocalCheckLoop(); return; } Log.info('✅ 非登录页面,网络正常'); // 启动本地检测循环 startLocalCheckLoop(); } // 启动 init(); })();