// ==UserScript== // @name 🥇(云端热更新版)超星学习通|知到智慧树--网课小助手|AI自动答题|答案校验|AI+题库调用费用1元100+次|飘飘友情提供|自动跳转任务点|自动答题|超高题库覆盖率|逐渐支持更多平台 // @namespace 飘飘 // @version 1.2.0 // @author PIAOPIAO // @license MIT // @description 轻量级引导脚本,自动从脚本猫平台拉取最新代码执行。支持热更新,无需手动更新脚本。 // @icon http://pan-yz.chaoxing.com/favicon.ico // @match *://*.chaoxing.com/* // @match *://*.xuexitong.com/* // @match *://*.edu.cn/* // @match *://*.nbdlib.cn/* // @match *://*.hnsyu.net/* // @match *://*.gdhkmooc.com/* // @match *://onlineexamh5new.zhihuishu.com/* // @require https://lib.baomitu.com/vue/3.5.0/vue.global.prod.js // @require https://lib.baomitu.com/vue-demi/0.14.7/index.iife.js // @require data:application/javascript,window.Vue%3DVue%3B // @require https://lib.baomitu.com/element-plus/2.7.2/index.full.min.js // @require https://lib.baomitu.com/pinia/2.3.1/pinia.iife.min.js // @require https://lib.baomitu.com/rxjs/7.8.2/rxjs.umd.min.js // @require https://lib.baomitu.com/blueimp-md5/2.19.0/js/md5.min.js // @resource ElementPlus https://lib.baomitu.com/element-plus/2.7.2/index.css // @resource ElementPlusStyle https://lib.baomitu.com/element-plus/2.8.2/index.min.css // @resource ttf https://www.forestpolice.org/ttf/2.0/table.json // @connect scriptcat.org // @connect 43.139.12.117 // @connect 152.136.30.238 // @grant GM_addStyle // @grant GM_getResourceText // @grant GM_getValue // @grant GM_info // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-start // @antifeature payment 答案需调用AI的API需收费 // ==/UserScript== (function () { 'use strict'; const CONFIG = { VERSION_SERVER: { VERSION_URL: 'http://43.139.12.117:3000/version', }, SCRIPTCAT: { SCRIPT_ID: '5597', SCRIPT_NAME: '超星学习通|知到智慧树--网课小助手', CODE_URL: 'https://scriptcat.org/scripts/code/5597/%E8%B6%85%E6%98%9F%E5%AD%A6%E4%B9%A0%E9%80%9A%EF%BD%9C%E7%9F%A5%E5%88%B0%E6%99%BA%E6%85%A7%E6%A0%91--%E7%BD%91%E8%AF%BE%E5%B0%8F%E5%8A%A9%E6%89%8B.user.js' }, CACHE_KEY: 'cloud_script_cache', VERSION_KEY: 'cloud_script_version', LAST_CHECK_KEY: 'last_check_time' }; const log = { info: (msg, ...args) => console.log(`%c[云端脚本] ${msg}`, 'color: #667eea; font-weight: bold;', ...args), success: (msg, ...args) => console.log(`%c[云端脚本] ✓ ${msg}`, 'color: #10b981; font-weight: bold;', ...args), warn: (msg, ...args) => console.warn(`%c[云端脚本] ⚠ ${msg}`, 'color: #f59e0b; font-weight: bold;', ...args), error: (msg, ...args) => console.error(`%c[云端脚本] ✗ ${msg}`, 'color: #ef4444; font-weight: bold;', ...args) }; let loadingWindow = null; function showLoadingWindow() { if (loadingWindow) return; const createLoading = () => { loadingWindow = document.createElement('div'); loadingWindow.id = 'cloud-script-loading-window'; loadingWindow.innerHTML = `
脚本正在加载...
请稍候,正在从云端获取最新代码
`; loadingWindow.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 2147483647; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; `; const style = document.createElement('style'); style.id = 'cloud-script-loading-styles'; style.textContent = ` #cloud-script-loading-window .loading-content { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 60px; border-radius: 16px; text-align: center; box-shadow: 0 20px 60px rgba(102, 126, 234, 0.4); animation: loadingPulse 2s ease-in-out infinite; } #cloud-script-loading-window .loading-spinner { width: 50px; height: 50px; border: 4px solid rgba(255, 255, 255, 0.3); border-top-color: white; border-radius: 50%; animation: loadingSpin 1s linear infinite; margin: 0 auto 20px; } #cloud-script-loading-window .loading-text { color: white; font-size: 18px; font-weight: 600; margin-bottom: 8px; } #cloud-script-loading-window .loading-subtext { color: rgba(255, 255, 255, 0.8); font-size: 13px; } @keyframes loadingSpin { to { transform: rotate(360deg); } } @keyframes loadingPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.02); } } `; document.head.appendChild(style); document.body.appendChild(loadingWindow); log.info('加载窗口已显示'); }; if (document.body) { createLoading(); } else { document.addEventListener('DOMContentLoaded', createLoading); } } function hideLoadingWindow() { if (loadingWindow) { loadingWindow.style.opacity = '0'; loadingWindow.style.transition = 'opacity 0.3s ease'; setTimeout(() => { if (loadingWindow) { loadingWindow.remove(); loadingWindow = null; const style = document.getElementById('cloud-script-loading-styles'); if (style) style.remove(); log.info('加载窗口已关闭'); } }, 300); } } window.__closeLoadingWindow__ = hideLoadingWindow; function compareVersion(v1, v2) { const parts1 = v1.split('.').map(Number); const parts2 = v2.split('.').map(Number); for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) { const p1 = parts1[i] || 0; const p2 = parts2[i] || 0; if (p1 > p2) return 1; if (p1 < p2) return -1; } return 0; } function httpGet(url, isText = false) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: url, timeout: 15000, onload: (response) => { if (response.status === 200) { resolve(isText ? response.responseText : response.response); } else { reject(new Error(`HTTP ${response.status}`)); } }, onerror: () => reject(new Error('网络请求失败')), ontimeout: () => reject(new Error('请求超时')) }); }); } function getLocalCache() { return { version: GM_getValue(CONFIG.VERSION_KEY, ''), code: GM_getValue(CONFIG.CACHE_KEY, ''), lastCheck: GM_getValue(CONFIG.LAST_CHECK_KEY, 0) }; } function saveLocalCache(version, code) { GM_setValue(CONFIG.VERSION_KEY, version); GM_setValue(CONFIG.CACHE_KEY, code); GM_setValue(CONFIG.LAST_CHECK_KEY, Date.now()); } async function fetchLatestVersion() { try { log.info('从服务器获取版本信息...'); const response = await httpGet(CONFIG.VERSION_SERVER.VERSION_URL, true); const data = JSON.parse(response); if (data.code === 200 && data.data && data.data.latestVersion) { log.info(`服务器最新版本: ${data.data.latestVersion}`); return data.data.latestVersion; } else { throw new Error('版本信息格式错误'); } } catch (e) { log.error('获取版本信息失败:', e.message); throw e; } } async function downloadScriptCode() { try { log.info('从脚本猫下载脚本代码...'); const code = await httpGet(CONFIG.SCRIPTCAT.CODE_URL, true); const versionMatch = code.match(/@version\s+(\d+\.\d+\.\d+)/); const version = versionMatch ? versionMatch[1] : 'unknown'; log.success(`下载完成,版本: ${version}`); return { code, version }; } catch (e) { log.error('下载脚本失败:', e.message); throw e; } } function executeCode(code) { try { log.info('执行脚本代码...'); window.__CLOUD_SCRIPT_LOADED__ = true; const codeStart = code.indexOf('// ==/UserScript=='); let executableCode = code; if (codeStart !== -1) { executableCode = code.substring(codeStart + '// ==/UserScript=='.length); } executableCode = executableCode.trim(); if (typeof Vue === 'undefined') { throw new Error('Vue 未加载,请检查 @require 配置'); } log.info('依赖库检查: Vue=' + (typeof Vue !== 'undefined') + ', Pinia=' + (typeof Pinia !== 'undefined') + ', RxJS=' + (typeof rxjs !== 'undefined') + ', MD5=' + (typeof md5 !== 'undefined') + ', ElementPlus=' + (typeof ElementPlus !== 'undefined')); eval(executableCode); log.success('脚本执行成功'); setupMainWindowObserver(); } catch (e) { log.error('脚本执行失败:', e.message); hideLoadingWindow(); throw e; } } function setupMainWindowObserver() { const closeAfterInit = () => { setTimeout(() => { log.info('脚本初始化完成,关闭加载窗口'); hideLoadingWindow(); }, 500); }; if (document.readyState === 'complete') { closeAfterInit(); } else { window.addEventListener('load', closeAfterInit); } } function showNotification(message, type = 'info') { const colors = { info: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', success: 'linear-gradient(135deg, #10b981 0%, #059669 100%)', error: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)' }; const toast = document.createElement('div'); toast.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 12px 20px; background: ${colors[type]}; color: white; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 2147483647; font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; animation: slideIn 0.3s ease; `; toast.textContent = message; if (!document.getElementById('cloud-script-styles')) { const style = document.createElement('style'); style.id = 'cloud-script-styles'; style.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } `; document.head.appendChild(style); } document.body.appendChild(toast); setTimeout(() => { toast.style.animation = 'slideIn 0.3s ease reverse'; setTimeout(() => toast.remove(), 300); }, 3000); } let cloudVersion = GM_getValue(CONFIG.VERSION_KEY, 'unknown'); window.__CLOUD_SCRIPT_VERSION__ = cloudVersion; async function main() { log.info('='.repeat(50)); log.info('云端热更新脚本启动(脚本猫版)'); log.info(`当前云端版本: v${cloudVersion}`); log.info('='.repeat(50)); if (window.self !== window.top) { log.info('检测到在 iframe 中运行,跳过'); return; } // i.mooc.chaoxing.com 首页不显示加载窗口 if (window.location.hostname === 'i.mooc.chaoxing.com') { log.info('检测到 i.mooc.chaoxing.com 首页,跳过加载窗口'); return; } showLoadingWindow(); try { const localCache = getLocalCache(); let code = localCache.code; let version = localCache.version; try { log.info('检查版本更新...'); const latestVersion = await fetchLatestVersion(); if (!localCache.version || compareVersion(latestVersion, localCache.version) > 0) { log.info(`发现新版本: ${localCache.version || '无'} → ${latestVersion}`); const result = await downloadScriptCode(); code = result.code; version = result.version; cloudVersion = version; window.__CLOUD_SCRIPT_VERSION__ = version; saveLocalCache(version, code); if (document.body) { showNotification(`🔄 脚本已更新到 v${version}`, 'success'); } } else { log.success(`已是最新版本 v${localCache.version}`); } } catch (e) { log.warn('检查更新失败,使用本地缓存:', e.message); if (!code) { throw new Error('网络异常且无本地缓存,无法启动脚本'); } } if (code) { executeCode(code); } else { throw new Error('没有可执行的代码'); } } catch (e) { log.error('脚本启动失败:', e.message); hideLoadingWindow(); const showError = () => { const errorDiv = document.createElement('div'); errorDiv.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 24px 32px; background: white; border: 1px solid #fecaca; border-radius: 12px; color: #dc2626; z-index: 999999; font-size: 14px; text-align: center; box-shadow: 0 4px 12px rgba(0,0,0,0.1); `; errorDiv.innerHTML = `
脚本加载失败
${e.message}
请检查网络连接或访问
脚本猫平台
`; document.body.appendChild(errorDiv); }; if (document.body) { showError(); } else { document.addEventListener('DOMContentLoaded', showError); } } } main(); })();