Greasy Fork

Greasy Fork is available in English.

学习通刷课助手-自动静音,防止鼠标移出暂停,章节结束自动跳转下一节

学习通课程自动挂机,当前脚本支持课程视频播放完成,自动跳转下一小节,章节测试自动跳过,后台播放防止视频暂停。

当前为 2024-11-16 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         学习通刷课助手-自动静音,防止鼠标移出暂停,章节结束自动跳转下一节
// @namespace    http://tampermonkey.net/
// @version      0.0.14
// @description  学习通课程自动挂机,当前脚本支持课程视频播放完成,自动跳转下一小节,章节测试自动跳过,后台播放防止视频暂停。
// @author       Sweek
// @match        *://*.chaoxing.com/*
// @license      GPLv3
// @icon         https://www.google.com/s2/favicons?sz=64&domain=csdn.net
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @require      https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==


// 定义全局变量
let currentTime = null // 当前视频当前播放节点
let duration = null // 当前视频总长度
let progress = null // 当前视频播放进度
let playbackRate = 1 // 当前视频播放倍速

// 课程章节相关数据
let courseName = null // 当前课程名称
let courseId = null // 当前课程id
let chapterInfo = [] // 当前课程所有章节数据
let currentChapterId = null // 当前所在章节id
let currentChapterName = null // 当前所在章节名称
let allChapterName = []  // 所有章节名称
let currentChapterTabArr = [] // 当前页面所有的分栏
let currentChapterTabName = '' // 当前页面激活的分栏名称
let videoProgressId = '' // 定时监听页面内容监听事件

// 获取当前页面的 URL
url = ''
chapterId = ''


// 页面模板部分
// 页面模板部分
// 页面模板部分

// 页面样式
var popCSs = `
#my-window {
    position: fixed;
    top: 5px;
    left: 20px;
    width: 300px;
    height: auto;
    background-color: rgba(247, 247, 247, 1);
    border: 1px solid #fff;
    border-radius: 5px;
    z-index: 9999;
    overflow: hidden;
  }
  
  #my-window .header {
    background-color: #4497fa;
    color: #fff;
    padding: 5px;
    font-size: 16px;
    font-family: 'fangsong';
    font-weight: bold;
    border-radius: 5px;
    cursor: move;
    height: 25px;
    width: 300px;
  }

  #my-window .content {
    width: 300px;
    height: 570px;
  }

  #my-window .content .content-title {
    height: 22px;
    width: 280px;
    background-color: #dadada;
    line-height: 22px;
    padding-left: 5px;
    font-size: 12px;
    font-family: 'fangsong';
    font-weight: 600;
    boder-radius: 5px;
    border-left: 4px solid #2196f3;
    border-right: 4px solid #dadada;
    margin-top: 5px;
  }

  #my-window .content .content-notice {
    height: 80px;
    width: 280px;
    overflow: auto;
    border: 1px solid gray;
    border-radius: 5px;
    padding: 5px;
    margin-top: 5px;
  }

  #my-window .content .content-process {
    height: 60px;
    width: 280px;
    overflow: auto;
    border: 1px solid gray;
    border-radius: 5px;
    padding: 5px;
    margin-top: 5px;
  }

  #my-window .content .content-log {
    height: 120px;
    width: 280px;
    overflow: auto;
    border: 1px solid gray;
    border-radius: 5px;
    padding: 5px;
    margin-top: 5px;
  }
  
  #my-window .content .content-set {
    height: 130px;
    width: 280px;
    overflow: auto;
    border: 1px solid gray;
    border-radius: 5px;
    padding: 5px;
    margin-top: 5px;
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
  }

  #my-window .content .content-set .content-set-content {
    width: 280px;
    display: flex;
    justify-content: space-between;
  }

  #my-window .content .content-set .content-set-content #email-input {
    width: 200px;
    border-radius: 5px;
    border: 1px solid gray;
  }


  #my-window .content .content-set #save-btn {
    color: gray;
    width: 100%;
    margin-top: 10px;
    border-radius: 5px;
    border: 1px solid gray;
  }

  #save-btn:hover {
    background-color: #e3e3e3!important;
  }

  #my-window .resizer {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 20px;
    height: 20px;
    background-color: #2196f3;
    cursor: se-resize;
    border-radius: 0px;
    z-index: 1;
  }
  
  #hide-btn {
    height: 25px;
    width: auto;
    float: right;
    margin-right: 10px;
    background-color: #fff;
    border: 1px solid gray;
    border-radius: 5px;
    font-size: 12px;
    padding: 0 5px;
    font-family: 'fangsong';
  }

  #hide-btn:active {
    background-color: #4497fa;
  }
`

// 页面Html
var popHtml = `
<div class="header">学习通助手
  <button id="hide-btn">显示/隐藏</button>
</div>
<div class="content" id="my-window-content">
  <div class="resizer" style="display: none;"></div>
  <div class="row" style="border: 1px solid #ccc; padding: 5px;">
    <div class="content-title">公告</div>
    <div class="content-notice" id="content-notice">
    </div>
    <div class="content-title">播放进度</div>
    <div class="content-process" id="content-process"></div>
    <div class="content-title">执行日志</div>
    <div class="content-log" id="content-log"></div>
    <div class="content-title">配置</div>
    <div class="content-set" id="content-set">        
    <div>该邮箱地址用来登录app网站,该邮箱需要和网站注册邮箱保持一致,不可为空,填写完,点击保存,可在网站查看课程进度,二维码:
      <a style="color: dodgerblue;cursor: pointer;" id="Qcode">点击查看,微信扫码</a>
    </div>
      <div class="content-set-content">
        <label for="email-input">邮箱:</label>
        <input type="email" id="email-input" placeholder="请输入邮箱地址">
      </div>
      <button id="save-btn">保存</button>
    </div>
  </div>
</div>
`

// 执行方法部分
// 执行方法部分
// 执行方法部分
function takeEmail() {
  // 获取邮箱输入框和保存按钮
  const emailInput = document.getElementById("email-input");
  const saveBtn = document.getElementById("save-btn");

  // 当保存按钮被点击时
  saveBtn.addEventListener("click", function() {
    // 获取输入的邮箱地址
    const email = emailInput.value.trim();
    console.log('emailInput.value:::+ ', emailInput.value)
    // 检查邮箱地址是否有效
    if (!isValidEmail(email)) {
      notify('请输入有效的邮箱地址!', 2500)
      return;
    }
    
    const url = 'http://sweek.top/api/checkEmailExists';
    const data = { 
      email
    };
    if(email) {
      fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json', // 声明请求主体的内容类型为 JSON
        },
        body: JSON.stringify(data), // 将数据对象转换为 JSON 字符串并作为请求主体
      }).then(response => {
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        return response.json(); // 解析 JSON 响应数据
      }).then(data => {
        // console.log('Response:', data);
        console.log('data:::+ ', data)
        if(data.exists){
          // 将邮箱地址存储到本地存储中
          GM_setValue("savedEmail", email);
          // 提示保存成功
          notify('保存成功!课程信息将同步到该邮箱账号', 2500)
        } else {
          notify('邮箱账号尚未注册,请扫码前往留言信箱网站注册', 2500)
        }
      }).catch(error => {
        console.error('Error:', error);
      });
    }

  });

  // 页面加载时,尝试从本地存储中获取已保存的邮箱地址并反显到输入框中
  const savedEmail = GM_getValue("savedEmail");
  if (savedEmail) {
    console.log('savedEmail:::+ ', savedEmail)
    emailInput.value = savedEmail;
  }
}

// 邮箱地址验证函数
function isValidEmail(email) {
  // 此处可以使用正则表达式等方式进行邮箱地址的验证
  // 这里简单地判断邮箱是否包含 '@' 符号
  return email.includes("@");
}

// 开始播放视频
function startVideo() {
  setTimeout(function() {
    if(location.pathname === '/ananas/modules/video/index.html') {
      var video = document.querySelector('video');
      if (video) {
        video.volume = 0; // 将声音调节至0
        addlog('已将视频声音调至0')
        addlog('当前视频倍速为' + video.playbackRate)
        if (video) {
          // video.play();
          const startBtn = document.querySelector('.vjs-big-play-button')
          // console.log('startBtn:::+ ', startBtn)
          startBtn.click()
          addlog('视频开始播放')
        }
      }
    }
  }, 2000);
}

// 获取视频播放进度-定时监听页面内容进行下一步处理
function getVideoProgress() {
  // 同步课程进度
  if(location.pathname == '/mycourse/studentstudy') {
    const emailInput = document.getElementById("email-input");
    const email = emailInput.value.trim();
    const url = 'http://sweek.top/api/checkEmailExists';
    const data = { 
      email
    };
    if(email) {
      fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json', // 声明请求主体的内容类型为 JSON
        },
        body: JSON.stringify(data), // 将数据对象转换为 JSON 字符串并作为请求主体
      }).then(response => {
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        return response.json(); // 解析 JSON 响应数据
      }).then(data => {
        // console.log('Response:', data);
        // console.log('data:::+ ', data)
        if(data.exists){  
          syncCourseData()
        } else {
          addlog('同步课程信息失败,该邮箱尚未注册')
        }
      }).catch(error => {
        console.error('Error:', error);
      });
    }

  }
  var video = null
  // console.log('location.pathname:::+ ', location.pathname)
  getSubChapter()
  // 学习目标模块显示时
  if(location.pathname === '/mycourse/studentstudy') {
    var studyModel = window.top.document.querySelector('#dct1')
    var ifStudyModel = studyModel.classList.contains('active') && studyModel.getAttribute('title') === '学习目标'
    if (ifStudyModel) {
      addlog('当前小节为学习目标,自动跳过')
      return toNextChapter()
    }
  }
  // 章节测试模块显示时
  if(location.pathname === '/ananas/modules/work/index.html') {
    addlog('当前小节为章节测试,自动跳过')
    return toNextChapter()
  } 
  // 章节小节模块显示时
  if(location.pathname === '/ananas/modules/questionnaire/index.html') {
    addlog('当前小节为章节小节,自动跳过')
    return toNextChapter()
  } 
  // 阅读模块显示时
  if (location.pathname === '/mooc-ans/coursedata/readjobv2/show') {
    addlog('当前小节为阅读,自动跳过')
    return toNextChapter()
  }
  // 调查问卷模块显示时
  if (location.pathname === '/ananas/modules/zt/vote/index-pc-new.html') {
    addlog('当前小节为调查问卷,课程已结束')
    // 清除定时器任务
    clearInterval(videoProgressId);
    addlog('脚本已终止')
    return toNextChapter()
  }  
  // 视频模块显示时
  if(location.pathname === '/ananas/modules/video/index.html') {
    video = document.querySelector('video');
    if (video) {
    }
  } else if (currentChapterTabName.length > 1 && currentChapterTabName.indexOf("视频") === -1) {
    if(location.pathname == '/mycourse/studentstudy') {
      // console.log('currentChapterTabName:::+ ', currentChapterTabName)
      addlog('当前小节为非视频内容:' + currentChapterTabName + ',自动跳过')
      return toNextChapter()
    }
  }
}

// 定时处理监听视频事件
function setIntervalStart() {
  if (location.pathname === '/ananas/modules/video/index.html') {
    let video = document.querySelector('video');
    let intervalId;

    function restartVideo() {
      if (video && video.paused && video.currentTime < video.duration) {
        // video.play(); // 重新开始播放
        const startBtn = document.querySelector('.vjs-big-play-button')
        // console.log('startBtn:::+ ', startBtn)
        startBtn.click()
      }
    }
    function goToNextChapter() {
      clearInterval(intervalId); // 清除定时器
      addlog('当前视频观看进度为100%,自动跳转到下一小节');
      toNextChapter();
    }
    function handleErrors() {
      clearInterval(intervalId); // 清除定时器
      addlog('遇到错误,页面将刷新');
      location.reload(); // 刷新页面
    }

    // 处理视频暂停
    video.addEventListener("pause", restartVideo);
    // 处理视频观看完成
    video.addEventListener("timeupdate", function() {
      let currentTime = video.currentTime; // 当前播放时间(以秒为单位)
      let duration = video.duration; // 视频总时长(以秒为单位)
      let progress = (currentTime / duration) * 100; // 计算播放进度百分比
      setVideoProcess(progress.toFixed(2) + '%', currentTime.toFixed(0), duration.toFixed(0)); // 设置视频播放进度显示
      // 如果播放进度大于等于100%,则跳转到下一章节
      if (progress >= 100) {
        goToNextChapter();
      }
    });
    // 定期检查视频是否出现错误
    intervalId = setInterval(function() {
      if (video.error) {
        handleErrors();
      }
    }, 10000); // 每秒检查一次
  }
}

// 跳转到下一章节 
function toNextChapter() {
  var nextButton = window.top.document.querySelector('#prevNextFocusNext');
  // console.log('nextButton:::+ ', nextButton)
  const nextChapter = window.top.document.querySelector('.nextChapter');
  if(nextChapter) {
      nextChapter.click()
      // console.log(nextChapter)
      return
  }
  if (nextButton) {
    nextButton.click();
  }
}

// 获取页面url
function getURLInfo() {
  if(location.pathname == '/mycourse/studentstudy') {
    url = location.href
    // console.log('url:::+ ', url)
    // 获取问号后面的部分
    var queryString = url.split('?')[1];
    // 将查询字符串拆分为参数对
    var queryParams = queryString.split('&');
    // 创建一个对象来存储参数
    var params = {};
    // 遍历参数对,将它们存储在对象中
    queryParams.forEach(function(queryParam) {
        var parts = queryParam.split('=');
        var key = decodeURIComponent(parts[0]);
        var value = decodeURIComponent(parts[1]);
        params[key] = value;
    });
    chapterId = params['chapterId']
    courseId = params['courseId']
    console.log('params:::+ ', params)
    GM_setValue("courseId", courseId);
  }
}

// 初始化添加页面弹窗以及悬浮球
function initPopup() {
  // 添加CSS样式
  GM_addStyle(popCSs);
  // 创建窗口元素
  const myWindow = document.createElement("div");
  myWindow.id = "my-window";
  myWindow.innerHTML = popHtml;
  // 获取页面body元素
  const body = document.getElementsByTagName("body")[0];
  // 添加窗口和悬浮球到页面
  body.appendChild(myWindow);
 // 绑定隐藏窗口按钮的click事件
 const hideBtn = document.querySelector("#hide-btn");
 hideBtn.addEventListener("click", hideWindow);
// 获取弹窗内容
var htmlContent = '<img src="http://sweek.top/api/preview/Qcode.png" alt="微信扫码">';

// 点击链接显示弹窗
document.getElementById('Qcode').addEventListener('click', function() {
  showCustomPopup(htmlContent, 500, 500);
});
 

// 获取头部元素
const header = myWindow.querySelector('.header');

// 处理移动事件
let isDragging = false;
let mouseX = 0;
let mouseY = 0;

header.addEventListener('mousedown', function (e) {
  e.preventDefault();
  isDragging = true;
  mouseX = e.clientX;
  mouseY = e.clientY;
});

document.addEventListener('mousemove', function (e) {
  if (isDragging) {
    const deltaX = e.clientX - mouseX;
    const deltaY = e.clientY - mouseY;
    const newLeft = Math.min(
      Math.max(0, myWindow.offsetLeft + deltaX),
      window.innerWidth - myWindow.offsetWidth
    );
    const newTop = Math.min(
      Math.max(0, myWindow.offsetTop + deltaY),
      window.innerHeight - myWindow.offsetHeight
    );
    myWindow.style.left = newLeft + 'px';
    myWindow.style.top = newTop + 'px';
    mouseX = e.clientX;
    mouseY = e.clientY;
  }
});

document.addEventListener('mouseup', function () {
  isDragging = false;
});

}

// 隐藏窗口函数
function hideWindow() {
  var myWindowContent = document.getElementById("my-window-content");
  var showPop = myWindowContent.style.display
  if (showPop == '' || showPop == 'block') {
    myWindowContent.style.display = "none";
  } else {
    myWindowContent.style.display = "block";
  }
}

// 获取当前页面章节小节的所有分栏
function getSubChapter() {
  try {
    if(location.pathname == '/mycourse/studentstudy') {
      var subChapter = window.top.document.querySelector('#prev_tab');
      if(subChapter) {
        currentChapterTabArr = subChapter.querySelectorAll('li');
        // console.log('currentChapterTabArr:::+ ', currentChapterTabArr)
        currentChapterTabArr.forEach(function(item) {
          if(item.className === 'active') {
            currentChapterTabName = item.innerText
          }
        })
      // console.log('currentChapterTabName:::+ ', currentChapterTabName)
      }
      
    }
  } catch (error) {
    console.error('An error occurred:', error);
    // location.reload(); // 刷新页面
  }
}

// 获取课程所有章节节点数据
function getChapterCodeInfo() {
  // console.log('location.pathname:::+ ', location.pathname)
  if(location.pathname === '/mooc-ans/knowledge/cards') {
    var chapter = window.top.document.querySelectorAll('.posCatalog_select')
    chapterInfo = chapter
    allChapterName=[]

    // console.log('chapterInfo:::+ ', chapterInfo)
    chapterInfo.forEach(function(item) {
      // console.log(item);
      allChapterName.push({
        id: item.id,
        title: item.innerText,
        active: item.classList.contains('posCatalog_active') ? 1 : 0,
        ifTitle: item.classList.contains('firstLayer') ? 1 : 0,
        status: item.childNodes[3]?.className == 'icon_Completed prevTips' ? 1 : 0
      })
      if (item.classList.contains('posCatalog_active')) {
        currentChapterId = item.id
        GM_setValue("currentChapterId", currentChapterId);
        currentChapterName = item.innerText
        GM_setValue("currentChapterName", currentChapterName);
      }
    });
    // console.log('allChapterName:::+ ', allChapterName)
    GM_setValue("chapterInfo", JSON.parse(JSON.stringify(allChapterName)));
    // console.log('currentChapterId:::+ ', currentChapterId)
    // console.log('currentChapterName:::+ ', currentChapterName)
    // console.log('allChapterName:::+ ', allChapterName)
    addlog('当前章节为' + currentChapterName, 'green')
  }
}

// 获取公告数据
function getBoard() {
  fetch('http://sweek.top/api/board')
  .then(response => response.json())
  .then(data => {
    // 在这里处理接收到的数据
    // console.log(data);
    var notice = document.querySelector('#content-notice');
    notice.innerHTML = data.text
  })
  .catch(error => {
    // 在这里处理错误
    console.error('Error:', error);
  });
}

// 同步课程数据至数据库
function syncCourseData() {
  const url = 'http://sweek.top/api/insertOrUpdateCourse';
  const email = GM_getValue("savedEmail")
  const course_name = GM_getValue("courseName")
  const current_chapter_id = GM_getValue("currentChapterId")
  const current_chapter_name = GM_getValue("currentChapterName")
  const course_id = GM_getValue("courseId")
  const process = document.querySelector('#content-process').innerHTML  
  const chapter_info = GM_getValue("chapterInfo")
  var chapter = window.top.document.querySelectorAll('.posCatalog_select')
  allChapterName = []
  chapter.forEach(function(item) {
    // console.log(item);
    allChapterName.push({
      id: item.id,
      title: item.innerText,
      active: item.classList.contains('posCatalog_active') ? 1 : 0,
      ifTitle: item.classList.contains('firstLayer') ? 1 : 0,
      status: item.childNodes[3]?.className == 'icon_Completed prevTips' ? 1 : 0
    })
    if (item.classList.contains('posCatalog_active')) {
      currentChapterId = item.id
      GM_setValue("currentChapterId", currentChapterId);
      currentChapterName = item.innerText
      GM_setValue("currentChapterName", currentChapterName);
    }
  });
  // console.log('chapter_info:::+ ', chapter_info)
  const data = { 
    email,
    course_id: course_id || '',
    course_name: course_name || '测试',
    chapter: JSON.stringify(allChapterName),
    current_chapter: current_chapter_id + ',' + current_chapter_name,
    process
  };
  if(process.includes("NaN")) {
    // console.log('视频播放异常,将发送邮件至邮箱' + email)
    console.log('视频播放异常,页面将刷新')
    location.reload(); // 刷新页面
    return
  }
  if(email && process) {
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json', // 声明请求主体的内容类型为 JSON
      },
      body: JSON.stringify(data), // 将数据对象转换为 JSON 字符串并作为请求主体
    }).then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json(); // 解析 JSON 响应数据
    }).then(data => {
      // console.log('Response:', data);
      addlog('同步课程信息成功')
    }).catch(error => {
      console.error('Error:', error);
    });
  }
}

// 获取当前时间,年月日时分秒
function getCurrentDateTime() {
  var now = new Date();

  var year = now.getFullYear();
  var month = (now.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需要加1,并确保两位数格式
  var day = now.getDate().toString().padStart(2, '0'); // 确保两位数格式
  var hours = now.getHours().toString().padStart(2, '0'); // 确保两位数格式
  var minutes = now.getMinutes().toString().padStart(2, '0'); // 确保两位数格式
  var seconds = now.getSeconds().toString().padStart(2, '0'); // 确保两位数格式

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

// 设置播放进度
function setVideoProcess(val1, val2, val3) {
  var _process = window.top.document.querySelector('#content-process');
  var _time = getCurrentDateTime()
  var newContent = '<p style="color: #000;">[' + _time + ']' + '</p><hr><p>' + '播放进度:' + val1 + '</p><hr><p>' + '视频长度:' + val2 + 's' + '/' +val3 + 's' + '</p>';
  _process.innerHTML = newContent;
}

// 页面弹窗显示
function showCustomPopup(htmlContent, width, height) {
  // 创建弹窗容器
  var popupContainer = document.createElement('div');
  popupContainer.className = 'custom-popup-container';
  // 设置弹窗容器样式
  popupContainer.style.position = 'fixed';
  popupContainer.style.top = '50px';
  popupContainer.style.left = '0';
  popupContainer.style.width = '100%';
  popupContainer.style.height = 'calc(100% - 50px)';
  popupContainer.style.display = 'flex';
  popupContainer.style.justifyContent = 'center';
  popupContainer.style.alignItems = 'center';
  popupContainer.style.zIndex = '999999';

  // 创建弹窗内容容器
  var popupContent = document.createElement('div');
  popupContent.className = 'custom-popup-content';
  // 设置弹窗内容样式
  popupContent.style.width = width + 'px';
  popupContent.style.height = height + 'px';
  popupContent.style.backgroundColor = '#fff';
  popupContent.style.border = '1px solid #ccc';
  popupContent.style.borderRadius = '5px';
  popupContent.style.position = 'relative';

  // 创建关闭按钮
  var closeButton = document.createElement('button');
  closeButton.innerHTML = '关闭';
  closeButton.style.position = 'absolute';
  closeButton.style.top = '5px';
  closeButton.style.right = '5px';
  closeButton.style.padding = '5px 10px';
  closeButton.style.backgroundColor = '#ccc';
  closeButton.style.border = 'none';
  closeButton.style.borderRadius = '3px';
  closeButton.style.cursor = 'pointer';
  closeButton.style.fontFamily = 'Arial, sans-serif';

  // 关闭按钮点击事件处理
  closeButton.addEventListener('click', function() {
    popupContainer.remove();
  });

  // 设置弹窗内容
  popupContent.innerHTML = htmlContent;

  // 将关闭按钮和弹窗内容添加到弹窗容器中
  popupContent.appendChild(closeButton);
  popupContainer.appendChild(popupContent);

  // 将弹窗容器添加到页面中
  document.body.appendChild(popupContainer);
}

// 页面通知提示
function notify(text, time) {
  // 创建通知元素
  var notification = document.createElement('div');
  notification.className = 'notification';
  // 设置通知内容
  notification.innerHTML = '<div class="notification-content"><h2 style="font-size: 16px;font-weight: bold;color: #307dff;font-family: fangsong;">' + '学习通助手提示' + '</h2><p style="font-family: fangsong;font-size: 13px;font-weight: bold;">' + text + '</p></div>';
  // 将通知添加到页面中
  document.body.appendChild(notification);
  // 设置通知样式
  notification.style.position = 'fixed';
  notification.style.top = '50px';
  notification.style.left = '-400px'; // 从左边弹出
  notification.style.transform = 'translateY(-50%)'; // 垂直居中
  notification.style.transition = 'left 0.5s ease-in-out'; // 添加过渡效果
  notification.style.zIndex = '999999';
  notification.style.backgroundColor = '#fff';
  notification.style.border = '1px solid #ccc';
  notification.style.padding = '10px';
  notification.style.borderRadius = '5px';
  notification.style.lineHeight = '25px';

  // 等待一小段时间后,移动通知到左边
  setTimeout(function() {
    notification.style.left = '20px'; // 移动到左边
  }, 100);

  // 设置定时器,在指定时间后移除通知
  setTimeout(function() {
    // 移动通知到左边以外
    notification.style.left = '-400px';
    // 等待过渡效果完成后,移除通知元素
    setTimeout(function() {
      notification.remove();
    }, 500);
  }, time);
}

// 添加执行日志
function addlog(str, color) {
  var _time = new Date().toLocaleTimeString()
  var contentLog = window.top.document.querySelector('.content-log');
  // console.log('contentLog:::+ ', contentLog)
  var newContent = '<p style="color: ' + color + ';">[' + _time + ']' + str + '</p><hr>';
  contentLog.innerHTML += newContent;
  // 将滚动条滚动到底部
  contentLog.scrollTop = contentLog.scrollHeight;
}

// 方法执行入口
(function () {
  // console.log('location.pathname:::+ ', location.pathname)
  // 进入学习通弹出提示
  if(location.pathname == '/base') {
    notify('已进入学习通首页,请进入课程,选择需要学习的课程', 5000)
  }
  // 进入课程弹出提示
  if(location.pathname == '/mooc2-ans/mycourse/stu') {   
    courseName = window.top.document.querySelector('.classDl .colorDeep').getAttribute('title')
    GM_setValue("courseName", courseName);
    notify('已进入课程:' + courseName + ',请选择需要学习的章节', 5000)
  }
  // 初始化显示页面弹窗
  if(location.pathname == '/mycourse/studentstudy') {
    initPopup()  
    // 获取公告数据
    getBoard()  
    // 邮箱操作
    takeEmail() 
  }
  // 获取页面章节节点数据
  getChapterCodeInfo()
  // 获取当前页面章节小节的所有分栏
  getSubChapter()
  // 获取页面url信息
  getURLInfo()
  // 开始播放视频
  startVideo()
  // 定时处理监听视频事件
  setTimeout(() => {
    setIntervalStart()
  }, 2000);
  // 定时打印视频播放进度-定时监听页面内容进行下一步处理
  videoProgressId = setInterval(() => {
    getVideoProgress()
  }, 10000);
})();