// ==UserScript== // @name 亳州学院校园网自动登录 // @namespace http://scriptcat.org/ // @version 1.2.0 // @description 亳州学院GiWiFi专属,断网自动重连,自定义检测间隔,登录成功后可自动关闭标签页,修复重复开认证标签页问题,脚本猫后台运行专属 | 作者微信:daishuawangke88 // @author 微信:daishuawangke88 // @match http://10.15.1.4/* // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_openInTab // @grant GM_notification // @run-at document-end // @license MIT // ==/UserScript== (function () { 'use strict'; // ===================== 核心固定配置(适配你的校园网源码,无需修改) ===================== const CONFIG = { // 校园网固定地址 LOGIN_PAGE: 'http://10.15.1.4/gportal/web/login', LOGIN_HOST: '10.15.1.4', // 外网检测地址(百度favicon,零误判) CHECK_URL: 'http://www.baidu.com/favicon.ico', // 默认检测间隔(秒),可在菜单自定义 DEFAULT_CHECK_INTERVAL: 30, // 表单查找最大重试次数(适配页面动态渲染) MAX_FORM_RETRY: 30, // 认证Tab存在标志的超时时间(ms),超时自动释放锁,防止 Tab 被手动关闭后锁不释放 LOGIN_TAB_LOCK_TIMEOUT: 60000, }; // ===================== 账号存储管理(单账号,简单稳定) ===================== const AccountManager = { get() { return { username: GM_getValue('bzxy_username', ''), password: GM_getValue('bzxy_password', '') }; }, save(username, password) { GM_setValue('bzxy_username', username.trim()); GM_setValue('bzxy_password', password.trim()); GM_notification({ title: '✅ 账号保存成功', text: '账号密码已保存,刷新登录页即可自动填充', timeout: 3000 }); }, view() { const account = this.get(); if (!account.username) { alert('⚠️ 暂未保存任何账号密码,请先在菜单中设置'); return; } alert(`📝 已保存的账号信息:\n\n账号:${account.username}\n密码:${account.password}`); }, hasConfig() { const account = this.get(); return account.username && account.password; } }; // ===================== 自动关闭标签页设置 ===================== const AutoCloseManager = { isEnabled() { return GM_getValue('bzxy_auto_close_tab', false); }, enable() { GM_setValue('bzxy_auto_close_tab', true); }, disable() { GM_setValue('bzxy_auto_close_tab', false); }, toggle() { const current = this.isEnabled(); if (current) { this.disable(); alert('🔔 已关闭「登录成功后自动关闭标签页」功能\n\n登录成功后将保留标签页,不再自动关闭。'); } else { this.enable(); alert('✅ 已开启「登录成功后自动关闭标签页」功能\n\n登录成功后将在 3 秒内自动关闭本登录标签页。'); } }, getStatusText() { return this.isEnabled() ? '🔴 关闭「登录成功自动关闭标签」(当前:已开启)' : '🟢 开启「登录成功自动关闭标签」(当前:已关闭)'; }, closeTabIfEnabled(delayMs = 3000) { if (!this.isEnabled()) return; console.log(`[亳州学院校园网] 登录成功,将在 ${delayMs / 1000} 秒后自动关闭本标签页`); GM_notification({ title: '🎉 登录成功,即将关闭标签页', text: `将在 ${delayMs / 1000} 秒后自动关闭本登录标签页`, timeout: delayMs }); setTimeout(() => { try { window.close(); setTimeout(() => { if (!window.closed) { document.body.innerHTML = '
🎉 校园网登录成功,此标签页可手动关闭
'; } }, 500); } catch (e) { console.warn('[亳州学院校园网] 自动关闭标签页失败:', e); } }, delayMs); } }; // ===================== 认证Tab全局锁(核心修复:防止重复打开认证Tab) ===================== // 原理:用 GM_setValue 在所有标签页间共享状态 // bzxy_login_tab_ts:最近一次打开认证Tab的时间戳 // 任意Tab在打开新认证Tab前,先检查这个时间戳: // - 距上次打开不足 LOGIN_TAB_LOCK_TIMEOUT 毫秒 → 说明已有认证Tab在运行,跳过 // - 超时 or 未设置 → 可以打开新Tab,并更新时间戳 // 认证Tab完成(成功/失败)后主动重置时间戳,释放锁 const LoginTabLock = { KEY: 'bzxy_login_tab_ts', // 尝试加锁,成功返回 true,说明可以打开新Tab;已有锁返回 false acquire() { const lastTs = GM_getValue(this.KEY, 0); const now = Date.now(); if (now - lastTs < CONFIG.LOGIN_TAB_LOCK_TIMEOUT) { console.log(`[亳州学院校园网] 已有认证Tab在运行中(${Math.round((CONFIG.LOGIN_TAB_LOCK_TIMEOUT - (now - lastTs)) / 1000)}秒后锁释放),本次跳过`); return false; } GM_setValue(this.KEY, now); console.log('[亳州学院校园网] 认证Tab锁已获取,可以打开新标签页'); return true; }, // 释放锁(登录完成、失败、或Tab关闭时调用) release() { GM_setValue(this.KEY, 0); console.log('[亳州学院校园网] 认证Tab锁已释放'); }, // 当前是否持有锁(锁内) isLocked() { const lastTs = GM_getValue(this.KEY, 0); return lastTs > 0 && (Date.now() - lastTs < CONFIG.LOGIN_TAB_LOCK_TIMEOUT); } }; // ===================== 网络检测模块(100%准确,不会被内网欺骗) ===================== const NetworkChecker = { getInterval() { return GM_getValue('bzxy_check_interval', CONFIG.DEFAULT_CHECK_INTERVAL) * 1000; }, setInterval(second) { GM_setValue('bzxy_check_interval', second); this.restartLoop(); alert(`✅ 检测间隔已设置为${second}秒,已自动重启检测`); }, async isOnline() { return new Promise((resolve) => { const img = new Image(); img.src = `${CONFIG.CHECK_URL}?t=${new Date().getTime()}`; img.onload = () => resolve(true); img.onerror = () => resolve(false); setTimeout(() => resolve(false), 3000); }); }, async checkNow() { alert('正在检测外网状态,请稍候...'); const online = await this.isOnline(); if (online) { alert('✅ 网络正常,校园网已连接,祝你上网愉快'); } else { if (confirm('❌ 网络断开,生活打不败我!是否打开校园网登录页?')) { this.openLoginPage(true); // 手动触发,强制打开 } } }, // 打开校园网登录页 // forceOpen=true 时跳过 Tab 锁检测(用于用户手动触发) openLoginPage(forceOpen = false) { if (!forceOpen) { // ★ 核心修复:检查是否已有认证Tab存在 if (!LoginTabLock.acquire()) { // 已有认证Tab在运行,不重复打开 return; } } console.log('[亳州学院校园网] 检测到外网断开,打开登录页'); GM_notification({ title: '🔌 校园网已断开', text: '生活打不败我!正在打开登录页,将自动完成登录', timeout: 3000 }); GM_openInTab(CONFIG.LOGIN_PAGE, { active: true }); }, loopTimer: null, startLoop() { this.stopLoop(); const interval = this.getInterval(); this.loopTimer = setInterval(async () => { const online = await this.isOnline(); console.log('[亳州学院校园网] 外网检测结果:', online ? '正常' : '断开'); if (!online) { this.openLoginPage(); // 后台自动触发,受Tab锁保护 } }, interval); console.log(`[亳州学院校园网] 后台检测已启动,间隔${interval/1000}秒`); }, stopLoop() { if (this.loopTimer) { clearInterval(this.loopTimer); this.loopTimer = null; console.log('[亳州学院校园网] 后台检测已停止'); } }, restartLoop() { this.stopLoop(); this.startLoop(); } }; // ===================== 自动登录模块(精准适配你的校园网源码,100%找到表单) ===================== const AutoLogin = { selectors: { username: 'input[name="user_account"], #p_account, #account', password: 'input[name="user_password"], #password', loginBtn: '#btn_login' }, isLoginPage() { return location.host.includes(CONFIG.LOGIN_HOST) && location.pathname.toLowerCase().includes('/login'); }, isLoggedInPage() { return location.host.includes(CONFIG.LOGIN_HOST) && (location.pathname.toLowerCase().includes('/index') || location.pathname.toLowerCase().includes('/logout')); }, findForm() { return { usernameInput: document.querySelector(this.selectors.username), passwordInput: document.querySelector(this.selectors.password), loginBtn: document.querySelector(this.selectors.loginBtn) }; }, async fillAndLogin() { if (!this.isLoginPage()) return; if (!AccountManager.hasConfig()) { alert('⚠️ 请先点击脚本猫菜单,设置你的校园网账号密码!'); LoginTabLock.release(); // 无法登录,释放锁 return; } const account = AccountManager.get(); console.log('[亳州学院校园网] 开始查找登录表单,准备自动登录'); for (let i = 0; i < CONFIG.MAX_FORM_RETRY; i++) { const { usernameInput, passwordInput, loginBtn } = this.findForm(); if (usernameInput && passwordInput && loginBtn) { console.log(`[亳州学院校园网] 第${i+1}次查找,已找到完整登录表单,开始填充`); usernameInput.value = account.username; passwordInput.value = account.password; usernameInput.dispatchEvent(new Event('input', { bubbles: true })); passwordInput.dispatchEvent(new Event('input', { bubbles: true })); usernameInput.dispatchEvent(new Event('change', { bubbles: true })); passwordInput.dispatchEvent(new Event('change', { bubbles: true })); await sleep(500); loginBtn.click(); console.log('[亳州学院校园网] 已点击登录按钮'); await sleep(3000); await this.checkLoginResult(); return; } console.log(`[亳州学院校园网] 第${i+1}次查找,未找到表单,重试中...`); await sleep(1000); } console.error('[亳州学院校园网] 多次重试后未找到登录表单'); LoginTabLock.release(); // 找不到表单,释放锁 alert('❌ 未找到登录表单,页面可能加载异常,请刷新页面重试'); }, async checkLoginResult() { const online = await NetworkChecker.isOnline(); if (online) { // ★ 登录成功:释放Tab锁(其他Tab检测到网络恢复就不会再开新Tab) LoginTabLock.release(); GM_notification({ title: '🎉 登录成功', text: '祝你上网愉快', timeout: 5000 }); if (AutoCloseManager.isEnabled()) { // 开启自动关闭时不弹 alert,避免阻塞 window.close AutoCloseManager.closeTabIfEnabled(3000); } else { alert('🎉 登录成功,祝你上网愉快'); } } else { // 登录失败:也释放锁,允许下次重试 LoginTabLock.release(); GM_notification({ title: '❌ 登录失败', text: '生活打不败我!请检查账号密码,或点击忘记密码找回', timeout: 5000 }); alert('❌ 登录失败,生活打不败我!\n\n请检查账号密码是否正确,若忘记密码,请点击页面上的「忘记密码」进行找回'); } }, async init() { // ★ 核心修复点2:认证Tab打开时,先检测网络是否已恢复 // 场景:开了多个认证Tab(前一个已登录成功),后面的Tab打开时网络已通 // → 直接关闭自己,不做任何登录操作 if (this.isLoginPage()) { console.log('[亳州学院校园网] 当前在认证登录页,先检测网络状态...'); await sleep(800); // 稍等页面稳定 const alreadyOnline = await NetworkChecker.isOnline(); if (alreadyOnline) { console.log('[亳州学院校园网] 网络已通(其他Tab已登录成功),关闭本冗余标签页'); GM_notification({ title: '✅ 网络已恢复', text: '已由其他标签页完成登录,正在关闭本冗余页', timeout: 2000 }); LoginTabLock.release(); await sleep(1500); try { window.close(); setTimeout(() => { if (!window.closed) { document.body.innerHTML = '
✅ 校园网已由其他标签页登录成功,此标签页可手动关闭
'; } }, 500); } catch (e) {} return; } // 网络未通,正常执行自动登录 await this.fillAndLogin(); return; } // 已登录的 index/logout 页,不执行任何操作 if (this.isLoggedInPage()) { console.log('[亳州学院校园网] 检测到已登录页面,无需操作'); return; } } }; // ===================== 菜单命令 ===================== function registerMenu() { GM_registerMenuCommand('📝 设置账号密码', () => { const username = prompt('请输入你的学号/校园网账号:'); if (!username) return; const password = prompt('请输入你的校园网密码:'); if (!password) return; AccountManager.save(username, password); }); GM_registerMenuCommand('👁️ 查看已保存账号', () => { AccountManager.view(); }); GM_registerMenuCommand('⏱️ 设置检测间隔', () => { const current = GM_getValue('bzxy_check_interval', CONFIG.DEFAULT_CHECK_INTERVAL); const input = prompt(`请输入网络检测间隔(单位:秒,建议5-300之间)`, current); if (!input) return; const second = parseInt(input); if (isNaN(second) || second < 5 || second > 300) { alert('❌ 请输入5-300之间的有效数字'); return; } NetworkChecker.setInterval(second); }); // 登录成功后自动关闭标签页 GM_registerMenuCommand(AutoCloseManager.getStatusText(), () => { AutoCloseManager.toggle(); }); GM_registerMenuCommand('🔍 立即检测网络状态', () => { NetworkChecker.checkNow(); }); GM_registerMenuCommand('📌 后台运行开启教程', () => { alert(`📌 脚本猫后台运行开启步骤: 1. 点击浏览器右上角脚本猫图标 2. 找到「设置」选项并进入 3. 找到并开启「启用后台运行」开关 4. 额外设置:脚本猫→本脚本→设置→添加后台定时任务(建议5分钟执行一次) 开启后,即使关闭所有浏览器窗口,浏览器仍会在后台运行,并最小化到系统托盘,直到您手动退出浏览器。这使后台脚本能够继续运行,断网也能自动重连。 🔴 仅脚本猫支持后台运行功能,油猴/暴力猴等其他脚本管理器无此能力`); }); GM_registerMenuCommand('ℹ️ 关于脚本', () => { alert(`亳州学院校园网自动登录 ==================== 作者:微信 daishuawangke88 适配:亳州学院GiWiFi校园网 版本:1.2.0 开源协议:MIT License ==================== 💬 问题反馈/定制需求 📱 微信:daishuawangke88`); }); } // ===================== 工具函数 ===================== function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // ===================== 首次启动提示 ===================== function firstRunTip() { if (!AccountManager.hasConfig()) { setTimeout(() => { alert('📌 首次使用请先点击脚本猫菜单,设置你的校园网账号密码!'); }, 1000); } const hasShownTip = GM_getValue('bzxy_background_tip', false); if (!hasShownTip) { setTimeout(() => { alert('📌 必看:请在脚本猫设置里开启「后台运行」,关闭浏览器窗口也能自动重连!\n\n开启步骤可在脚本菜单的「后台运行开启教程」中查看'); GM_setValue('bzxy_background_tip', true); }, 1500); } } // ===================== 脚本初始化 ===================== async function init() { console.log('======================================'); console.log('亳州学院校园网自动登录 启动成功 v1.2.0'); console.log('作者微信:daishuawangke88'); console.log('======================================'); // 1. 注册菜单 registerMenu(); // 2. 如果是认证Tab(10.15.1.4域名),执行登录逻辑,不需要启动后台检测循环 if (location.host.includes(CONFIG.LOGIN_HOST)) { await AutoLogin.init(); return; } // 3. 非认证页(其他网页),启动后台网络检测循环 NetworkChecker.startLoop(); // 4. 首次启动提示(只在非认证页显示,避免认证Tab也弹窗) firstRunTip(); } if (document.readyState === 'complete') { init(); } else { window.addEventListener('load', init); } })();