【U校园答案显示】 自用版(推荐使用ScriptCat脚本猫)

U校园题目答案显示;不支持单元测试

目前為 2024-11-16 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         【U校园答案显示】 自用版(推荐使用ScriptCat脚本猫)
// @namespace    jayhyy
// @homepage     https://greasyfork.org/zh-CN/scripts/517254-u%E6%A0%A1%E5%9B%AD%E7%AD%94%E6%A1%88%E6%98%BE%E7%A4%BA-%E8%87%AA%E7%94%A8%E7%89%88-%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8scriptcat%E8%84%9A%E6%9C%AC%E7%8C%AB
// @version      1.4
// @description  U校园题目答案显示;不支持单元测试
// @author       jayhyy
// @match        *://ucontent.unipus.cn/_pc_default/pc.html?*
// @connect      *://ucontent.unipus.cn/*
// @connect      unipus.cn
// @grant        GM_xmlhttpRequest
// @run-at       document-end
// @require      https://lib.baomitu.com/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// @license      MIT
// ==/UserScript==

$('head').append('<link href="https://lib.baomitu.com/layui/2.6.8/css/layui.css" rel="stylesheet" type="text/css" />');
$.getScript("https://lib.baomitu.com/layui/2.6.8/layui.js", function(data, status, jqxhr) {
    layui.use('element', function(){
        var element = layui.element;
    });
    layer.closeAll();
    show();
    showanswer();
});

// 感谢ssmjae提供的解密代码
function decryptContent(json) {
    if (json) {
        let r = json.content.slice(7)
        , o = CryptoJS.enc.Utf8.parse("1a2b3c4d" + json.k)
        , i = CryptoJS.enc.Hex.parse(r)
        , a = CryptoJS.enc.Base64.stringify(i)
        , contentJson = JSON.parse(CryptoJS.AES.decrypt(a, o, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.ZeroPadding
        }).toString(CryptoJS.enc.Utf8));
        json = contentJson;
        console.log(json);
    }
    return json;
}

var show = ()=>{
    layer.open({
        type: 1,
        area: ['500px', '600px'],
        offset: ['bottom', 'left'] ,// 距离底部和左侧
        id: 'msgt',
        closeBtn: 1,
        title: "U校园网课助手(答案显示,支持单选、多选、填空、简答、问答)",
        shade: 0,
        maxmin: true,
        anim: 2,
        content:'<div class="layui-collapse"><div class="layui-colla-item"><h2 class="layui-colla-title">公告</h2><div class="layui-colla-content layui-show">脚本已修复</div>'+
        '</div></div>'+
        '<div id="content"><ul></ul><table class="layui-table"> <colgroup> <col width="100"> <col> <col> </colgroup> <thead> <tr>  </tr> </thead> <tbody>  </tbody> </table></div></div></div>'
    });
}

let isShow = true
var showanswer = ()=>{
    if (isShow){
        let url = location.href
        let arr = url.split("/")
        let book = arr[arr.length-7]
        let unit = arr[arr.length-2]
        let answer = []
        GM_xmlhttpRequest({
            method: 'GET',
            url: 'https://ucontentapi.unipus.cn/course/api/content/'+book+'/'+unit+'/default/',
            headers: {
                'X-ANNOTATOR-AUTH-TOKEN': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvcGVuX2lkIjoidHV4NkNCQVc4aGRrcnFZdzc5SEpEWDF2aTR5Z2ptcDUiLCJuYW1lIjoiIiwiZW1haWwiOiIiLCJhZG1pbmlzdHJhdG9yIjoiZmFsc2UiLCJleHAiOjE5MDI5NzAxNTcwMDAsImlzcyI6IlI0aG03RmxQOFdvS0xaMUNmTkllIiwiYXVkIjoiZWR4LnVuaXB1cy5jbiJ9.CwuQmnSmIuts3hHAMf9lT954rKHXUNkps-PfRJp0KnU'
            },
            timeout: 5000,
            onload: function(xhr) {
                if (xhr.status == 200) {
                    let el = '<tr class="layui-bg">' + '</td></tr>'
                    console.log('https://ucontentapi.unipus.cn/course/api/content/'+book+'/'+unit+'/default/')

                    console.log(xhr.responseText)
                    let obj = JSON.parse(xhr.responseText) || {};
                    let deObj = decryptContent(obj);
                    let keyList = Object.keys(deObj);
                    console.log(keyList)
                    Array.prototype.contains = function (obj) {
                        var index = this.length;
                        while (index--) {
                            if (this[index] === obj) {
                                return true;
                            }
                        }
                        return false;
                    }
                    // 选择题
                    if (keyList.contains('questions:questions')) {
                        let questionList = deObj['questions:questions'].questions;
                        let lineCount = 0; // 初始化行数计数器

                        for (let question of questionList) {
                            let result = '';
                            
                            if (question.answers) {
                                result += question.answers.join(' ');
                            }

                            // 在每一行前加上行号
                            lineCount++; // 增加行数
                            el = el + '<tr><td>第' + lineCount + '题: ' + result + question.analysis.html + '</td></tr>';
                        }

                        // 可选:在最后添加总行数统计
                        el = el + '<tr><td colspan="2">总题数: ' + lineCount + '</td></tr>';
                    }
                // 简答题
                if (keyList.contains('shortanswer:shortanswer')) {
                    let questionList = deObj['shortanswer:shortanswer'].questions;
                    let lineCount = 0; // 初始化行数计数器

                    for (let question of questionList) {
                        lineCount++; // 每处理一个题目,行数加 1
                        el = el + '<tr><td>第' + lineCount + '题: ' + deObj['shortanswer:shortanswer'].analysis.html + question.content.html + question.analysis.html + '</td></tr>';
                    }

                    // 可选:在最后添加总行数统计
                    el = el + '<tr><td colspan="2">总题数: ' + lineCount + '</td></tr>';
                }
                    // 填空题
                    if (keyList.contains('questions:scoopquestions')) {
                        let questionList = deObj['questions:scoopquestions'].questions;
                        let lineCount = 0; // 初始化行数计数器

                        for (let question of questionList) {
                            lineCount++; // 每处理一个题目,行数加 1

                            let result = '';
                            if (question.answers) {
                                result += question.answers.join(' ');
                            }

                            // 输出包含行号的 HTML 和复制按钮
                            el = el + '<tr><td>第' + lineCount + '题: ' + result + question.analysis.html + '</td>';
                            el += '<td><button class="layui-btn layui-btn-xs copy-btn" data-content="' + result + '">复制</button></td></tr>';
                        }

                        // 可选:在最后添加总行数统计
                        el = el + '<tr><td colspan="2">总题数: ' + lineCount + '</td></tr>';
                    }

                    // 为复制按钮添加事件监听
                    $(document).on('click', '.copy-btn', function() {
                        var content = $(this).data('content'); // 获取该按钮对应的内容
                        var textarea = document.createElement("textarea"); // 创建一个临时的textarea元素
                        textarea.value = content; // 将内容设置为textarea的值
                        document.body.appendChild(textarea); // 将textarea添加到DOM中
                        textarea.select(); // 选择textarea中的内容
                        document.execCommand("copy"); // 执行复制操作
                        document.body.removeChild(textarea); // 删除临时textarea

                        // 提示用户已复制
                        layer.msg('已复制: ' + content, {icon: 1});
                    });                // 短回答题
                if (keyList.contains('questions:shortanswer')) {
                    let questionList = deObj['questions:shortanswer'].questions;
                    let lineCount = 0; // 初始化行数计数器

                    for (let question of questionList) {
                        lineCount++; // 每处理一个题目,行数加 1

                        let result = '';
                        if (question.answers) {
                            result += question.answers.join(' ');
                        }

                        // 输出包含行号的 HTML
                        el = el + '<tr><td>第' + lineCount + '题: ' + result + question.analysis.html + '</td></tr>';
                    }

                    // 可选:在最后添加总行数统计
                    el = el + '<tr><td colspan="2">总题数: ' + lineCount + '</td></tr>';
                }
                    el = el + '<td>答案结束,如果没有答案,尝试刷新试试</td></td></tr>'
                    $("#content>table>tbody").append($(el));
                }
            }
        });
    }
    isShow = !isShow
}

var show = () => {
    layer.open({
        type: 1,
        area: ['500px', '600px'],
        offset: ['20%', '60%'], // 垂直居中,水平自动
        id: 'msgt',
        closeBtn: 1,
        title: "U校园网课助手(答案显示,支持单选、多选、填空、简答、问答)",
        shade: 0,
        maxmin: true,
        anim: 2,
        content: '<div class="layui-collapse"><div class="layui-colla-item"><h2 class="layui-colla-title">公告</h2><div class="layui-colla-content layui-show">脚本已修复</div>' +
            '</div></div>' +
            '<div id="content"><ul></ul><table class="layui-table"> <colgroup> <col width="100"> <col> <col> </colgroup> <thead> <tr>  </tr> </thead> <tbody>  </tbody> </table>' +
            // 添加刷新按钮
            '<button id="refresh-btn" class="layui-btn layui-btn-normal">一键刷新</button>' +
            '</div></div></div>',
        success: function(layero, index) {
            // 获取浏览器窗口的宽度和弹框的宽度
            var windowWidth = $(window).width();
            var layerWidth = $(layero).outerWidth();
            var layerHeight = $(layero).outerHeight();
            var topOffset = (window.innerHeight - layerHeight) / 2; // 垂直居中
            var rightOffset = windowWidth - layerWidth - 10; // 右侧10px边距

            // 设置弹框的位置,垂直居中,右对齐
            $(layero).css({
                'top': topOffset + 'px',
                'right': rightOffset + 'px'
            });
        }
    });

    // 为刷新按钮绑定点击事件
    $('#refresh-btn').click(function() {
        console.log('刷新页面');
        location.reload(); // 刷新页面
    });
}

$(document).ready(function() {
    // 页面加载完毕时初始化点击检查
    function autoClickConfirmButton() {
        var interval = setInterval(function() {
            var confirmButton = $("span[style*='font-size: 14px'][style*='text-transform: uppercase']");
            if (confirmButton.length > 0) {
                confirmButton.click(); // 自动点击
                console.log("已自动点击确定按钮");
                clearInterval(interval); // 点击后停止检查
            }
        }, 500); // 每500ms检查一次
    }

    // 初始时调用函数检查按钮
    autoClickConfirmButton();

    // 监听URL的变化,检测页面切换
    window.onhashchange = function() {
        console.log("页面切换 detected");
        $("#content>table>tbody").empty(); // 清空之前的内容
        showanswer(); // 重新加载答案
        autoClickConfirmButton(); // 每次页面切换后重新调用点击函数
    };
});


// 检查脚本是否有更新
function checkForUpdates() {
    GM_xmlhttpRequest({
        method: 'GET',
        url: 'https://update.greasyfork.org/scripts/517254/%E3%80%90U%E6%A0%A1%E5%9B%AD%E7%AD%94%E6%A1%88%E6%98%BE%E7%A4%BA%E3%80%91%20%E8%87%AA%E7%94%A8%E7%89%88.meta.js', // 获取脚本元数据
        onload: function(response) {
            const meta = response.responseText;
            const remoteVersion = /@version\s+([\d.]+)/.exec(meta)[1]; // 提取远程版本号
            const currentVersion = GM_info.script.version; // 当前脚本版本

            if (remoteVersion > currentVersion) {
                alert(`检测到新版本:${remoteVersion},请更新脚本!`);
                // 提供更新提醒或自动下载更新
                if (confirm("发现新版本,是否立即更新脚本?")) {
                    window.location.href = "https://update.greasyfork.org/scripts/517254/%E3%80%90U%E6%A0%A1%E5%9B%AD%E7%AD%94%E6%A1%88%E6%98%BE%E7%A4%BA%E3%80%91%20%E8%87%AA%E7%94%A8%E7%89%88.user.js"; // 自动跳转到更新链接
                }
            }
        },
        onerror: function() {
            console.log("无法检查更新,请稍后再试");
        }
    });
}

// 每隔一段时间检查一次更新(例如,每24小时检查一次)
setInterval(checkForUpdates, 86400000); // 24小时检查一次



window.onhashchange=()=>{
    $("#content>table>tbody").empty();
    showanswer();
}