EduCity

Optimize the website of educity.cn.

目前為 2022-10-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name               EduCity
// @name:zh-CN         希赛
// @description        Optimize the website of educity.cn.
// @description:zh-CN  希赛页面优化
// @namespace          https://github.com/HaleShaw
// @version            1.3.6
// @author             HaleShaw
// @copyright          2021+, HaleShaw (https://github.com/HaleShaw)
// @license            AGPL-3.0-or-later
// @homepage           https://github.com/HaleShaw/TM-EduCity
// @supportURL         https://github.com/HaleShaw/TM-EduCity/issues
// @contributionURL    https://www.jianwudao.com/
// @icon               https://www.educity.cn/favicon.ico
// @match              https://www.educity.cn/wangxiao2/*
// @match              http://www.educity.cn/wangxiao2/*
// @match              https://uc.educity.cn/personalCenter/studyCenter.html
// @match              https://uc.educity.cn/tiku/testReport.html*
// @match              https://uc.educity.cn/tiku/examinationMode.html*
// @match              https://uc.educity.cn/tiku/examinationModeCopy.html*
// @match              https://wangxiao.xisaiwang.com/wangxiao2/*
// @compatible	       Chrome
// @grant              GM_addStyle
// @grant              GM_info
// ==/UserScript==

// ==OpenUserJS==
// @author             HaleShaw
// @collaborator       HaleShaw
// ==/OpenUserJS==

(function () {
  "use strict";
  const zhiBoStyle = `
/* 左上角标题 */
#mainVid > div.vid_head > div.vid_hleft > a:not(:last-child),

/* 右上角“返回旧版、视频课程” */
#mainVid > div.vid_head > div.vid_hright > a,

/* 离线观看 */
#mainVid > div.vid_mid > div.vid_midL > div.vid_midL_top,

/* 右侧笔记、提问 */
#mainVid > div.vid_mid > div.vid_midR > div.vid_midR_tab > div > a:nth-child(2),
#mainVid > div.vid_mid > div.vid_midR > div.vid_midR_tab > div > a:nth-child(3),

/* 鼠标混入视频时的浮标按钮“新建笔记” */
.vid_bj_new,

/* 顶部横条 */
.vid_head {
	display: none !important;
}

.vid_head .vid_hright {
  padding-top: 0 !important;
}

.vid_mid .vid_midL {
  padding: 0 !important;
}

.vid_midR_tab,
.vid_midR_tab > a,
.vid_midR_tab > a > i,
.vid_midR_tab > .vid_midR_ul,
.vid_midR_tab > .vid_midR_ul > a,
.vid_midR_tab > .vid_midR_ul > a > i,
.tabhide .vid_midR{
	width: 28px !important;
}

.tabhide .vid_mid {
  padding-right: 28px;
}
.vid_mid {
	padding-right: 439px;
}

.vid_midR {
	width: 439px;
}

.vid_tab_content {
	padding-bottom: 0;
}

/* 进度条上的时间 */
.time-span {
  margin: 0 10px;
}
`;

  const testReportStyle = `
.side.rightfixside,
.cbox,
.review,
.doPane.note,
.doPane.question,
.notes,
.advise,
.answerTitle,
.six.clearfix>span,
.pull-right.clearfix,
li.one, li.two, li.four, li.five,
.tsbody,
footer {
display: none !important;
}

.wrong,
.wrong + .clearfix.dajx,
.analysisAnswer.none,
li.one.bt{
display: block !important;
}

.tsbody {
padding: 5px 0 !important;
}

.answerEnd>span {
  color: #51cb65;
}

.answerEnd>div {
  color: #a3a3af;
  text-decoration: line-through;
}
`;

  const examStyle = `
div.col-md-12 > div > div.zt_top_right,
div.doPane.note,
div.doPane.question,
div.shitiDesp.pdt15 > div.jiexinew:nth-child(3),
div.answerTitle,
#ztsetWrap > div.bg-fff.box-shadow,
#scantronWrap > div > div.dtklist > div.cbnWrap > h5,
#scantronWrap > div > div.spanExplain{
	display: none !important;
}

.right-title {
	padding: 0 20px !important;
	margin-bottom: 0px !important;
}

.zt_top_zong {
	height: 65px !important;
	background: none !important;
}

div.col-md-9 > div.bg-fff.box-shadow.mgt10.subject-content {
	background: none !important;
}

.bp20 {
	padding: 6px !important;
}

#ztsetWrap {
	margin-top: -96px !important;
}

.dtklist>.cbnWrap {
    max-height: 837px !important;
    padding: 5px 20px 0px 20px !important;
}

.col-md-3 {
    width: 19% !important;
}

.pdb20 {
    padding-bottom: 0px !important;
}

.subjectBody {
    padding-bottom: 0px !important;
}

.ISpan {
    margin-bottom: 2px !important;
    margin-right: 0 !important;
}

.pdt15 {
	padding-top: 0px !important;
}

.answerEnd {
	padding: 0 10px !important;
	margin-top: 0px !important;
}
.subject-content {
	padding: 0px 30px !important;
	background: none !important;
}
.answerWrap {
	padding: 0px 30px !important;
}

.jiexinew {
	padding: 5px 30px !important;
}

div.analysisAnswer > div.bg-fff.box-shadow.mgt10:nth-child(2) {
	padding-bottom: 0 !important;
}

.mgb20 {
	margin-bottom: 0px !important;
}
.answerList {
	padding: 0 15px !important;
}

.lh2 {
	margin-bottom: 5px !important;
}

.countTime {
	padding: 0 !important;
}
#ztsetWrap > div.bg-fff.box-shadow {
	margin-bottom: 0 !important;
}

.mgt10 {
	margin-top: 0px !important;
}

.swal-footer {
	text-align: center !important;
}

.lh2 {
	font-weight: bolder !important;
	color: #337ab7 !important;
	font-size: 1.125em !important;
}

.lh2 > span {
	display: none !important;
}
.shitiText.lh2 {
	font-weight: normal !important;
	color: #333 !important;
	font-size: 14px !important;
}

#accountSettingsHeader,
.center.answerCard,
.doPane,
.pull-right > span:not(:first-child),
.answerTitle {
	display: none !important;
}

#paperTitleWrap {
	display: none !important;
}

.center {
	margin-top: 0px !important;
	margin-bottom: 0px !important;
}

.modeTitle {
	padding-bottom: 0px !important;
}

.right-title {
	padding: 0 0 !important;
	margin-bottom: 0px !important;
}

.mgt {
	margin-top: 0px !important;
}

.subject-content {
	background: none !important;
}

header {
	height: 0px;
}

#navigation {
	height: 0px !important;
	line-height: 2rem !important;
}

.spanExplain {
	padding: 5px 20px !important;
}

.exBtn {
	margin-top: 5px !important;
}

.answerWrap {
	padding: 0px 30px !important;
}

.mgb20 {
	margin-bottom: 0px !important;
}

.singleR {
    font-size: 16px;
}
`;

  setTimeout(() => { main(); }, 1500);

  function main() {
    logInfo(GM_info.script.name, GM_info.script.version);
    let url = window.location.href;
    // 个人中心添加播放按钮
    if ("https://uc.educity.cn/personalCenter/studyCenter.html" == url) {
      updatePlayTitle();
    } else if (
      url.startsWith("https://www.educity.cn/wangxiao2") ||
      url.startsWith("http://www.educity.cn/wangxiao2") ||
      url.startsWith('https://wangxiao.xisaiwang.com/wangxiao2/')
    ) {
      // 直播回放调节播放速度
      updateSpeed();
    } else if (url.startsWith("https://uc.educity.cn/tiku/testReport.html")) {
      // 测试报告中,自动填充答案
      GM_addStyle(testReportStyle);
      autoFillAnswer();
    } else if (
      url.startsWith("https://uc.educity.cn/tiku/examinationModeCopy.html") ||
      url.startsWith("https://uc.educity.cn/tiku/examinationMode.html")
    ) {
      // 添加键盘监听事件,按键答题
      GM_addStyle(examStyle);
      addKeyListener();
    }
  }

  // 个人中心,学习列表添加播放按钮,修改标题描述
  function updatePlayTitle() {
    setTimeout(function () {
      document.getElementById("loadStuWrap").lastElementChild.click();
      setTimeout(function () {
        addPlayBotton();
        adjustDes();
      }, 1000);
    }, 1500);
  }

  // 个人中心,学习列表添加播放按钮
  function addPlayBotton() {
    const urlPrefix = "https://www.educity.cn/courseCenter/zhibo.html?gsver=2&id=";
    if (document.getElementsByClassName("enterStudy")) {
      let spans = document.getElementsByClassName("enterStudy");
      console.log(spans.length);
      for (let i = 0; i < spans.length; i++) {
        let dataId = spans[i].getAttribute("data-id");
        let url = urlPrefix + dataId;
        let aEle = document.createElement("a");
        aEle.setAttribute("href", url);
        aEle.setAttribute("target", "_blank");
        aEle.innerHTML = '<i class="icon_index_login_me inline-block icon-st"> </i>';
        spans[i].parentElement.append(aEle);
        spans[i].style.display = "none";
      }
    }
  }

  // 将描述移动到标题上
  function adjustDes() {
    let titleDivs = document.querySelectorAll("div.cMenuTitle.clearfix");
    for (let i = 0; i < titleDivs.length; i++) {
      let content = "";
      let aEle = titleDivs[i].nextElementSibling.querySelector("h4.panel-title>a");
      if (aEle) {
        content = aEle.innerText;
      }
      let childEle = document.createElement("div");
      childEle.setAttribute("class", "pull-left");
      childEle.innerHTML = "<span>" + content + "</span>";
      titleDivs[i].append(childEle);
      titleDivs[i].nextElementSibling.style.display = "none";
    }
  }

  function updateSpeed() {
    GM_addStyle(zhiBoStyle);

    addRemainingTime();
    addRateButton();
    addRateListener();
    updateSideHeight();
    addPersonalCenter();
  }


  /**
   * 添加倍速按钮
   */
  function addRateButton() {
    if (!$('.pv-rate-select') || $('.pv-rate-select').length == 0) {
      return;
    }
    $('<div data-rate="4">4x</div><div data-rate="3.5">3.5x</div><div data-rate="3">3x</div><div data-rate="2.5">2.5x</div>').insertBefore($('.pv-rate-select').children().eq(0));
  }

  // 获取当前倍速
  function getCurrentRate() {
    let rate = 1.0;
    let rateEle = document.querySelector('button.pv-rate-btn>span');
    if (!rateEle) {
      return rate;
    }
    rate = rateEle.textContent.replace("x", "");

    return rate;
  }

  /**
   * 添加控制播放速度的监听事件,仅用于更新显示当前速度,速度控制通过其他通用三方脚本实现。
   */
  function addRateListener() {
    let rateEle = document.querySelector('button.pv-rate-btn>span');

    document.onkeyup = function (e) {
      var theEvent = e || window.event;
      var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
      if (code == 88) {
        // X,减速
        let rate = getCurrentRate();
        let newRate = (new Number(rate) - new Number(0.1)).toFixed(1);
        let rateStr = newRate + "x";
        rateEle.textContent = rateStr;
        updateRate(rateStr);
      }
      if (code == 67) {
        // C,加速
        let rate = getCurrentRate();
        let newRate = (new Number(rate) + new Number(0.1)).toFixed(1);
        let rateStr = newRate + "x";
        rateEle.textContent = rateStr;
        updateRate(rateStr);
      }
      if (code == 90) {
        // Z,恢复正常速度
        rateEle.textContent = "1x";
        updateRate("1x");
      }
    };
  }

  /**
   * 更新右侧边栏上的播放倍率
   * @param {String} rate 播放倍率
   */
  function updateRate(rate) {
    let rateEle = document.querySelector('span.rateRight');
    if (rateEle) {
      rateEle.textContent = rate;
    } else {
      document.querySelector('.vid_midR_tab').appendChild($(`<span class="rateRight">${rate}</span>`)[0]);
    }
  }

  /**
   * 更新右侧侧边栏高度
   */
  function updateSideHeight() {
    let sideBar = document.querySelector('.vid_midR_tab');
    if (!sideBar) {
      return;
    }
    sideBar.style.height = sideBar.parentElement.previousElementSibling.offsetHeight + 'px';
    document.querySelector('.vid_midR_wrap').style.height = sideBar.parentElement.previousElementSibling.offsetHeight + 'px';
  }

  /**
   * 添加个人中心按钮
   */
  function addPersonalCenter() {
    $('<a href="/ucenter2/personal/index.html" target="_blank">个人中心</a>').insertBefore($('.vid_midR_tab').children().eq(0));
  }

  // 自动填充答案
  function autoFillAnswer() {
    setTimeout(function show() {
      var aa = document.getElementsByClassName("chak zhank");
      var bb = document.getElementsByClassName("ckjx");
      const answers = document.getElementsByClassName("answerEnd");
      for (let i = 0; i < answers.length; i++) {
        var ans = answers[i].children[0].innerText.replace("参考答案:", "").replace(/\s+/g, "");
        var your = answers[i].children[1].innerText.replace("你的答案:", "").replace(/\s+/g, "");
        if (ans != your) {
          aa[i].click();
          bb[i].click();
          var ansId;
          let yourId;
          switch (ans) {
            case "A":
              ansId = 0;
              break;
            case "B":
              ansId = 1;
              break;
            case "C":
              ansId = 2;
              break;
            case "D":
              ansId = 3;
              break;
            default:
              console.warn("error");
              break;
          }
          switch (your) {
            case "A":
              yourId = 0;
              break;
            case "B":
              yourId = 1;
              break;
            case "C":
              yourId = 2;
              break;
            case "D":
              yourId = 3;
              break;
            default:
              console.warn("Error: There's no your answer.");
              break;
          }
          var ansList =
            answers[i].parentElement.previousElementSibling.previousElementSibling.children[0]
              .children[1].children;
          ansList[ansId].style.fontWeight = "bold";
          ansList[ansId].style.color = "#51cb65";
          ansList[ansId].children[1].style.fontWeight = "bold";
          // ansList[ansId].children[0].children[0].checked = true;
          if (yourId != undefined) {
            ansList[yourId].style.color = "rgba(128, 128, 145,0.7)";
            ansList[yourId].style.textDecoration = "line-through";
          }
        }
      }
    }, 6000);
  }

  // 添加键盘监听事件,按键答题
  function addKeyListener() {
    document.onkeyup = function (e) {
      var theEvent = e || window.event;
      var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
      // 	Spacebar. 查看答案解析
      if (code == 32) {
        document.getElementsByClassName("col-md-4 center bottomCenter bp20")[0].click();
      }
      // Left Arrow.
      if (code == 37) {
        document.getElementsByClassName("col-md-4 center bp20 bLeftWrap")[0].click();
      }
      // Right Arrow.
      if (code == 39) {
        document.getElementsByClassName("col-md-4 center bp20 bRightWrap")[0].click();
      }
      // A,1.
      if (code == 49 || code == 65 || code == 97) {
        document.getElementById("slec0A").click();
      }
      // B,2.
      if (code == 50 || code == 66 || code == 98) {
        document.getElementById("slec0B").click();
      }
      // C,3.
      if (code == 51 || code == 67 || code == 99) {
        document.getElementById("slec0C").click();
      }
      // D,4.
      if (code == 52 || code == 68 || code == 100) {
        document.getElementById("slec0D").click();
      }
      // J. 标记
      if (code == 74 && document.getElementsByClassName("bj_icon addBiaoji")[0]) {
        document.getElementsByClassName("bj_icon addBiaoji")[0].click();
        setTimeout(function () {
          if (document.getElementsByClassName("swal-button swal-button--confirm")[0]) {
            document.getElementsByClassName("swal-button swal-button--confirm")[0].click();
            document.getElementsByClassName("col-md-4 center bp20 bRightWrap")[0].click();
          }
        }, 300);
      }
      // P.暂停
      if (code == 80 && document.getElementsByClassName("inline-block zanTing")[0]) {
        document.getElementsByClassName("inline-block zanTing")[0].click();
      }
    };
  }

  // ---------------------------------------------------
  // 添加剩余时间
  function addRemainingTime() {
    document.querySelector(".pv-time-current").addEventListener(
      "DOMSubtreeModified",
      function () {
        let remainingSeconds = getRemainingSeconds();
        let remainingTime = remainingSeconds > 0 ? formatSeconds(remainingSeconds) : "";
        let realRemainingSeconds = (new Number(remainingSeconds) / new Number(getCurrentRate())).toFixed(0);
        let realRemainingTime = formatSeconds(realRemainingSeconds);
        let overTime = getOverTime(realRemainingSeconds);

        let currentEle = document.querySelector('.pv-time-current');
        if (currentEle) {
          let parent = currentEle.parentElement;

          let remainingTimeSpan = document.querySelector('.pv-time-remaining.time-span');
          if (!remainingTimeSpan) {
            remainingTimeSpan = document.createElement("span");
            remainingTimeSpan.setAttribute("class", "pv-time-remaining time-span");
            parent.append(remainingTimeSpan);
          }
          remainingTimeSpan.textContent = '剩余时间:' + remainingTime;

          let realRemainingTimeSpan = document.querySelector('.pv-time-remaining-real.time-span');
          if (!realRemainingTimeSpan) {
            realRemainingTimeSpan = document.createElement("span");
            realRemainingTimeSpan.setAttribute("class", "pv-time-remaining-real time-span");
            parent.append(realRemainingTimeSpan);
          }
          realRemainingTimeSpan.textContent = '真实剩余时间:' + realRemainingTime;

          let overTimeSpan = document.querySelector('.pv-time-over.time-span');
          if (!overTimeSpan) {
            overTimeSpan = document.createElement("span");
            overTimeSpan.setAttribute("class", "pv-time-over time-span");
            parent.append(overTimeSpan);
          }
          overTimeSpan.textContent = '结束时间:' + overTime;
        }
        document.querySelector('.pv-video-wrap').nextElementSibling.setAttribute("class", "pv-skin-blue pv-video-bottom pv-subtitle-hide pv-show-fullscreen-page pv-base-control pv-first-h pv-first-hh");
      },
      false
    );
  }

  // 获取当前时间
  function getNowSeconds() {
    let nowSeconds = 0;
    let currentEle = document.querySelector('.pv-time-current');
    if (!currentEle) {
      return nowSeconds;
    }

    let nowTime = currentEle.textContent;
    let nowArr = nowTime.split(":");
    if (nowArr.length == 2) {
      nowSeconds = parseInt(nowArr[0]) * 60 + parseInt(nowArr[1]);
    } else if (nowArr.length == 3) {
      nowSeconds = parseInt(nowArr[0]) * 60 * 60 + parseInt(nowArr[1]) * 60 + parseInt(nowArr[2]);
    }

    return nowSeconds;
  }

  // 获取总时长
  function getAllSeconds() {
    let allSeconds = 0;
    let durationEle = document.querySelector(".pv-time-duration");
    if (!durationEle) {
      return allSeconds;
    }

    let allTime = durationEle.textContent;
    let allArr = allTime.split(":");
    if (allArr.length == 2) {
      allSeconds = parseInt(allArr[0]) * 60 + parseInt(allArr[1]);
    } else if (allArr.length == 3) {
      allSeconds = parseInt(allArr[0] * 60 * 60) + parseInt(allArr[1]) * 60 + parseInt(allArr[2]);
    }

    return allSeconds;
  }

  // 获取剩余时间
  function getRemainingSeconds() {
    let allSeconds = getAllSeconds();
    let nowSeconds = getNowSeconds();
    return allSeconds - nowSeconds;
  }

  // 获取结束时间
  function getOverTime(seconds) {
    let timestamp = new Date().getTime() + seconds * 1000;
    return dateFormat('HH:MM:SS', new Date(timestamp));
  }

  // 将秒格式化为时间格式
  function formatSeconds(value) {
    let result = parseInt(value);
    let h =
      Math.floor(result / 3600) < 10 ? "0" + Math.floor(result / 3600) : Math.floor(result / 3600);
    let m =
      Math.floor((result / 60) % 60) < 10
        ? "0" + Math.floor((result / 60) % 60)
        : Math.floor((result / 60) % 60);
    let s = Math.floor(result % 60) < 10 ? "0" + Math.floor(result % 60) : Math.floor(result % 60);

    let res = "";
    if (h !== "00") res += `${h}:`;
    if (m !== "00") res += `${m}:`;
    res += `${s}`;
    return res;
  }

  /**
   * Format date.
   * @param fmt format standard.
   * @param date date.
   * @returns {Time formatted string}
   */
  function dateFormat(fmt, date) {
    let ret;
    let opt = {
      'Y+': date.getFullYear().toString(),
      'm+': (date.getMonth() + 1).toString(),
      'd+': date.getDate().toString(),
      'H+': date.getHours().toString(),
      'M+': date.getMinutes().toString(),
      'S+': date.getSeconds().toString()
    };
    for (let k in opt) {
      ret = new RegExp('(' + k + ')').exec(fmt);
      if (ret) {
        fmt = fmt.replace(
          ret[1],
          ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
        );
      }
    }
    return fmt;
  }

  /**
   * Log the title and version at the front of the console.
   * @param {String} title title.
   * @param {String} version script version.
   */
  function logInfo(title, version) {
    console.clear();
    const titleStyle = 'color:white;background-color:#606060';
    const versionStyle = 'color:white;background-color:#1475b2';
    const logTitle = ' ' + title + ' ';
    const logVersion = ' ' + version + ' ';
    console.log('%c' + logTitle + '%c' + logVersion, titleStyle, versionStyle);
  }
})();

QingJ © 2025

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