东南大学抢课助手

听说你抢不到课

目前为 2021-05-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         东南大学抢课助手
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  听说你抢不到课
// @author       realhuhu
// @match        http://newxk.urp.seu.edu.cn/xsxkapp/sys/xsxkapp/*
// @icon         https://huhu-1304907527.cos.ap-nanjing.myqcloud.com/share/qkzs
// @grant        none
// ==/UserScript==

(function () {
  'use strict';
  (_ => {
    _.init = () => {
      window.raw = {}
      window.result = []
      getAllCourses()
    }

    let getAllCourses = () => {
      $.ajax({
        type: "POST",
        url: "http://newxk.urp.seu.edu.cn/xsxkapp/sys/xsxkapp/elective/recommendedCourse.do",
        data: buildQueryTCParam(""),
        dataType: "json",
        ContentType: "application/json",
        beforeSend: XMLHttpRequest => {
          XMLHttpRequest.setRequestHeader("token", sessionStorage["token"])
        },
        success: data => {
          window.allCourses = data.dataList
          window.allCoursesId = getAllCoursesId(data.dataList)
        }
      })
    }

    let getAllCoursesId = allCourses => {
      let allCoursesId = []
      allCourses.forEach(value => {
        value.tcList.forEach(value => {
          allCoursesId.push(value.teachingClassID)
        })
      })
      return allCoursesId
    }


    let getSingleCourse = id => {
      let courseName = ""
      let teacherName = ""
      let info = {}
      allCourses.forEach(value => {
        courseName = value.courseName
        value.tcList.forEach(value => {
          if (value.teachingClassID === id) {
            teacherName = value.teacherName
            info = {course: courseName, teacher: teacherName}
          }
        })
      })
      return info
    }

    _.updateRaw = id => {
      if (window.raw[id] === undefined) {
        let index = Object.keys(window.raw).map(s => s.substr(0, s.length - 2)).indexOf(id.substr(0, id.length - 2))
        if (index === -1) {
          window.raw[id] = getSingleCourse(id)
          $.bhTip({
            content: "已添加",
            state: "success",
            hideWaitTime: 1000
          })
        } else {
          window.raw.length = 0
          Object.keys(window.raw).splice(index, 1, id).forEach(key => {
            raw[key] = getSingleCourse(key)
          })
          $.bhTip({
            content: "已替换",
            state: "success",
            hideWaitTime: 1000
          })
        }
      } else {
        $.bhTip({
          content: "你已经添加过这门课了",
          state: "danger",
          hideWaitTime: 2000
        })
      }
      Components.reloadList()
    }

  })(window.Courses = window.Courses || {});

  (_ => {
    _.mount = () => {
      createTag()
      createPanel()
      createModal()
      createAddButton()
    }

    let createTag = () => {
      let target = $(".cv-icons")[0]
      let wrap = document.createElement("div")
      wrap.setAttribute("class", "cv-user-icon cvMiniIconFlag")
      wrap.setAttribute("title", "抢课列表")
      wrap.setAttribute("onclick", "toggle()")
      wrap.innerHTML = tagTemplate()
      target.appendChild(wrap)
    }

    let createPanel = () => {
      let target = $("body")[0]
      let wrap = document.createElement("div")
      wrap.setAttribute("class", "panel hide")
      wrap.setAttribute("style", "display:none")
      wrap.innerHTML = panelTemplate()
      target.appendChild(wrap)
    }

    let createModal = () => {
      let target = $("body")[0]
      let wrap = document.createElement("div")
      wrap.setAttribute("class", "musk cover")
      wrap.setAttribute("style", "display:none; z-index:10000000;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8)")
      wrap.innerHTML = _.modalTemplate(result)
      target.appendChild(wrap)
    }

    let createAddButton = () => {
      let row = []
      let cards = []
      new Promise((resolve, reject) => {
        let timer = setInterval(() => {
          row = $("article .cv-row")
          if (row.length !== 0) {
            clearInterval(timer)
            resolve()
          }
        }, 10)
      }).then(successMessage => {
        for (let i = 0; i < row.length; i++) {
          row[i].addEventListener("click", () => {
            new Promise((resolve, reject) => {
              let timer = setInterval(() => {
                let target = row[i]
                cards = target.getElementsByClassName("cv-info")
                if (cards.length !== 0) {
                  clearInterval(timer)
                  resolve()
                }
              }, 10)
            }).then(successMessage => {
              for (let j = 0; j < cards.length; j++) {
                let target = cards[j]
                let id = target.querySelectorAll("button[tcid]")[0].getAttribute("tcid")
                if (target.getElementsByClassName("add").length === 0) {
                  let wrap = document.createElement("div")
                  wrap.setAttribute("class", "cv-caption-text cv-operation add")
                  wrap.innerHTML = '<button class="cv-btn cv-btn-cancel" type="button"  style="margin-left:0" onclick="addCourse(\'' + id + '\')">添加到列表</button>'
                  target.appendChild(wrap)
                }
              }
            })
          })
        }
      })
    }

    let tagTemplate = () =>
      '<svg t="1622102436350" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1611" width="100%" height="100%">' +
      '<path d="M768 952.32h-512c-57.344 0-102.4-45.056-102.4-102.4v-675.84c0-57.344 45.056-102.4 102.4-102.4h512c57.344 0 102.4 45.056 102.4 102.4v677.888c0 55.296-47.104 100.352-102.4 100.352z m-512-839.68c-34.816 0-61.44 26.624-61.44 61.44v675.84c0 34.816 26.624 61.44 61.44 61.44h512c32.768 0 61.44-26.624 61.44-59.392V174.08c0-34.816-26.624-61.44-61.44-61.44h-512z" p-id="1612" fill="#ffffff"/>' +
      '<path d="M714.752 530.432H309.248c-12.288 0-20.48-8.192-20.48-20.48s8.192-20.48 20.48-20.48h405.504c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48zM714.752 348.16H309.248c-12.288 0-20.48-8.192-20.48-20.48s8.192-20.48 20.48-20.48h405.504c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48zM598.016 716.8H309.248c-12.288 0-20.48-8.192-20.48-20.48s8.192-20.48 20.48-20.48h288.768c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48z" p-id="1613" fill="#ffffff"/>' +
      '</svg>'

    let panelTemplate = () => {
      let content = ''
      content += '<div style="width: 350px;height: 100%;float: left;position: fixed;top: 0;left: 0;background-color: rgba(61,72,105,0.9);z-index: 10000">'
      content += '<h1 style="color: #c7e6e6;margin-left: 20px; text-align: center">东大抢课脚本</h1>'
      content += '<hr>'
      content += '<input class="cv-search-input" id="enter" placeholder="输入课程编号+老师编号后,按回车添加" type="text"  style="width: 90%; margin:10px 5% 10px" onkeydown="enterCourse(\'' + event + '\')">'
      content += '<div class="list-wrap" style="overflow: auto;margin: 10px;border:1px solid white;height: 50%">'
      content += listTemplate(raw)
      content += '</div>'
      content += '<hr>'
      content += '<div class="cv-clearfix-child"><button class="cv-btn cv-btn-chose crab" style="width: 120px;height: 40px;font-size: 20px;float: right;margin: 20px 30px 0" onclick="crab()">一键抢课</button></div>'
      content += '<div class="cv-clearfix-child"><button class="cv-btn cv-btn-cancel show-result" style="width: 120px;height: 40px;font-size: 20px;float: right; margin: 20px 30px 0;display: none" onclick="showResult()">显示结果</button></div>'
      content += '</div>'
      return content
    }

    let listTemplate = raw => {
      let content = ''
      content += ' <div class="cv-list">'
      content += '<div class="cv-head">'
      content += '<div class="cv-normal" style="width: 60%">已选课程</div>'
      content += '<div class="cv-normal" style="width: 20%">教师</div>'
      content += '<div class="cv-normal" style="width: 20%">操作</div>'
      content += '</div>'
      if (JSON.stringify(raw) !== '{}') {
        content += '<div class="cv-body">'
        Object.keys(raw).forEach(key => {
          let course = raw[key].course
          let teacher = raw[key].teacher
          content += '<div class="cv-row">'
          content += '<div style="width: 60%;color: lightblue;height: 45px;border-right:1px solid rgba(230, 240, 252, 0.6);font-size: ">' + course + '</div>'
          content += '<div style="width: 20%;color: lightblue;height: 45px;border-right:1px solid rgba(230, 240, 252, 0.6)">' + teacher + '</div>'
          content += '<div style="width: 20%;height: 45px"><button class="cv-btn cv-btn-cancel" type="button" onclick="removeCourse(\'' + key + '\')">移除</button></div>'
          content += '</div>'
        })
        content += '</div>'
      } else {
        content += "<h3 style='color:lightblue;margin-top: 50%'>还未选择课程</h3>"
      }
      content += '</div>'
      return content
    }

    _.modalTemplate = result => {
      let content = ''
      content += '<div style="position: fixed;left: 20%;top:20%;width: 60%;height: 60%;background-color: white">'
      content += '<div style="margin: 60px 50px 0;height: 45vh;overflow: auto; border:1px solid rgba(61,72,105,0.9)">'
      content += '<div class="cv-list">'
      content += '<div class="cv-head">'
      content += '<div class="cv-normal" style="width: 40%">课程</div>'
      content += '<div class="cv-normal" style="width: 60%">结果</div>'
      content += '</div>'
      content += '<div class="cv-body">'
      result.forEach(value => {
        let course = value.course
        let result = value.result
        content += '<div class="cv-row">'
        content += '<div style="width: 40%;color: black;height: 45px;border-right:1px solid rgba(230, 240, 252, 0.6) ">' + course + '</div>'
        content += '<div style="width: 60%;color: black;height: 45px;border-right:1px solid rgba(230, 240, 252, 0.6)">' + result + '</div>'
        content += '</div>'
      })
      content += '</div>'
      content += '</div>'
      content += '</div>'
      content += '<button class="cv-btn cv-btn-chose" style="width: 120px;height: 40px;font-size: 20px;float: right;margin: 20px 50px 0" onclick="closeResult()">确定</button>'
      content += '</div>'
      return content
    }

    _.reloadList = () => {
      $(".list-wrap")[0].innerHTML = listTemplate(raw)
    }

  })(window.Components = window.Components || {});

  (() => {
    window.toggle = () => {
      let target = $(".panel")
      if (target.hasClass("hide")) {
        target.removeClass("hide")
        target.removeAttr("style")
      } else {
        target.addClass("hide")
        target.attr("style", "display:none")
      }
    }

    window.removeCourse = key => {
      delete raw[key]
      Components.reloadList()
      $.bhTip({
        content: "已移除",
        state: "success",
        hideWaitTime: 1000
      })
    }

    window.enterCourse = e => {
      let evt = window.event || e;
      if (evt.keyCode === 13) {
        let target = $("#enter")
        let id = target.val()
        id = "202020214" + id
        if (allCoursesId.indexOf(id) !== -1) {
          if (raw[id] === undefined) {
            target.val("")
            Courses.updateRaw(id)
          } else {
            $.bhTip({
              content: "你已经添加过这门课了",
              state: "danger",
              hideWaitTime: 2000
            })
          }
        } else {
          $.bhTip({
            content: "无效的课程代码,请重新输入",
            state: "danger",
            hideWaitTime: 2000
          })
        }
      }
    }

    window.crab = () => {
      if (JSON.stringify(raw) === '{}') {
        $.bhTip({
          content: "你还没有选择课程!!!",
          state: "danger",
          hideWaitTime: 2000
        })
      } else {
        window.result.length = 0
        let posts = []
        Object.keys(raw).forEach(key => {
          let param = buildAddVolunteerParam(key)
          posts.push($.ajax({
            type: "POST",
            url: "http://newxk.urp.seu.edu.cn/xsxkapp/sys/xsxkapp/elective/volunteer.do",
            data: param,
            dataType: "json",
            ContentType: "application/json",
            beforeSend: XMLHttpRequest => {
              XMLHttpRequest.setRequestHeader("token", sessionStorage["token"])
            },
            success: data => {
              result.push({"course": raw[key].course + "  " + raw[key].teacher, "result": data.msg})
            }
          }))
        })
        $(".crab")[0].innerText = "请等待.."
        $.when(...posts).done(() => {
          $(".crab")[0].innerText = "一键抢课"
          $.bhTip({
            content: "抢课完成",
            state: "success",
            hideWaitTime: 1000
          })
          $(".show-result").css("display", "")
        })
      }
    }

    window.showResult = () => {
      let target = $(".musk")
      if (target.hasClass("cover")) {
        target.removeClass("cover")
        target.css("display", "")
        target[0].innerHTML = Components.modalTemplate(result)
      }
    }

    window.closeResult = () => {
      let target = $(".musk")
      target.addClass("cover")
      target.css("display", "none")
    }

    window.addCourse = id => {
      if (raw[id] === undefined) {
        Courses.updateRaw(id)
      } else {
        $.bhTip({
          content: "你已经添加过这门课了",
          state: "danger"
        })
      }
    }
  })();

  $(() => {
    Courses.init()
    Components.mount()
  })
})
();

QingJ © 2025

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