Greasy Fork

来自缓存

Greasy Fork is available in English.

🥇(免更新版)超星学习通|知到智慧树--网课小助手|AI自动答题|答案校验|AI+题库调用费用1元100+次|飘飘友情提供|自动跳转任务点|自动答题|超高题库覆盖率|逐渐支持更多平台

轻量级引导脚本,自动从脚本猫平台拉取最新代码执行。支持热更新,无需手动更新脚本。

在您安装前,Greasy Fork 希望您知道此脚本声明其包含了一些负面功能。这些功能也许会使脚本作者获利,而不能给您带来任何直接的金钱收益。

您只有在付费后才能使用脚本的全部功能。Greasy Fork 未参与到支付的流程,因此无法验证您是否获得了有价值的东西,亦无法帮助您申请退款。 脚本作者的说明: 答案需调用AI的API需收费

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         🥇(免更新版)超星学习通|知到智慧树--网课小助手|AI自动答题|答案校验|AI+题库调用费用1元100+次|飘飘友情提供|自动跳转任务点|自动答题|超高题库覆盖率|逐渐支持更多平台
// @namespace    飘飘
// @version      1.3.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 = `
                <div class="loading-content">
                    <div class="loading-spinner"></div>
                    <div class="loading-text">脚本正在加载...</div>
                    <div class="loading-subtext">请稍候,正在从云端获取最新代码</div>
                </div>
            `;
            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, headers = {}) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                headers: headers,
                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, { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' });
            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 = `
                    <div style="font-size: 32px; margin-bottom: 12px;">❌</div>
                    <div style="font-weight: bold; margin-bottom: 8px; font-size: 16px;">脚本加载失败</div>
                    <div style="color: #991b1b; margin-bottom: 12px;">${e.message}</div>
                    <div style="color: #7f1d1d; font-size: 12px;">
                        请检查网络连接或访问<br>
                        <a href="https://scriptcat.org/zh-CN/script-show-page/5597" target="_blank" style="color: #667eea;">脚本猫平台</a>
                    </div>
                `;
                document.body.appendChild(errorDiv);
            };
            if (document.body) {
                showError();
            } else {
                document.addEventListener('DOMContentLoaded', showError);
            }
        }
    }

    main();

})();