Greasy Fork

Greasy Fork is available in English.

上海开大助手

提高了自己效率,希望能帮助到更多人

目前为 2024-12-24 提交的版本。查看 最新版本

// ==UserScript==
// @name         上海开大助手
// @namespace    http://tampermonkey.net/
// @homepage     https://shkd.script.woca.fun
// @description  提高了自己效率,希望能帮助到更多人
// @author       AchieveHF
// @version      1.0.10
// @match        *://*.shou.org.cn/*
// @match        *://live.eeo.cn/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=shou.org.cn
// @grant        GM_setValue
// @grant        GM_getValue
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://unpkg.com/[email protected]/dist/layui.js
// @license MIT
// @run-at document-idle
// ==/UserScript==

(function() {
        'use strict';


        const css = document.createElement('link');
        css.rel = 'stylesheet';
        css.href = '//shkd.script.woca.fun/static/layui/css/layui.css';
        document.head.appendChild(css);
        const apiDomain = 'https://shkd.script.woca.fun/';
        // const apiDomain = 'http://localhost:8000/';

        let link = parseURLDetails();
        if (link.domain == 'live.eeo.cn') {
            setTimeout(() => {
                //第三方回放页面
                $('#player_html5_api')[0].muted = true;
                $('#player_html5_api')[0].play()
                return;
            }, 3000)
        }
        switch (link.path) {
            case '/study/assignment/preview.aspx':
                //插入工具
                $.ajax({
                        url: apiDomain + '/api/getBody', //获取题目接口
                        type: 'GET',
                        data: {
                            path: link.path,
                        },
                        success: function(data) {
                            $('.e-q-t').append(data)
                        }
                    })
                    //监听工具使用
                $('body').on('click', '.searchQuestion', function() {
                    let q = getQuestion($(this).parent().parent())
                    var index = layer.load(0, { shade: false });
                    $.ajax({
                        url: apiDomain + '/api/searchQuestion', //获取题目接口
                        type: 'POST',
                        data: {
                            question: q,
                        },
                        success: (res) => {
                            layer.close(index);
                            if (res.code == 200) {
                                $(this).parent().find('.result').html('参考答案:<pre>' + res.data.answer + '</pre>')
                                $(this).parent().parent().find('.e-a .ErichText').each((index, elem) => {
                                    // 获取当前选项的文本,并去掉多余的换行符和空格
                                    const optionText = $(elem).text().trim().replaceAll('\n', '');

                                    // 获取答案,按 '\n' 分隔为数组
                                    const answerList = res.data.answer.split('\n').map(ans => ans.trim());

                                    // 检查当前选项是否在答案数组中
                                    if (answerList.includes(optionText)) {
                                        $(elem).css('background-color', '#F5C16B'); // 设置背景色
                                    }
                                });
                                layer.msg(res.msg)
                            } else {
                                layer.msg(res.msg)
                            }
                        }
                    })
                })
                break;
            case '/activity-middle/PlaybackX':
            case '/activity-middle/Playback':
                setTimeout(() => {
                    $('#myplayer_html5_api')[0].muted = true
                    $('#myplayer_html5_api')[0].play()
                }, 5000)
                break;
            case '/study/activity-classInVideo.aspx':
                setTimeout(() => {
                    window.open($('#classIn')[0].src, '_blank', 'width=800,height=600')
                    window.close();
                }, 5000)
                break;
            case '/study/play.aspx':
                setTimeout(() => {
                    $('#video')[0].muted = true
                    $('#video')[0].play()
                }, 5000)
                break;
            case '/study/activity-preview.aspx':
                if (link.params.auto !== undefined) {
                    window.location.href = $('.am-btn.am-btn-success.am-btn-default').attr('href')
                }
                break;
            case '/study/directory.aspx':
                //观看课程页面
                const mustCourse = GM_getValue('mustCourse', {})
                setTimeout(() => {

                            if (mustCourse[link.params.CourseOpenId] != undefined) {
                                $('.bd .sh-cw-bd').prepend(`<div class="sh-toc2-pd layui-form">
                          <span class="module" style="width:36px;">  <img src="https://shkd.script.woca.fun/icon.png" style="width: 15px"></span>
                          <span title="上海开大助手" class="name">上海开大助手
                          </span>
                          <span class="name">
                          <button type="button" class="layui-btn ${GM_getValue('autoPlay') ? 'layui-bg-red' : 'layui-bg-blue'}" id="autoPlay">点击${GM_getValue('autoPlay') ? '关闭' : '开启'}自动刷课</button>
                            </span>
</div>
                      </div>
                      <div class="sh-toc3" style="background-position: -37px 0px;">
                        <table width="100%" class="course_catalog">
                            <tbody>
                                <tr data-id="mxb9amcxepbejp7twioola" class="tr_topic">
                                    <td width="36">
                                        <div class="sh-toc3-topic"> 1</div>
                                    </td>
                                    <td class="sh-toc3-dot" width="14"><span class="am-icon am-icon-circle-o"></span></td>
                                    <td title="必看课程">
                                        <div class="sh-toc3-desc show_topic">
                                            <span class="am-icon show_cell_list am-icon-caret-down"></span>
                                            <a title="必看课程">必看课程</a>
                                        </div>
                                        <div class="sh-toc3-children div_show_cell" name="showcell" data-isleaf="False" style="overflow: hidden; display: block;">
                                            <ul style="padding-left: 0px; margin-bottom: 0px;">
                                                <li class="cell_info1">
                                            ${mustCourse[link.params.CourseOpenId].map(item => `
                                                <a ${link.params.cellId == item.cellId ? 'class="active"' : ''} href="${item.url}" title="${item.title}">${item.title} <span class="sh-res-b">${item.type}</span><span class="sh-res-b">${item.status}</span></a>
                                            `).join('')}
                                            </li>
                                            </ul>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                      `)
                } else {
                    //没有找到必看
                    console.log(mustCourse)
                }
            }, 2000)

            setTimeout(() => {
                if (GM_getValue('autoPlay')) {
                    autoPlayStart()
                }
            }, 5000)
            // <div class="hd">
            //         <ul> 
            //             <li class="on">课程目录

            //             </li>

            //         </ul>
            //     <li><img src="https://shkd.script.woca.fun/icon.png" style="width: 15px">必看课程</li></div>

            $('body').on('click', '#autoPlay', function () {
                GM_setValue('autoPlay', GM_getValue('autoPlay') ? false : true)
                if (GM_getValue('autoPlay')) {
                    $(this).removeClass('layui-bg-blue').addClass('layui-bg-red')
                    autoPlayStart()
                } else {
                    $(this).removeClass('layui-bg-red').addClass('layui-bg-blue')
                }
                $(this).text('点击' + (GM_getValue('autoPlay') ? '关闭' : '开启') + '自动刷课')
            })
            break;
        case '/scenter':
            //学习空间首页
            const liveCourse = {};
            //获取课程列表
            const courseList = [];
            // 保存原生的 XMLHttpRequest.open 方法
            var originalXHROpen = XMLHttpRequest.prototype.open;

            XMLHttpRequest.prototype.open = function (method, url, ...args) {
                this.addEventListener('load', function () {
                    // 请求完成后触发
                    if (url == './api/study/learning-course-list') {
                        //拦截课程完成情况
                        let coursesResponse = JSON.parse(this.responseText)
                        //提取所有未完成的直播课
                        if (coursesResponse.code == 200 && coursesResponse.result.length > 0) {
                            coursesResponse.result.forEach((item) => {
                                if (item.activityProgress && item.activityProgress.progress) {
                                    item.activityProgress.progress.forEach((v) => {
                                        if (new Date() > new Date(v.endTime)) {
                                            v.courseId = item.activityProgress.courseOpenId
                                            if (liveCourse[item.activityProgress.courseOpenId] != undefined) {
                                                liveCourse[item.activityProgress.courseOpenId].push(v)
                                            } else {
                                                liveCourse[item.activityProgress.courseOpenId] = [v];
                                            }
                                        }
                                    })
                                }
                                courseList.push({
                                    courseOpenId: item.courseOpenId,
                                    courseName: item.courseName
                                })
                            })

                        }
                    }
                });

                // 调用原始的 open 方法
                return originalXHROpen.call(this, method, url, ...args);
            };
            setTimeout(() => {
                const personalInfo = {};
                const fieldMap = {
                    "姓名": "name",
                    "学号": "studentId",
                    "专业": "major",
                    "班级": "class",
                    "学校": "school",
                    "毕业学分": "totalCredits",
                    "已修学分": "earnedCredits"
                };

                $(".info-area p").each(function () {
                    const label = $(this).find(".info-label").text().replace(":", "").trim();
                    const value = $(this).text().replace($(this).find(".info-label").text(), "").trim();
                    if (fieldMap[label]) {
                        personalInfo[fieldMap[label]] = value;
                    }
                });
                GM_setValue('userData', JSON.stringify(personalInfo))

                $.ajax({
                    url: apiDomain + '/api/getBody',
                    type: 'POST',
                    data: {
                        path: link.path,
                        user: personalInfo,
                        courses: courseList
                    },
                    success: function (data) {
                        $('.content-left').append(data)
                    }
                })
            }, 5000)

            $('body').on('click', '#openLiveCourse', function () {
                GM_setValue('waitCourse', {})
                layer.confirm('先点击【查找】检测未完成的直播课<br/>点击后会弹出一些弹窗,不需要进行任何操作<br/>查找成功后点击【一键打开直播课】,点击后不需要进行任何操作会自动播放所有未完成的直播课', {
                    btn: ['查找', '请先点左边的查找按钮'] //按钮
                }, function (index, layero) {
                    //获取所有课程的学习表现
                    const iframes = [];
                    courseList.forEach((item) => {
                        iframes.push({
                            title: `获取${item.courseName}直播得分情况`,
                            url: `https://l.shou.org.cn/study/assistTeacher/scoreinfo?auto=true&courseOpenId=${item.courseOpenId}&minorcourseopenid=${item.courseOpenId}&stuId=${link.params.xh}&type=6`
                        })
                    })
                    openiframes(iframes, 'url', 'title')
                    const btn2 = layero.find('.layui-layer-btn1'); // 获取第二个按钮
                    layero.find('.layui-layer-btn0').hide()
                    btn2.text('一键打开直播课'); // 修改文本

                }, function () {
                    var waitCourseSet = GM_getValue('waitCourse');
                    const waitLiveCourse = [];
                    $.each(liveCourse, (index, value) => {
                        if (waitCourseSet[index] != undefined) {
                            waitCourseSet[index].forEach((val, key) => {
                                waitLiveCourse.push(liveCourse[index][val])
                            })
                        }
                    })
                    if (waitLiveCourse.length > 0) {
                        openWindowsInGridFromArray(waitLiveCourse)
                    } else {
                        layer.msg('没找到未完成的直播课')
                        layer.close();
                    }
                });
            })
            break;
        case '/study/assistTeacher/scoreinfo':
            setTimeout(() => {

                //学习表现页面
                if (link.params.auto) {
                    //在弹窗中的操作
                    //检查得分
                    $('thead tr th').each((index, item) => {
                        if ($(item).text() == '得分') {
                            if ($('tbody tr td:nth-child(' + (index + 1) + ')').text().trim() != 100) {
                                //没有得满分,获取签到详情

                                window.parent.postMessage(
                                    {
                                        type: 'change',
                                        oldurl: window.location.href,
                                        url: $('tbody tr td:last-child a').attr('href') + '&auto=true&courseId=' + link.params.courseOpenId
                                    },
                                    '*'
                                );
                                window.location.href = $('tbody tr td:last-child a').attr('href') + '&auto=true&courseId=' + link.params.courseOpenId
                            } else {
                                window.parent.postMessage(
                                    {
                                        type: 'close',
                                        url: window.location.href // 传递当前子页面的 URL
                                    },
                                    '*'
                                );
                            }
                        }

                    })

                }
            }, 3000)
            break;
        case '/appviewdev/xxbx/':

            var courseId = link.params.courseId
            // 保存原生的 XMLHttpRequest.open 方法
            var originalXHROpen = XMLHttpRequest.prototype.open;
            //拦截请求
            XMLHttpRequest.prototype.open = function (method, url, ...args) {
                this.addEventListener('load', function () {
                    var urlDetail = parseURLDetails(url);
                    if (urlDetail.path == '/v2/datac/stu/course_live_data_with_sign') {
                        let result = JSON.parse(this.responseText);
                        if (result.code == 0 && result.data.data.length > 0) {
                            //获取未完成的直播课的排序
                            var res = result.data.data.filter(item => item.live_type != '面授');
                            res.forEach((item, index) => {
                                if (item.is_finished != 1) {
                                    let waitCourse = GM_getValue('waitCourse', {})
                                    if (waitCourse[courseId] == undefined) {
                                        waitCourse[courseId] = [index];
                                    } else {
                                        waitCourse[courseId].push(index)
                                    }
                                    GM_setValue('waitCourse', waitCourse);
                                }
                            })

                            window.parent.postMessage(
                                {
                                    type: 'close',
                                    url: window.location.href // 传递当前子页面的 URL
                                },
                                '*'
                            );
                        }
                    }
                });

                // 调用原始的 open 方法
                return originalXHROpen.call(this, method, url, ...args);
            };
            break;
        case '/study/assignment/history.aspx':
            //插入页面工具
            $.ajax({
                url: apiDomain + '/api/getBody',//获取题目接口
                type: 'GET',
                data: {
                    path: link.path,
                },
                success: function (data) {
                    $('.e-quest-header').before(data)
                }
            })
            //监听工具动作
            $('body').on('click', '.share', function () {
                //作业结果页面
                let q_a = [];
                //获取所有回答正确的题
                $('.e-q-t').each(function (index, element) {
                    //大题
                    if ($(element).find('.e-q-quest .e-q-quest').length > 0) {
                        if ($(element).find('.e-q-l .e-q-right').length > 0) {
                            let topic = $(element).find('.e-q-q .ErichText').first().html()
                            let topic_text = $(element).find('.e-q-q .ErichText').first().text().trim().replaceAll('\n', '')
                            $(element).find('.e-q-quest .e-q-quest').each((index, elem) => {
                                let q = {
                                    topic: topic,
                                    topic_text: topic_text,
                                    type: '',
                                    question: '',
                                    question_text: '',
                                    answer: '',
                                    answer_options: '',
                                }
                                q = getRightQuestion(elem, q, true);
                                pushQuestion(q_a, q, element)
                                // pushQuestion(q_a,q,element)
                            })
                        }
                    } else {
                        let q = {
                            topic: '',
                            topic_text: '',
                            type: '',
                            question: '',
                            question_text: '',
                            answer: '',
                            answer_options: '',
                        }
                        q = getRightQuestion(element, q);
                        if (q !== false) {
                            pushQuestion(q_a, q, element)
                        }
                    }

                })
                //发送请求记录到题库
                $.ajax({
                    url: apiDomain + '/api/saveQuestions',//记录题目接口
                    type: 'POST',
                    data: {
                        q_a: q_a,
                        params: link.params,
                        userData: JSON.parse(GM_getValue('userData'))
                    },
                    success: function (data) {
                        layer.msg(data.msg)
                    }
                })
            })
            break;
        case '/p/PowerPointFrame.aspx':
            GM_setValue('goNext', false)
            document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2).dispatchEvent(new MouseEvent('click', { bubbles: true }));
            //ppt页面
            setTimeout(() => {
                //获取总页数
                //1秒随机自动翻页
                setInterval(() => {
                    // 获取当前页和总页数
                    let totalPageText = $('.cui-ctl-mediumlabel').text();
                    if (!totalPageText.includes('第') || !totalPageText.includes('共')) {
                        console.error('无法解析总页数和当前页数,请检查选择器');
                        return;
                    }

                    let totalPage = totalPageText.split('共')[1].split('张')[0].trim();
                    let currentPage = totalPageText.split('第')[1].split('张')[0].trim();


                    if (parseInt(currentPage) < parseInt(totalPage)) {
                        // 定位屏幕中央的元素
                        let element = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);

                        if (element) {
                            element.dispatchEvent(new MouseEvent('click', { bubbles: true }));
                        } else {
                            console.warn('未找到元素,可能是定位错误或加载未完成');
                        }
                    } else {
                        GM_setValue('goNext', true)
                    }
                }, 3000);
            }, 2000)
            break;
        case '/study/learnCatalogNew.aspx':
            //目录页面
            setTimeout(() => {
                $.ajax({
                    url: apiDomain + '/api/getBody',//获取题目接口
                    type: 'POST',
                    data: {
                        path: link.path
                    },
                    success: function (data) {
                        $('#d_courseright').prepend(data)
                    }
                })
                //保存必看
                let mustCourse = GM_getValue('mustCourse', {})
                let must = [];
                $('.sh-res').each((index, elem) => {
                    if ($(elem).find('span:contains("(必看)")').length > 0) {
                        let mustItem = {
                            title: $(elem).find('a').text().trim(),
                            url: $(elem).find('a').attr('href'),
                            cellId: $(elem).find('a').attr('href').split('cellId=')[1],
                            status: $(elem).find('img.warningnew1').attr('title'),
                            type: $(elem).find('a').next().text().trim()
                        }
                        must.push(mustItem)
                    }
                })
                console.log(must)
                if (must.length > 0) {
                    mustCourse[link.params.courseOpenId] = must
                    GM_setValue('mustCourse', mustCourse)
                    console.log(GM_getValue('mustCourse', {}))
                }
            }, 2000)
            //展开全部
            $('body').on('click', '#showAll', function () {
                $('.showcell').css('height', 'auto')
                $('.showcell').css('overflow', 'hidden')
            })
            //只显示必看
            $('body').on('click', '#showMust', function () {
                $('.sh-res').each((index, elem) => {
                    if ($(elem).find('span:contains("(必看)")').length == 0) {
                        $(elem).css('display', 'none')
                    }
                })
            })
            break;
        case '/study/assignment-preview.aspx':
            break;
    }

    //提取题目
    function getRightQuestion(element, q, sureRight = false) {
        if ($(element).find('.e-checking-a').length > 0) {
            //判断题
            q.type = '判断题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')
            if ($(element).find('.e-q-l .e-q-right').length > 0) {
                //答对的
                q.answer = $(element).find('li.e-a.checked').text().trim().split(' ')[1]
                q.answer_options = $(element).find('li.e-a.checked').text().trim().charAt(0)
            } else {
                //答错的,记录正确答案
                q.answer = $(element).find('li.e-a:not(.checked)').text().trim().split(' ')[1]
                q.answer_options = $(element).find('li.e-a:not(.checked)').text().trim().charAt(0)
            }
        } else if ($(element).find('.e-choice-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) {
            //答对的单选题
            q.type = '选择题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')
            if ($(element).find('li.e-a.checked').length > 1) {
                //多选题
                $(element).find('li.e-a.checked').each((index, elem) => {
                    q.answer += $(elem).find('.ErichText').text().trim().replaceAll('\n', '') + '\n'
                    q.answer_options += $(elem).contents().eq(2).text().trim().charAt(0)
                })
            } else if ($(element).find('li.e-a.checked').length = 1) {
                q.answer = $(element).find('li.e-a.checked .ErichText').text().trim().replaceAll('\n', '')
                q.answer_options = $(element).find('li.e-a.checked').contents().eq(2).text().trim().charAt(0)
            }
        } else if ($(element).find('.e-blank-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) {
            //填空题
            q.type = '填空题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')
            q.answer = []
            $(element).find('li.e-a').each((index, elem) => {
                q.answer.push({
                    title: $(elem).find('.e-blank-e').text(),
                    answer: $(elem).find('input').val()
                })
            })
            q.answer_options = null
        } else if ($(element).find('.e-short-a').length > 0 && ($(element).find('.e-q-l .e-q-right').length > 0 || sureRight)) {
            //排序题
            q.type = '排序题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')
            q.answer = []
            $(element).find('.am-g .am-u-sm-5').first().find('.ErichText').each((index, elem) => {
                q.answer.push({
                    title: $(elem).text().trim().replaceAll('\n', ''),
                    answer: $(element).find('.am-g .am-u-sm-1 .e-choice-i').eq(index).text().trim().replaceAll('\n', '')
                })
            })
            q.answer_options = null
        } else {
            q = false;
        }
        return q;
    }

    function getQuestion(element) {
        let q = {
            topic: '',
            topic_text: '',
            type: '',
            question: '',
            question_text: ''
        }
        if ($(element).find('.e-checking-a').length > 0) {
            //判断题
            q.type = '判断题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')

        } else if ($(element).find('.e-choice-a').length > 0) {
            //答对的单选题
            q.type = '选择题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')
        } else if ($(element).find('.e-blank-a').length > 0) {
            //填空题
            q.type = '填空题';
            q.question = $(element).find('.e-q-q .ErichText').html()
            q.question_text = $(element).find('.e-q-q .ErichText').text().trim().replaceAll('\n', '')

        } else {
            q = false;
        }
        return q;
    }

    //题目筛查
    function pushQuestion(q_a, q, element) {
        if (q.question === undefined || q.answer === undefined || q.answer_options === undefined) {
            $.ajax({
                url: '/api/errorQuestion',//记录无法提取的题目接口
                type: 'POST',
                data: {
                    element: element.outerHTML,
                },
                success: function (data) {
                    return false
                }
            })
            console.log('无法提取的题目已记录', element, q)
        } else {
            q_a.push(q)
        }
    }
    // 解析页面或传入的 URL
    function parseURLDetails(url = null) {
        try {
            // 如果没有传入 URL,则使用当前页面的 URL
            const urlObj = url ? new URL(url) : new URL(window.location.href);

            // 获取页面路径(不含参数)
            const pathname = urlObj.pathname;

            // 获取域名
            const domain = urlObj.hostname;

            // 处理普通查询参数
            const params = new URLSearchParams(urlObj.search);
            const queryParams = {};

            // 将参数拆分为键值对
            params.forEach((value, key) => {
                queryParams[key] = value;
            });

            // 检查并解析 # 后的参数(如果存在)
            if (urlObj.hash && urlObj.hash.includes('?')) {
                const hashParams = new URLSearchParams(urlObj.hash.split('?')[1]);
                hashParams.forEach((value, key) => {
                    queryParams[key] = value;
                });
            }

            // 返回结果对象
            return {
                url: urlObj.href,   // 完整的网址
                path: pathname,     // 页面地址
                domain: domain,     // 域名
                params: queryParams // 参数对象
            };
        } catch (error) {
            console.error('Invalid URL:', error.message);
            return null;
        }
    }

    //一键打开窗口铺满屏幕
    function openWindowsInGridFromArray(liveCourse) {
        if (!Array.isArray(liveCourse) || liveCourse.length === 0) {
            console.error('liveCourse 必须是一个非空数组');
            return;
        }

        const n = liveCourse.length; // 窗口数量
        const screenWidth = window.screen.availWidth; // 屏幕可用宽度
        const screenHeight = window.screen.availHeight; // 屏幕可用高度

        // 计算每行和每列的窗口数量
        const cols = Math.ceil(Math.sqrt(n)); // 列数
        const rows = Math.ceil(n / cols);    // 行数

        // 计算每个窗口的宽高
        const windowWidth = Math.floor(screenWidth / cols);
        const windowHeight = Math.floor(screenHeight / rows);

        // 遍历 liveCourse 数组并打开窗口
        liveCourse.forEach((item, index) => {
            const row = Math.floor(index / cols); // 当前窗口所在行
            const col = index % cols;            // 当前窗口所在列

            // 计算窗口的左上角位置
            const left = col * windowWidth;
            const top = row * windowHeight;

            // 打开窗口
            window.open(
                `https://l.shou.org.cn/study/activity-preview.aspx?auto=1&courseOpenId=${item.courseId}&activityId=${item.id}`,
                '_blank',
                `width=${windowWidth},height=${windowHeight},left=${left},top=${top},scrollbars=yes,resizable=yes`
            );
        });
    }

    function openiframes(urls, urlKey, titleKey) {
        const screenWidth = window.screen.availWidth; // 可用屏幕宽度
        const screenHeight = window.screen.availHeight; // 可用屏幕高度
        const columns = Math.ceil(Math.sqrt(urls.length)); // 列数
        const rows = Math.ceil(urls.length / columns); // 行数
        const iframeWidth = Math.floor(screenWidth / columns); // 每个窗口的宽度
        const iframeHeight = Math.floor(screenHeight / rows); // 每个窗口的高度

        // 记录每个 iframe 的索引和 layerId
        const layerIds = {};

        // 打开多个 iframe 窗口
        urls.forEach((url, index) => {
            const col = index % columns; // 当前列
            const row = Math.floor(index / columns); // 当前行
            const xOffset = col * iframeWidth; // x 轴偏移
            const yOffset = row * iframeHeight; // y 轴偏移

            const layerId = layer.open({
                type: 2, // iframe 类型
                title: `${url[titleKey]}`, // 窗口标题
                area: [`${iframeWidth}px`, `${iframeHeight}px`], // 窗口尺寸
                offset: [`${yOffset}px`, `${xOffset}px`], // 窗口位置
                content: url[urlKey], // iframe 的 URL
                shade: 0,
            });

            // 记录 layerId 和 URL 的对应关系
            layerIds[url[urlKey]] = layerId;
        });

        // 父页面监听消息
        window.addEventListener('message', (event) => {
            try {
                if (event.data.type === 'close') {
                    const layerId = layerIds[event.data.url];
                    if (layerId) {
                        layer.close(layerId); // 关闭对应的 iframe
                        delete layerIds[event.data.url]; // 删除记录
                    }
                } else if (event.data.type === 'change') {
                    layerIds[event.data.url] = layerIds[event.data.oldurl]
                }
            } catch (error) {
                console.error('消息解析失败', error);
            }
        });
    }

    function autoPlayStart() {

        const mustCourse = GM_getValue('mustCourse', {})
        //刷课
        // 获取课程类型
        const currentCell = mustCourse[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId)
        const nextUnfinishedCell = mustCourse[link.params.CourseOpenId].find(item => item.status != '已完成')
        if (currentCell.status == '已完成') {
            //寻找下一个未完成的课程
            if (nextUnfinishedCell != undefined) {
                window.location.href = nextUnfinishedCell.url
            } else {
                layer.alert('<img src="https://shkd.script.woca.fun/icon.png" style="width: 15px">没有未完成的必看课程了')
            }
        } else {
            if (currentCell.type.includes('视频')) {
                // 视频自动播放
                $('video')[0].muted = true
                $('video')[0].play()
                $('video')[0].addEventListener('ended', function () {
                    //标记本课程已完成储存到脚本
                    if (nextUnfinishedCell != undefined) {
                        //标记本节课已完成
                        let mustCourseTemp = GM_getValue('mustCourse', {})
                        mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成'
                        GM_setValue('mustCourse', mustCourseTemp)
                        window.location.href = nextUnfinishedCell.url
                    } else {
                        layer.alert('<img src="https://shkd.script.woca.fun/icon.png" style="width: 15px">没有未完成的必看课程了')
                    }
                })
            }else if(currentCell.type.includes('文档')) {
                //文档自动翻页
                setInterval(()=>{
                    //每三秒检查一次是否可以进行下一课
                    if(GM_getValue('goNext',false)){
                        //标记本课程已完成储存到脚本
                        if (nextUnfinishedCell != undefined) {
                            //标记本节课已完成
                            let mustCourseTemp = GM_getValue('mustCourse', {})
                            mustCourseTemp[link.params.CourseOpenId].find(item => item.cellId == link.params.cellId).status = '已完成'
                            GM_setValue('mustCourse', mustCourseTemp)
                            window.location.href = nextUnfinishedCell.url
                        } else {
                            layer.alert('<img src="https://shkd.script.woca.fun/icon.png" style="width: 15px">没有未完成的必看课程了')
                        }
                    }
                },3000)
            }
        }
    }

})();