// ==UserScript==
// @name 财小助(官网/校园网访问加强助手)
// @namespace https://caixiaozhu.top:8082/
// @version 1.0.7
// @description 支持重财校园网快速切换与一网通版登录,雨课堂自动唤起扫码,舒心体验官网快登。
// @author 你的名字
// @icon https://caixiaozhu.top:8082/images/logo.png
// @match *://uia.cfec.edu.cn/*
// @match *://10.149.255.220/*
// @match *://jwmis.cfec.edu.cn/*
// @match *://xsc.cfec.edu.cn:*/*
// @match *://jgyth.cfec.edu.cn/*
// @match *://cqrz.yuketang.cn/*
// @match *://caixiaozhu.top:*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @connect *
// @run-at document-start
// @license CC-BY-NC-ND-4.0
// @antifeature none
// ==/UserScript==
/**
* =========================================================================
* 🛡️ 财小助(官网/校园网访问加强助手) - 版权与安全声明
* =========================================================================
* 1. 【隐私安全】本脚本纯本地运行!所有的学号、密码均保存在您个人的浏览器本地
* 存储中(GM_setValue),绝不会向任何第三方服务器发送您的凭证信息。
* 2. 【授权协议】CC-BY-NC-ND-4.0 (署名-非商业性使用-禁止演绎)。
* 您可以自由使用本脚本,但严禁将本代码修改后二次发布,严禁用于任何商业用途!
* 3. 【免责声明】本脚本仅供重庆财经学院师生个人便捷登录使用,请勿在公共电脑
* 上保存密码。因使用本脚本导致的任何账号异常、信息泄露,作者不承担任何责任。
* 4. 【防篡改警告】若您是从非官方渠道下载的本脚本,请立即删除!任何人不得在
* 本脚本中添加窃取密码、劫持请求等恶意代码。
* =========================================================================
*/
(async function () {
'use strict';
// ================= 配置区 =================
const SHORTCUTS = [
{ name: '📚 教务', url: 'http://uia.cfec.edu.cn/cas/login?service=http%3A%2F%2Fjwmis.cfec.edu.cn%2Fsso%2Fzllogin' },
{ name: '🎓 学工', url: 'http://xsc.cfec.edu.cn:82/sso' },
{ name: '📝 请假申请', url: 'http://xsc.cfec.edu.cn:82/leave/LeaveApply/list' },
{ name: '🛠️ 宿舍报修', url: 'http://xsc.cfec.edu.cn:82/dormitoryRepair/stuDormitoryRepair/list' },
{ name: '☔ 雨课堂', url: 'https://cqrz.yuketang.cn/pro/portal/home/' }
];
const FRIEND_LINK = { name: '财小助官网', url: 'https://caixiaozhu.top:8082/' };
const QQ_GROUP_URL = 'https://qm.qq.com/cgi-bin/qm/qr?k=ph5b7OmdNWd2ciiBMmCA9Fh-qfrwoyMf&jump_from=webapi&authKey=eEKIrJWSWKfSir5HNPE5VQZLSkrHcl+jyslBdiF4lFjbFnu5CPk3eGMCm6YIjbVF';
const SCRIPT_HOME_URL = 'https://scriptcat.org/zh-CN/script-show-page/8596';
// 更新提示点击跳转的地址(通常填发布页即可)
const UPDATE_PAGE_URL = 'https://scriptcat.org/zh-CN/script-show-page/8596';
// ==========================================
const CURRENT_VERSION = '1.0.7';
const STORAGE_KEY = 'cfec_uia_config_v10';
const DEFAULT_CONFIG = {
uiaProfiles: [],
campusProfiles: [],
uiaLastUsedId: '',
campusLastUsedId: '',
autoSubmit: true
};
/* ---------- 存储层 ---------- */
const Store = {
async get(key, def) {
try {
if (typeof GM !== 'undefined' && GM.getValue) {
const v = await GM.getValue(key, def);
return v === undefined ? def : v;
}
if (typeof GM_getValue === 'function') {
const v = GM_getValue(key, def);
return v instanceof Promise ? await v : (v === undefined ? def : v);
}
} catch (e) {}
return def;
},
async set(key, val) {
try {
if (typeof GM !== 'undefined' && GM.setValue) { await GM.setValue(key, val); return; }
if (typeof GM_setValue === 'function') {
const r = GM_setValue(key, val);
if (r instanceof Promise) await r;
}
} catch (e) {}
}
};
let config = Object.assign({}, DEFAULT_CONFIG, await Store.get(STORAGE_KEY, {}));
if (!config.uiaProfiles.length && !config.campusProfiles.length) {
const legacy = await Store.get('cfec_uia_config_v9', null) || await Store.get('cfec_uia_config_v8', null);
if (legacy) {
config.uiaProfiles = legacy.uiaProfiles || legacy.profiles || [];
config.campusProfiles = legacy.campusProfiles || [];
config.uiaLastUsedId = legacy.uiaLastUsedId || legacy.lastUsedId || '';
config.campusLastUsedId = legacy.campusLastUsedId || '';
config.autoSubmit = legacy.autoSubmit !== false;
await Store.set(STORAGE_KEY, config);
}
}
function uid() { return 'p_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 7); }
async function persist() { await Store.set(STORAGE_KEY, config); }
/* ---------- 环境判断 ---------- */
const isCampusNet = location.host === '10.149.255.220';
const isUia = location.host.includes('uia.cfec.edu.cn');
const isYuketang = location.host.includes('yuketang.cn');
const getProfiles = () => isCampusNet ? config.campusProfiles : config.uiaProfiles;
const getLastUsedId = () => isCampusNet ? config.campusLastUsedId : config.uiaLastUsedId;
/* ---------- 基础工具 ---------- */
function qs(selectors) {
for (const s of selectors) {
try { const el = document.querySelector(s); if (el) return el; } catch (_) {}
}
return null;
}
function setNativeValue(el, value) {
if (!el) return;
const proto = Object.getPrototypeOf(el);
const desc = Object.getOwnPropertyDescriptor(proto, 'value');
if (desc && desc.set) desc.set.call(el, value); else el.value = value;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
const UIA_USER_SELECTORS = ['#username', 'input[name="username"]', 'input[name="userName"]', 'input[name="loginName"]', 'input[name="account"]', 'input[id*="user" i]', 'input[placeholder*="账号"]', 'input[placeholder*="用户名"]', 'input[placeholder*="学号"]'];
const UIA_PASS_SELECTORS = ['input[type="password"]', '#password', 'input[name="password"]'];
const CAMPUS_USER_SELECTORS = ['input[placeholder*="校内学号"]', 'input[type="text"]'];
const CAMPUS_PASS_SELECTORS = ['input[placeholder*="一站式门户密码"]', 'input[type="password"]'];
const CAPTCHA_IMG_SELECTORS = ['img[src*="captcha" i]', 'img[src*="verify" i]', 'img[src*="validate" i]', 'img[id*="captcha" i]', 'img[class*="captcha" i]', 'img[src*="code" i]'];
const CAPTCHA_INPUT_SELECTORS = ['input[name*="captcha" i]', 'input[id*="captcha" i]', 'input[name*="verify" i]', 'input[id*="verify" i]', 'input[name*="validate" i]', 'input[id*="validate" i]', 'input[placeholder*="验证码"]', 'input[placeholder*="校验码"]'];
function findLoginButton() {
const candidates = document.querySelectorAll('button, input[type="submit"], input[type="button"], a, div[role="button"]');
for (const el of candidates) {
const text = (el.textContent || el.value || '').trim();
if (/^登\s*录$|^登\s*入$|^login$/i.test(text)) return el;
}
return document.querySelector('button[type="submit"], input[type="submit"]');
}
function detectCaptcha() {
if (isCampusNet) return { exists: false, img: null, input: null };
return {
img: qs(CAPTCHA_IMG_SELECTORS),
input: qs(CAPTCHA_INPUT_SELECTORS),
exists: !!(qs(CAPTCHA_IMG_SELECTORS) || qs(CAPTCHA_INPUT_SELECTORS))
};
}
/* =========================================================
检查更新模块
========================================================= */
let hasUpdate = false;
function compareVersion(v1, v2) {
const p1 = v1.split('.').map(Number);
const p2 = v2.split('.').map(Number);
const len = Math.max(p1.length, p2.length);
for (let i = 0; i < len; i++) {
const num1 = p1[i] || 0;
const num2 = p2[i] || 0;
if (num1 > num2) return 1;
if (num1 < num2) return -1;
}
return 0;
}
function checkForUpdates() {
if (hasUpdate) return;
let checkUrl = '';
if (typeof GM_info !== 'undefined' && GM_info.script) {
checkUrl = GM_info.script.updateURL || GM_info.script.downloadURL;
}
if (!checkUrl) return;
try {
GM_xmlhttpRequest({
method: "GET",
url: checkUrl,
headers: { "Cache-Control": "no-cache" },
onload: function(res) {
if (res.status === 200) {
const match = res.responseText.match(/@version\s+([\d.]+)/);
if (match && match[1]) {
const latestVersion = match[1];
if (compareVersion(latestVersion, CURRENT_VERSION) > 0) {
hasUpdate = true;
const link = widgetHost?.shadowRoot?.querySelector('#update-link');
if (link) link.style.display = 'inline';
}
}
}
}
});
} catch (e) {
console.warn('[财小助] 检查更新失败', e);
}
}
/* =========================================================
UI 模块:配置面板
========================================================= */
let panelHost = null;
function openConfigPanel(defaultTab = isCampusNet ? 'campus' : 'uia') {
if (panelHost) { panelHost.style.display = 'flex'; return; }
panelHost = document.createElement('div');
panelHost.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:flex;';
const shadow = panelHost.attachShadow({ mode: 'open' });
let currentTab = defaultTab;
let viewMode = 'list';
let editingProfile = null;
function render() {
const activeList = currentTab === 'uia' ? config.uiaProfiles : config.campusProfiles;
const lastId = currentTab === 'uia' ? config.uiaLastUsedId : config.campusLastUsedId;
shadow.innerHTML = `
${viewMode === 'list' ? `
` : ''}
${viewMode === 'edit' ? renderEditForm() : renderList(activeList, lastId)}
${viewMode === 'edit' ? `
` : `
`}
`;
bindEvents();
}
function renderList(list, lastId) {
let html = '';
if (list.length === 0) html += '暂无保存的账号
';
else html += list.map(p => `
${p.label || p.username}
${p.username}
`).join('');
if (currentTab === 'uia' && config.uiaProfiles.length > 0) html += ``;
else if (currentTab === 'campus' && config.uiaProfiles.length > 0) html += ``;
html += `填表后自动点击登录
`;
return html;
}
function renderEditForm() {
const p = editingProfile || { label: '', username: '', password: '' };
return `
`;
}
function bindEvents() {
const $ = s => shadow.querySelector(s);
$('#btn-close').onclick = () => { panelHost.style.display = 'none'; };
$('#overlay').onclick = (e) => { if (e.target.id === 'overlay') panelHost.style.display = 'none'; };
if (viewMode === 'list') {
if ($('#tab-uia')) $('#tab-uia').onclick = () => { currentTab = 'uia'; render(); };
if ($('#tab-campus')) $('#tab-campus').onclick = () => { currentTab = 'campus'; render(); };
shadow.querySelectorAll('.item').forEach(el => {
el.onclick = (e) => {
if (e.target.closest('[data-action]')) return;
if (currentTab === 'uia') config.uiaLastUsedId = el.dataset.id;
else config.campusLastUsedId = el.dataset.id;
persist(); render(); showToast(`已切换默认账号`);
};
});
shadow.querySelectorAll('[data-action="edit"]').forEach(el => {
el.onclick = (e) => { e.stopPropagation(); editingProfile = (currentTab === 'uia' ? config.uiaProfiles : config.campusProfiles).find(x => x.id === el.dataset.id); viewMode = 'edit'; render(); };
});
shadow.querySelectorAll('[data-action="del"]').forEach(el => {
el.onclick = (e) => {
e.stopPropagation();
if (confirm('确定删除此账号?')) {
if (currentTab === 'uia') {
config.uiaProfiles = config.uiaProfiles.filter(x => x.id !== el.dataset.id);
if (config.uiaLastUsedId === el.dataset.id) config.uiaLastUsedId = config.uiaProfiles[0]?.id || '';
} else {
config.campusProfiles = config.campusProfiles.filter(x => x.id !== el.dataset.id);
if (config.campusLastUsedId === el.dataset.id) config.campusLastUsedId = config.campusProfiles[0]?.id || '';
}
persist(); render();
}
};
});
$('#btn-add').onclick = () => { editingProfile = null; viewMode = 'edit'; render(); };
$('#btn-finish').onclick = () => { panelHost.style.display = 'none'; };
$('#chk-autosubmit').onchange = (e) => { config.autoSubmit = e.target.checked; persist(); };
if ($('#btn-copy-to-campus')) {
$('#btn-copy-to-campus').onclick = () => {
let count = 0;
config.uiaProfiles.forEach(p => { if (!config.campusProfiles.find(c => c.username === p.username)) { config.campusProfiles.push({ id: uid(), label: p.label, username: p.username, password: p.password }); count++; } });
persist(); showToast(`成功复制 ${count} 个账号`); currentTab = 'campus'; render();
};
}
if ($('#btn-copy-from-uia')) {
$('#btn-copy-from-uia').onclick = () => {
let count = 0;
config.uiaProfiles.forEach(p => { if (!config.campusProfiles.find(c => c.username === p.username)) { config.campusProfiles.push({ id: uid(), label: p.label, username: p.username, password: p.password }); count++; } });
persist(); showToast(`成功拉取 ${count} 个账号`); render();
};
}
} else {
$('#btn-back').onclick = () => { viewMode = 'list'; render(); };
$('#btn-save').onclick = () => {
const label = $('#edit-label').value.trim(), user = $('#edit-user').value.trim(), pass = $('#edit-pass').value;
if (!user || !pass) { alert('账号密码不能为空'); return; }
const list = currentTab === 'uia' ? config.uiaProfiles : config.campusProfiles;
if (editingProfile) { editingProfile.label = label; editingProfile.username = user; editingProfile.password = pass; }
else {
const np = { id: uid(), label: label || user, username: user, password: pass };
list.push(np);
if (currentTab === 'uia' && !config.uiaLastUsedId) config.uiaLastUsedId = np.id;
if (currentTab === 'campus' && !config.campusLastUsedId) config.campusLastUsedId = np.id;
}
persist(); viewMode = 'list'; render();
};
}
}
document.documentElement.appendChild(panelHost);
render();
}
/* =========================================================
自动化执行模块
========================================================= */
let isAutoRunning = false;
function showUiaInterruptCard(profile, uEl, pEl) {
const host = document.createElement('div');
host.id = 'cfec-uia-interrupt';
host.style.cssText = 'position:fixed; top:15%; left:50%; transform:translateX(-50%); z-index:2147483647;';
const shadow = host.attachShadow({ mode: 'open' });
let countdown = 3, paused = false, timer = null;
shadow.innerHTML = `
🔓
正在自动登录
账号: ${profile.label || profile.username}
`;
document.documentElement.appendChild(host);
const bar = shadow.getElementById('bar');
shadow.getElementById('card').onmouseenter = () => { paused = true; };
shadow.getElementById('card').onmouseleave = () => { paused = false; };
shadow.getElementById('btn-cancel').onclick = () => { clearInterval(timer); host.remove(); isAutoRunning = false; openConfigPanel('uia'); };
setTimeout(() => { bar.style.width = '0%'; }, 50);
timer = setInterval(() => {
if (paused) return;
countdown--;
if (countdown <= 0) { clearInterval(timer); host.remove(); executeLogin(uEl, pEl); }
}, 1000);
}
function executeLogin(uEl, pEl) {
const captcha = detectCaptcha();
if (captcha.exists && captcha.input) {
captcha.input.style.outline = '3px solid #ef4444';
captcha.input.style.boxShadow = '0 0 0 4px rgba(239,68,68,.2)';
captcha.input.focus();
showToast('⚠️ 检测到验证码,请手动输入');
const submitFn = () => { const btn = findLoginButton(); if (btn) btn.click(); };
captcha.input.addEventListener('input', () => {
const len = (captcha.input.value || '').trim().length;
if (len >= (captcha.input.maxLength > 0 ? captcha.input.maxLength : 4)) submitFn();
});
captcha.input.addEventListener('keydown', (e) => { if (e.key === 'Enter') submitFn(); });
} else if (config.autoSubmit) {
const btn = findLoginButton();
if (btn) btn.click();
else pEl.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter', keyCode: 13 }));
}
isAutoRunning = false;
}
function startAutoLogin() {
if (isAutoRunning) return;
const profiles = getProfiles();
if (profiles.length === 0) return;
const uEl = qs(isCampusNet ? CAMPUS_USER_SELECTORS : UIA_USER_SELECTORS);
const pEl = qs(isCampusNet ? CAMPUS_PASS_SELECTORS : UIA_PASS_SELECTORS);
if (!uEl || !pEl || (uEl.value && pEl.value)) return;
isAutoRunning = true;
const lastId = getLastUsedId();
const profile = profiles.find(p => p.id === lastId) || profiles[0];
setNativeValue(uEl, profile.username);
setNativeValue(pEl, profile.password);
if (isCampusNet) {
showToast(`正在登录校园网: ${profile.label || profile.username}`);
setTimeout(() => executeLogin(uEl, pEl), 300);
} else {
showUiaInterruptCard(profile, uEl, pEl);
}
}
/* =========================================================
可拖拽侧边栏:财小助
========================================================= */
let widgetHost = null;
let isExpanded = isUia;
function injectSidebarTab() {
if (widgetHost) return;
widgetHost = document.createElement('div');
widgetHost.id = 'cfec-uia-sidebar';
widgetHost.style.cssText = 'position:fixed; z-index:2147483640; right:20px; bottom:20px;';
const shadow = widgetHost.attachShadow({ mode: 'open' });
function render() {
shadow.innerHTML = `
v${CURRENT_VERSION}
检测到更新
`;
bindEvents();
// 如果检测到更新,直接展示
if (hasUpdate) {
const link = shadow.querySelector('#update-link');
if (link) link.style.display = 'inline';
}
}
function bindEvents() {
const $ = s => shadow.querySelector(s);
$('#btn-expand').onclick = () => {
isExpanded = true;
render();
};
$('#btn-close').onclick = () => {
isExpanded = false;
render();
};
// 绑定折叠面板点击事件
shadow.querySelectorAll('.menu-title[data-target]').forEach(el => {
el.onclick = () => {
const targetId = el.dataset.target;
const content = shadow.getElementById(targetId);
const isActive = content.classList.contains('active');
shadow.querySelectorAll('.menu-title[data-target]').forEach(t => t.classList.remove('active'));
shadow.querySelectorAll('.menu-content').forEach(c => c.classList.remove('active'));
if (!isActive) {
el.classList.add('active');
content.classList.add('active');
}
};
});
// 绑定跳转链接,拦截未登录状态下的快捷访问
shadow.querySelectorAll('.nav-link').forEach(el => {
el.onclick = (e) => {
e.preventDefault();
const url = el.dataset.url;
const isBlank = el.dataset.blank === 'true';
const isShortcut = SHORTCUTS.some(s => s.url === url);
if (isShortcut && isUia && !checkIsLoggedIn()) {
showLoginRequiredPrompt();
return;
}
if (isBlank) {
window.open(url, '_blank');
} else {
window.location.href = url;
}
};
});
// 绑定版本号跳转主页
const verBtn = shadow.querySelector('#version-btn');
if (verBtn) {
verBtn.onclick = () => {
window.open(SCRIPT_HOME_URL, '_blank');
};
}
// 绑定更新提示跳转
const updateLink = shadow.querySelector('#update-link');
if (updateLink) {
updateLink.onclick = () => {
window.open(UPDATE_PAGE_URL, '_blank');
};
}
$('#btn-config').onclick = () => {
openConfigPanel(isCampusNet ? 'campus' : 'uia');
};
}
document.documentElement.appendChild(widgetHost);
render();
}
/* =========================================================
状态检测与辅助功能
========================================================= */
function checkIsLoggedIn() {
if (isCampusNet) return !qs(CAMPUS_PASS_SELECTORS);
const url = location.href;
if (url.includes('/myAffairs')) return true;
const bodyEl = document.body;
if (!bodyEl) return false;
const text = bodyEl.textContent || '';
if (['退出登录', '个人中心', '我的事务', '欢迎您'].some(m => text.includes(m))) return true;
const hasLoginBtn = Array.from(document.querySelectorAll('a, button, span, div')).some(el => {
const t = (el.innerText || '').trim();
const r = el.getBoundingClientRect();
return (t === '登录' || t === '登录/注册' || t === '用户登录') && r.width > 0 && r.height > 0 && r.top < 200 && r.left > window.innerWidth / 2;
});
return !hasLoginBtn;
}
let alertTimer = null;
function showProminentAlert() {
if (isCampusNet) return;
if (document.getElementById('cfec-uia-alert-box')) return;
if (sessionStorage.getItem('cfec_uia_dismiss_alert') === '1') return;
clearTimeout(alertTimer);
alertTimer = setTimeout(() => {
if (checkIsLoggedIn()) return;
const host = document.createElement('div');
host.id = 'cfec-uia-alert-box';
host.style.cssText = 'position:fixed;top:15%;left:50%;transform:translateX(-50%);z-index:2147483647;';
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
⚠️
您当前尚未登录
为了不影响您的正常使用,请先登录系统。
`;
document.documentElement.appendChild(host);
shadow.querySelector('#btn-login').onclick = () => {
sessionStorage.removeItem('cfec_uia_dismiss_alert');
window.location.href = '/login';
};
shadow.querySelector('#btn-close').onclick = () => {
host.remove();
sessionStorage.setItem('cfec_uia_dismiss_alert', '1');
};
}, 1500);
}
function showNoProfileAlert() {
if (document.getElementById('cfec-uia-no-profile-box')) return;
if (sessionStorage.getItem('cfec_uia_no_profile_dismissed') === '1') return;
const host = document.createElement('div');
host.id = 'cfec-uia-no-profile-box';
host.style.cssText = 'position:fixed;top:15%;left:50%;transform:translateX(-50%);z-index:2147483647;';
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
📢
尚未配置登录凭据
请添加账号密码,以便财小助为您提供自动登录服务。
`;
document.documentElement.appendChild(host);
shadow.querySelector('#btn-login').onclick = () => {
host.remove();
openConfigPanel(isCampusNet ? 'campus' : 'uia');
};
shadow.querySelector('#btn-close').onclick = () => {
host.remove();
sessionStorage.setItem('cfec_uia_no_profile_dismissed', '1');
};
}
let pwdErrorAlertShown = false;
function showPasswordErrorAlert() {
if (pwdErrorAlertShown) return;
pwdErrorAlertShown = true;
const host = document.createElement('div');
host.id = 'cfec-uia-pwd-error-box';
host.style.cssText = 'position:fixed;top:20%;left:50%;transform:translateX(-50%);z-index:2147483647;';
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
🚫
密码错误提示
系统检测到您的密码输入错误。
请前往 A校区1123 更改密码后再试。
`;
document.documentElement.appendChild(host);
shadow.querySelector('#btn-close').onclick = () => {
host.remove();
};
}
function showLoginRequiredPrompt() {
if (document.getElementById('cfec-uia-login-required-box')) return;
const host = document.createElement('div');
host.id = 'cfec-uia-login-required-box';
host.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;background:rgba(15,23,42,0.4);backdrop-filter:blur(2px);animation:fadeIn 0.2s ease;';
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
`;
document.documentElement.appendChild(host);
host.onclick = () => {
host.remove();
};
}
function checkPasswordError() {
if (pwdErrorAlertShown) return;
if (!isUia && !isCampusNet) return;
const isLoginPage = isCampusNet || /\/login/i.test(location.pathname) || (qs(UIA_PASS_SELECTORS) !== null);
if (!isLoginPage) return;
const bodyText = document.body ? (document.body.innerText || '') : '';
const errorKeywords = ['密码错误', '账号或密码错误', '密码不正确', '用户名或密码错误', '密码有误'];
if (errorKeywords.some(kw => bodyText.includes(kw))) {
showPasswordErrorAlert();
}
}
function showToast(msg) {
let toast = document.getElementById('cfec-uia-toast');
if (!toast) {
toast = document.createElement('div');
toast.id = 'cfec-uia-toast';
toast.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:2147483647;pointer-events:none;';
document.documentElement.appendChild(toast);
}
const shadow = toast.shadowRoot || toast.attachShadow({ mode: 'open' });
shadow.innerHTML = `${msg}
`;
toast.style.display = 'block';
clearTimeout(toast._timer);
toast._timer = setTimeout(() => { toast.style.display = 'none'; }, 2500);
}
function checkPageState() {
injectSidebarTab();
if (isYuketang) {
const loginBtn = Array.from(document.querySelectorAll('button, a, div, span')).find(el => {
const t = (el.innerText || '').trim();
const r = el.getBoundingClientRect();
return (t === '登录' || t === '登录/注册') && r.width > 0 && r.height > 0 && r.top < 200;
});
if (loginBtn && !document.getElementById('cfec-yuketang-cliked')) {
const flag = document.createElement('div');
flag.id = 'cfec-yuketang-cliked';
flag.style.display = 'none';
document.body.appendChild(flag);
loginBtn.click();
setTimeout(() => { if (flag.parentNode) flag.remove(); }, 10000);
}
return;
}
if (!isUia && !isCampusNet) return;
checkPasswordError();
const hasAnyProfile = config.uiaProfiles.length > 0 || config.campusProfiles.length > 0;
if (!hasAnyProfile) {
showNoProfileAlert();
return;
}
const isLoginPage = isCampusNet || /\/login/i.test(location.pathname) || (qs(UIA_PASS_SELECTORS) !== null);
if (isLoginPage) {
const alertBox = document.getElementById('cfec-uia-alert-box');
if (alertBox) alertBox.remove();
startAutoLogin();
return;
}
const loggedIn = checkIsLoggedIn();
if (loggedIn) {
clearTimeout(alertTimer);
const alertBox = document.getElementById('cfec-uia-alert-box');
if (alertBox) alertBox.remove();
} else {
showProminentAlert();
}
}
let checkTimeout = null;
function scheduleCheck() {
if (checkTimeout) clearTimeout(checkTimeout);
checkTimeout = setTimeout(checkPageState, 300);
}
if (typeof GM_registerMenuCommand === 'function') {
GM_registerMenuCommand('⚙️ 打开账号配置面板', () => openConfigPanel());
}
let lastUrl = location.href;
new MutationObserver(() => {
if (location.href !== lastUrl) {
lastUrl = location.href;
scheduleCheck();
}
}).observe(document, { subtree: true, childList: true });
new MutationObserver(scheduleCheck).observe(document.documentElement, { childList: true, subtree: true });
window.addEventListener('DOMContentLoaded', scheduleCheck);
setTimeout(scheduleCheck, 1000);
setTimeout(scheduleCheck, 3000);
// 每次运行脚本时,静默检测一次更新
setTimeout(checkForUpdates, 1500);
})();