// ==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);
}
})();