宜宾智慧校园助手

智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频

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

    // ==UserScript==
    // @name         宜宾智慧校园助手
    // @namespace    智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案===来自计算机科学与技术学院--修改自若离智慧校园
    // @version      5.2
    // @description  智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频
    // @author       计算机科学与技术学院---软工
    // @match        https://mooc.yibinu.edu.cn/*
    // @icon         https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png
    // @resource cs1 https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.css
    // @resource cs2 https://pan.ruoli.cc/s/8b0cc4
    // @require      https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js
    // @require      https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.min.js
    // @require      https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/xlsx.full.min.js
    // @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
    // @run-at       document-end
    // @grant        GM_xmlhttpRequest
    // @grant        GM_addStyle
    // @grant        GM_getResourceText
    // ==/UserScript==

// 脚本初始化
var setting = {
    'logs': ['初始化脚本完成,', '当前脚本版本:V5.2'],
    'datas': [],
    'secretKey': '爹', // 暗号
    'validDuration': 2 * 24 * 60 * 60 * 1000,
};

// 日志
function log(logText){
    setting.logs.unshift(logText);

    // Ensure Vue instance logs are updated
    if (window.vue) {
        window.vue.$nextTick(() => {
            window.vue.logs = [...setting.logs];
        });
    }
}

// 添加一个清理HTML标签的函数
function cleanHtmlTags(text) {
    if (!text) return '';

    // 先将HTML转换为纯文本
    let temp = document.createElement('div');
    temp.innerHTML = text;
    let cleanText = temp.textContent || temp.innerText;

    // 清理多余的空白字符
    cleanText = cleanText.replace(/\s+/g, ' ').trim();

    return cleanText;
}

// 从后台获取答案
function getAnswer(url, data){
    log('获取答案中');
    let id = url.match(/\/examSubmit\/(\d+)\/getExamPaper/)[1];
    GM_xmlhttpRequest({
        method: "post",
        url: url,
        data: data,
        dataType: 'json',
        headers: {
            'Origin': location.origin,
            'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
            'Content-type': 'application/x-www-form-urlencoded;charset=utf-8',
            'Referer': `https://mooc.yibinu.edu.cn/examTest/stuExamList/${id}.mooc`
        },
        onload: function(res){
            if(res.status == 200){
                try {
                    let response = JSON.parse(res.responseText);
                    if (response && response.paper && response.paper.paperStruct) {
                        log("获取答案成功正在格式化答案!");
                        formatAnswer(response.paper.paperStruct);
                    } else {
                        log("答案数据格式异常,请检查接口返回");
                    }
                } catch (error) {
                    log("解析答案数据失败:" + error.message);
                }
            } else {
                log("获取答案失败,状态码:" + res.status);
            }
        },
        onerror: function(error) {
            log("请求答案失败:" + error.message);
        }
    });
}
//格式化答案
function formatAnswer(str) {
    try {
        setting.datas = []; // 清空之前的数据
        if (!Array.isArray(str)) {
            log("答案数据式错误");
            return;
        }

        str.forEach((listItem, index) => {
            if (!listItem.quiz) {
                return;
            }

            // 使用cleanHtmlTags清理题目内容
            var question = cleanHtmlTags(listItem.quiz.quizContent) || "未知题目";
            var options = {};
            var optionContents = {};  // 存储选项内容
            var answer = [];
            const questionNum = (index + 1).toString();

            // 处理选择题
            if (listItem.quiz.quizOptionses && listItem.quiz.quizOptionses.length > 0) {
                listItem.quiz.quizOptionses.forEach((optionItem, idx) => {
                    if (optionItem && optionItem.optionId !== undefined) {
                        const optionLabel = String.fromCharCode(65 + idx);
                        options[optionItem.optionId] = optionLabel;
                        optionContents[optionItem.optionId] = optionItem.optionContent || '';
                    }
                });

                // 处理答案
                if (listItem.quiz.quizResponses) {
                    listItem.quiz.quizResponses.forEach(answerItem => {
                        if (answerItem && options[answerItem.optionId]) {
                            const label = options[answerItem.optionId];
                            const content = optionContents[answerItem.optionId];
                            answer.push(`${label}.${content}`);
                        }
                    });
                }

                // 合并序号和选项标签
                const answerLabels = listItem.quiz.quizResponses
                    .map(item => options[item.optionId])
                    .join('');
                const idAndOptions = `${questionNum}.${answerLabels}`;

                setting.datas.push({
                    'key': index.toString(),
                    'idAndOptions': idAndOptions,
                    'question': question,
                    'answer': answer.join('\n')  // 每个选项答案换行显示
                });
            } else {
                // 处理填空题
                if (listItem.quiz.quizResponses) {
                    const fillAnswers = [];
                    listItem.quiz.quizResponses.forEach(answerItem => {
                        if (answerItem && answerItem.responseContent) {
                            fillAnswers.push(answerItem.responseContent);
                        }
                    });

                    setting.datas.push({
                        'key': index.toString(),
                        'idAndOptions': `${questionNum}.(填空)`,
                        'question': question,
                        'answer': fillAnswers.join('\n')  // 多个填空答案换行显示
                    });
                }
            }
        });

        // 更新 Vue 实例中的数据
        if (window.vue) {
            Vue.nextTick(() => {
                window.vue.answerList = [...setting.datas];
                window.vue.hasAnswer = true; // 设置答案获取状态为 true
            });
        }

        log(`成功处理 ${setting.datas.length} 道题目`);
        log('答案获取完成,可以切换到答案列表查看');
    } catch (error) {
        log("格式化答案时出错:" + error.message);
        if (window.vue) {
            window.vue.hasAnswer = false;
        }
    }
}
//初始化界面
function initView(){
    // 检查验证是否有效
    const validUntil = localStorage.getItem('scriptValidUntil');
    if (validUntil && parseInt(validUntil) > Date.now()) {
        // 验证仍然有效,直接继续初始化
        continueInit();
        return;
    }

    // 验证已过期或未验证,显示验证界面
    const createModal = () => {
        const modalHtml = `
            <div id="secretModal" style="
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.5);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 10000;
            ">
                <div style="
                    background: white;
                    padding: 30px;
                    border-radius: 15px;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.2);
                    width: 320px;
                    text-align: center;
                    animation: modalFadeIn 0.3s ease;
                ">
                    <img src="https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png" style="
                        width: 64px;
                        height: 64px;
                        margin-bottom: 15px;
                    ">
                    <h2 style="
                        margin: 0 0 20px 0;
                        color: #333;
                        font-size: 20px;
                        font-weight: 500;
                    ">请输入暗号</h2>
                    <input type="text" id="secretInput" style="
                        width: 100%;
                        padding: 12px;
                        margin-bottom: 15px;
                        border: 2px solid #e8e8e8;
                        border-radius: 8px;
                        font-size: 16px;
                        outline: none;
                        transition: all 0.3s;
                        box-sizing: border-box;
                    " placeholder="请输入暗号...">
                    <button onclick="verifySecret()" style="
                        width: 100%;
                        padding: 12px;
                        border: none;
                        background-color: #1890ff;
                        color: white;
                        border-radius: 8px;
                        font-size: 16px;
                        cursor: pointer;
                        transition: all 0.3s;
                        box-sizing: border-box;
                    ">验证</button>
                </div>
            </div>
        `;

        // 添加动画样式
        const styleSheet = document.createElement("style");
        styleSheet.textContent = `
            @keyframes modalFadeIn {
                from {
                    opacity: 0;
                    transform: translateY(-20px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            #secretInput:focus {
                border-color: #1890ff;
                box-shadow: 0 0 0 2px rgba(24,144,255,0.2);
            }
            #secretModal button:hover {
                background-color: #40a9ff;
            }
            #secretModal button:active {
                background-color: #096dd9;
            }
        `;
        document.head.appendChild(styleSheet);
        document.body.insertAdjacentHTML('beforeend', modalHtml);

        // 添加回车键监听
        document.getElementById('secretInput').addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                window.verifySecret();
            }
        });

        // 自动聚焦输入框
        setTimeout(() => {
            document.getElementById('secretInput').focus();
        }, 100);
    };

    // 更新验证函数
    window.verifySecret = () => {
        const input = document.getElementById('secretInput').value;
        if(!input) {
            const inputElem = document.getElementById('secretInput');
            inputElem.style.borderColor = '#ff4d4f';
            inputElem.style.animation = 'shake 0.5s';
            setTimeout(() => {
                inputElem.style.borderColor = '#e8e8e8';
                inputElem.style.animation = '';
            }, 1000);
            return;
        }

        if(input !== setting.secretKey) {
            const modalDiv = document.querySelector('#secretModal > div');
            modalDiv.style.animation = 'shake 0.5s';
            document.getElementById('secretInput').style.borderColor = '#ff4d4f';
            setTimeout(() => {
                modalDiv.style.animation = '';
                document.getElementById('secretInput').style.borderColor = '#e8e8e8';
            }, 1000);
            return;
        }

        // 保存验证时间
        const validUntil = Date.now() + setting.validDuration;
        localStorage.setItem('scriptValidUntil', validUntil.toString());

        // 添加关闭动画
        const modal = document.getElementById('secretModal');
        modal.style.animation = 'modalFadeOut 0.3s ease';
        setTimeout(() => {
            modal.remove();
            continueInit();
        }, 300);
    };

    // 添加抖动动画
    const shakeStyle = document.createElement("style");
    shakeStyle.textContent = `
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
            20%, 40%, 60%, 80% { transform: translateX(5px); }
        }
        @keyframes modalFadeOut {
            from {
                opacity: 1;
            }
            to {
                opacity: 0;
            }
        }
    `;
    document.head.appendChild(shakeStyle);

    createModal();
}

// 将原来的初始化代码移动到新的函数中
function continueInit() {
    var $div =$('<div class="rlBox minimized">' +
        '   <a-card title="宜宾学院智慧校园助手" style="width: 100%;height: 100%;">' +
        '       <template slot="extra">' +
        '           <span style="margin-right: 10px; font-size: 12px; color: #999;">{{validTimeRemaining}}</span>' +
        '           <a-button :type="buttonColor" shape="circle" :icon="buttonIcon" @click="toClose" size="small"/>' +
        '       </template>' +
        '       <div style="margin-bottom: 15px;" v-show="!close">' +
        '           <a-button-group style="width: 100%;">' +
        '               <a-button type="danger" style="width: 33.33%;" @click="passVideo()">秒过视频</a-button>' +
        '               <a-button type="primary" style="width: 33.33%;" @click="exportExcel()">导出题库</a-button>' +
        '               <a-button type="success" style="width: 33.33%;" @click="clearLogs()">清除日志</a-button>' +
        '           </a-button-group>' +
        '       </div>' +
        '       <a-tabs default-active-key="1" @change="callback" v-show="!close">' +
        '           <a-tab-pane key="1" tab="运行日志">' +
        '               <div class="rl-panel log">' +
        '                   <p v-for="item in logs" class="log_content">' +
        '                       {{item}}' +
        '                   </p>' +
        '               </div>' +
        '           </a-tab-pane>' +
        '           <a-tab-pane key="2" :tab="answerTabTitle" :disabled="!hasAnswer">' +
        '               <div class="rl-panel">' +
        '                   <a-table id="rlTable"' +
        '                   :pagination="false" bordered size="small" :columns="columns" :data-source="answerList">' +
        '                   </a-table>' +
        '               </div>' +
        '           </a-tab-pane>' +
        '       </a-tabs>' +
        '   </a-card>' +
        '</div>');

    // 更新样式
    const customStyle = `
        .rlBox {
            position: fixed;
            top: 10px;
            right: 10px;
            width: 400px;
            z-index: 9999;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 10px;
            transition: all 0.3s ease;
            transform: none !important;
            overflow: hidden;
        }

        /* 优化最小化状态 */
        .rlBox.minimized {
            width: 40px !important;
            height: 40px !important;
            padding: 0 !important;
            overflow: hidden;
            opacity: 0.8;
            cursor: pointer;
            border-radius: 50%;
            background: #1890ff;
            box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        /* 按钮样式优化 */
        .ant-btn-danger {
            background: #ff4d4f !important;
            border-color: #ff4d4f !important;
            color: white !important;
        }

        .ant-btn-danger:hover {
            background: #ff7875 !important;
            border-color: #ff7875 !important;
        }

        .ant-btn-primary {
            background: #1890ff !important;
            border-color: #1890ff !important;
        }

        .ant-btn-primary:hover {
            background: #40a9ff !important;
            border-color: #40a9ff !important;
        }

        .ant-btn-success {
            background: #52c41a !important;
            border-color: #52c41a !important;
            color: white !important;
        }

        .ant-btn-success:hover {
            background: #73d13d !important;
            border-color: #73d13d !important;
        }

        /* 最小化状态下的卡片样式 */
        .rlBox.minimized .ant-card {
            background: transparent;
            border: none;
            box-shadow: none;
        }

        /* 最小化状态下的标题隐藏 */
        .rlBox.minimized .ant-card-head-title {
            display: none;
        }

        /* 最小化状态下的展开按钮样式 */
        .rlBox.minimized .ant-btn-circle {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: transparent !important;
            border: 2px solid white !important;
            color: white !important;
            box-shadow: none;
        }

        .rlBox.minimized .ant-btn-circle:hover {
            background: rgba(255, 255, 255, 0.2) !important;
        }

        /* 最小化状态悬停效果 */
        .rlBox.minimized:hover {
            opacity: 1;
            box-shadow: 0 6px 16px rgba(24, 144, 255, 0.4);
            transform: translateY(-2px) !important;
        }

        /* 移动端适配 */
        @media screen and (max-width: 768px) {
            .rlBox {
                width: 300px;
            }

            .rlBox.minimized {
                width: 36px !important;
                height: 36px !important;
            }
        }

        /* 表格容器样式 */
        .rl-panel {
            height: auto;
            max-height: calc(100vh - 200px);
            overflow: hidden;
        }

        /* 表格样式优化 */
        .ant-table-wrapper {
            overflow-x: auto;
            overflow-y: hidden;
        }

        .ant-table {
            min-width: 800px;
            background: transparent;
        }

        /* 表格滚动条样式 */
        .ant-table-wrapper::-webkit-scrollbar {
            height: 8px;
            width: 8px;
        }

        .ant-table-wrapper::-webkit-scrollbar-thumb {
            background: #d9d9d9;
            border-radius: 4px;
        }

        .ant-table-wrapper::-webkit-scrollbar-track {
            background: #f0f0f0;
            border-radius: 4px;
        }

        /* 表格单元格样式 */
        .ant-table-tbody > tr > td {
            white-space: normal;
            word-break: break-word;
            padding: 8px 16px;
            line-height: 1.5;
        }

        /* 表格头部样式 */
        .ant-table-thead > tr > th {
            background: #f5f5f5;
            padding: 12px 16px;
            white-space: nowrap;
        }

        /* 确保表格不会挤压内容 */
        #rlTable {
            table-layout: fixed;
        }

        /* 移动端适配 */
        @media screen and (max-width: 768px) {
            .ant-table {
                min-width: 600px;
            }

            .ant-table-tbody > tr > td {
                padding: 6px 12px;
            }

            .ant-table-thead > tr > th {
                padding: 8px 12px;
            }
        }
    `;

    $("body").append($div);
    GM_addStyle(GM_getResourceText("cs1"));
    GM_addStyle(GM_getResourceText("cs2"));
    GM_addStyle(customStyle);

    var vue = new Vue({
        el: '.rlBox',
        data:{
            logs: setting.logs,
            close: true,
            key: '1',
            columns:[
                {
                    title: '序号.选项',
                    dataIndex: 'idAndOptions',
                    key: 'idAndOptions',
                    width: '100px',
                    fixed: 'left',
                    align: 'center'
                },
                {
                    title: '题目',
                    dataIndex: 'question',
                    key: 'question',
                    width: '400px',
                    ellipsis: true
                },
                {
                    title: '答案',
                    dataIndex: 'answer',
                    key: 'answer',
                    width: '300px',
                    customRender: (text) => {
                        return text ? text.split('\n').join('<br/>') : '';
                    }
                }
            ],
            answerList: [],  // 初化为空数组
            isDragging: false,
            currentX: 0,
            currentY: 0,
            initialX: 0,
            initialY: 0,
            xOffset: 0,
            yOffset: 0,
            hasAnswer: false, // 添加答案获取状态标志
            validUntil: localStorage.getItem('scriptValidUntil') || null,
        },
        mounted() {
            window.vue = this;
            this.initDragEvents();

            // 修改初始化位置设置
            const box = document.querySelector('.rlBox');
            box.style.right = '0px';
            box.style.left = 'auto';
            box.setAttribute('data-expand-side', 'right'); // 设置默认展开方向

            // 添加窗口大小改变监听
            window.addEventListener('resize', this.checkPosition);

            // 每分钟更新一次验证时间显示
            setInterval(() => {
                this.validUntil = localStorage.getItem('scriptValidUntil');
            }, 60000);
        },
        computed:{
            isShow(){
                return this.close ? 0.8 : 1.0;
            },
            buttonIcon(){
                return this.close ? 'plus' : 'minus';
            },
            buttonColor(){
                return this.close ? 'primary' : 'default';
            },
            answerTabTitle() {
                return this.hasAnswer ? '答案列表' : '答案列表 (等待获取...)';
            },
            validTimeRemaining() {
                if (!this.validUntil) return '未验证';
                const remaining = parseInt(this.validUntil) - Date.now();
                if (remaining <= 0) return '验证已过期';

                const days = Math.floor(remaining / (24 * 60 * 60 * 1000));
                const hours = Math.floor((remaining % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
                return `验证剩余: ${days}天${hours}小时`;
            }
        },
        methods: {
            callback(key) {
                if (key === '2' && !this.hasAnswer) {
                    this.$message.warning('请等待答案获取完成后再查看答案列表');
                    this.key = '1'; // 保持在日志页面
                    return;
                }
                this.key = key;
            },
            toClose() {
                this.close = !this.close;
                const box = document.querySelector('.rlBox');
                const rect = box.getBoundingClientRect();
                const windowWidth = window.innerWidth;

                if (this.close) {
                    // 最小化时,判断靠近哪边
                    box.style.transition = 'all 0.3s ease';
                    const centerX = rect.left + rect.width / 2;
                    if (centerX > windowWidth / 2) {
                        // 靠右
                        box.style.right = '10px';
                        box.style.left = 'auto';
                        box.setAttribute('data-side', 'right');
                    } else {
                        // 靠左
                        box.style.left = '10px';
                        box.style.right = 'auto';
                        box.setAttribute('data-side', 'left');
                    }
                    box.classList.add('minimized');
                } else {
                    // 展开时
                    box.style.transition = 'all 0.3s ease';
                    box.classList.remove('minimized');
                    const side = box.getAttribute('data-side') || 'right';

                    if (side === 'right') {
                        box.style.right = '10px';
                        box.style.left = 'auto';
                    } else {
                        box.style.left = '10px';
                        box.style.right = 'auto';
                    }
                }
            },
            passVideo() {
                let video = document.getElementsByTagName("video");
                if(video.length == 0){
                    log("您当前页面不存在视频,请先打开学习视频页面");
                    return;
                }

                let currentVideo = video[0];

                // 添加视频结束监听器
                currentVideo.addEventListener('ended', () => {
                    this.handleNextVideo(); // 使用 this 来调用 Vue 实例的方法
                });

                // 设置视频结束前的最后一秒
                currentVideo.currentTime = currentVideo.duration - 0.1;
                currentVideo.playbackRate = 1;
                log("视频已完成,准备跳转下一个视频...");
            },
            exportExcel(){
                // 检查是否有答案数据
                if (!this.answerList || this.answerList.length === 0) {
                    this.$message.error('没有可导出的答案数据!请等待答案获取完成。');
                    log('导出失败:没有答案数据');
                    return;
                }

                // 准备数据
                const data = this.answerList.map(item => ({
                    '序号.选项': item.idAndOptions,
                    '题目': item.question,
                    '答案': item.answer
                }));

                // 创建工作簿
                const wb = XLSX.utils.book_new();
                // 创建工作表
                const ws = XLSX.utils.json_to_sheet(data);

                // 设置列宽
                const colWidths = {
                    '序号.选项': 10,
                    '题目': 50,
                    '答案': 30
                };

                ws['!cols'] = Object.keys(colWidths).map(key => ({
                    wch: colWidths[key]
                }));

                // 将工作表添加到工作簿
                XLSX.utils.book_append_sheet(wb, ws, "题库");

                // 生成并下载文件
                XLSX.writeFile(wb, "题库.xlsx");

                log('题库已导出为 Excel 文件');
            },
            clearLogs() {
                // 清空所有现有日志
                this.logs = [];
                setting.logs = [];

                // 添加清除提示
                const clearMessage = [
                    '日志已清除',
                    '------------------------',
                    '当前脚本版本:V3.0'
                ];

                // 直接设置新的日志数组,而不是使用 log 函数
                this.logs = clearMessage;
                setting.logs = [...clearMessage];

                // 阻止其他日志添加
                setTimeout(() => {
                    // 确保清除状态保持
                    if (this.logs.length > clearMessage.length) {
                        this.logs = [...clearMessage];
                        setting.logs = [...clearMessage];
                    }
                }, 200);
            },
            // 优化拖动处理
            initDragEvents() {
                const box = document.querySelector('.rlBox');
                const dragZone = document.querySelector('.ant-card-head');
                let startX, startY, initialMouseX, initialMouseY;

                dragZone.addEventListener('mousedown', (e) => {
                    if (this.close) return; // 最小化时禁止拖动
                    e.preventDefault();
                    this.isDragging = true;

                    const rect = box.getBoundingClientRect();
                    startX = rect.left;
                    startY = rect.top;
                    initialMouseX = e.clientX;
                    initialMouseY = e.clientY;

                    box.style.transition = 'none';
                    document.body.style.userSelect = 'none';
                });

                document.addEventListener('mousemove', (e) => {
                    if (!this.isDragging) return;

                    const dx = e.clientX - initialMouseX;
                    const dy = e.clientY - initialMouseY;

                    let newX = startX + dx;
                    let newY = startY + dy;

                    box.style.left = `${newX}px`;
                    box.style.top = `${newY}px`;
                    box.style.right = 'auto';

                    // 实时检查位置
                    this.checkPosition();
                });

                document.addEventListener('mouseup', () => {
                    if (this.isDragging) {
                        this.isDragging = false;
                        box.style.transition = 'all 0.2s';
                        document.body.style.userSelect = '';
                    }
                });

                // 添加触摸支持
                dragZone.addEventListener('touchstart', (e) => {
                    const touch = e.touches[0];
                    const rect = box.getBoundingClientRect();
                    startX = rect.left;
                    startY = rect.top;
                    initialMouseX = touch.clientX;
                    initialMouseY = touch.clientY;
                    this.isDragging = true;
                });

                document.addEventListener('touchmove', (e) => {
                    if (!this.isDragging) return;
                    e.preventDefault();

                    const touch = e.touches[0];
                    const dx = touch.clientX - initialMouseX;
                    const dy = touch.clientY - initialMouseY;

                    let newX = startX + dx;
                    let newY = startY + dy;

                    const maxX = window.innerWidth - box.offsetWidth;
                    const maxY = window.innerHeight - box.offsetHeight;

                    newX = Math.min(Math.max(0, newX), maxX);
                    newY = Math.min(Math.max(0, newY), maxY);

                    box.style.left = `${newX}px`;
                    box.style.top = `${newY}px`;
                });

                document.addEventListener('touchend', () => {
                    this.isDragging = false;
                });
            },
            handleNextVideo() {
                // Find the current active video item by checking for a class that indicates it's the current video
                const currentVideoItem = document.querySelector('.video-item.active, .video-item.current, .course-item.active, .course-item.current');

                if (!currentVideoItem) {
                    log("Unable to locate the current video. Please ensure the video list items are correctly marked.");
                    return;
                }

                // Extract the current video number from the text content of the current video item
                const currentNumber = parseInt(currentVideoItem.textContent.match(/\d+/)[0], 10);

                // Find the next video item by looking for the next sequence number
                const nextVideoNumber = currentNumber + 1;
                const nextVideoItem = Array.from(document.querySelectorAll('.video-item, .course-item'))
                                  .find(item => parseInt(item.textContent.match(/\d+/)[0], 10) === nextVideoNumber);

                if (nextVideoItem) {
                    // Attempt to click the next video item
                    const clickableElement = nextVideoItem.querySelector('a') || nextVideoItem.querySelector('button') || nextVideoItem;
                    clickableElement.click();
                    log(`Attempted to transition to video number ${nextVideoNumber}.`);

                    // Check if the new video has loaded
                    setTimeout(() => {
                        const newVideo = document.getElementsByTagName("video")[0];
                        if (newVideo && newVideo !== currentVideoItem) {
                            this.passVideo(); // Continue processing the new video
                        } else {
                            log("The new video has not started playing, manual intervention might be needed.");
                        }
                    }, 2000);
                } else {
                    log("Could not find the next video. Please manually select the next video or check the structure of the video list items.");
                }
            },
            checkPosition() {
                const box = document.querySelector('.rlBox');
                const rect = box.getBoundingClientRect();
                const windowWidth = window.innerWidth;
                const windowHeight = window.innerHeight;

                // 检查并修正水平位置
                if (rect.right > windowWidth) {
                    box.style.right = '0px';
                    box.style.left = 'auto';
                }
                if (rect.left < 0) {
                    box.style.left = '0px';
                    box.style.right = 'auto';
                }

                // 检查并修正垂直位置
                if (rect.bottom > windowHeight) {
                    box.style.top = `${windowHeight - rect.height - 10}px`;
                }
                if (rect.top < 0) {
                    box.style.top = '10px';
                }
            }
        }
    });
}





// 初始化获取答案,延迟5秒防止流程崩溃
function initGetAnswer(settings){
    var url = location.origin + settings.url;
    var data = settings.data.replace(/(testPaperId=).*?(&)/,'$1' + '1250' + '$2');
    console.log("=====")
    console.log(url,'url')
    console.log(data)
    getAnswer(url,data);
}




// 脚本入口
initView();
//监听跳过视频按钮
$('#rl_passVideo').click(function(){passVideo();});
//监听url访问,当访问了加载题目的url时,将获取答案
$(document).ready(function(){
    $(document).ajaxComplete(function (evt, request, settings) {
        if(settings.url.search('getExamPaper') != -1){
            setting.logs.unshift("您已打开作业界面,5秒后将为您获取答案")
            setTimeout(initGetAnswer,5000, settings);
        }
    });
})

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址