美文网首页
一起来摆脱教务系统强制教评的痛苦

一起来摆脱教务系统强制教评的痛苦

作者: 忠叔 | 来源:发表于2017-07-04 20:43 被阅读5120次

    文章的最后给出了使用方法,如果你没有编程经验的话,按照底下的教程直接拿来用就可以啦。

    故事是这么开始的

    每学习期末都会被教务系统的教学质量评价系统折腾的很惨,因为我必须完成所有科目的评价才能干别的事情。但是做这个评价又是一个非常痛苦的过程,每一个科目都要选一堆的项目,曾经因为选了十几门课,被教评狠狠地折腾到双手残废。

    image.png

    我曾在空间里看到有同学发过自动填充表单的脚本,大致是这样的

    var divJs=frame.getElementById('divJs');
    var items=divJs.querySelectorAll('select');
    for(i=0;i<items.length;i++)
        items[i].value="1(完全同意)"
    

    其实原理很简单,就是查询到所有评价项目的DOM,把它们的值逐一改成第一项就行了。运行这段脚本,页面上所有的评价就会自动填好,这时只要点击保存就可以了。
    不过因为教务系统的网页是一个框架结构,教评的页面实际上是嵌在一个iframe里面的,所以我们要先让这个页面独立地在一个新标签中打开,才能去运行这段脚本。

    image.png

    不过聪明的你一定能发现其中的缺陷,我们在保存完之后,浏览器就会跳转到下一个科目的评价页面,这时候我们刚才运行的脚本已经被删除掉了。于是我们就得在每个页面把这个脚本粘贴到控制台再运行。在课程非常多的情况下,评价的效率仍有很大的提升空间。

    第一次优化

    这个时候我们正好可以利用教务系统这个框架结构的特点,我们在父页面运行脚本,让子页面在iframe跳转,脚本则可以一直保留在父页面中。我们对最初的脚本做一些改动,让父页面获取框架内的DOM(因为它们是同域的),再把代码封装到函数内,每跳到一个新页面执行一次函数就行了。

    function autoFill() {
      var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
      var divJs = frame.getElementById('divJs');
      var items = divJs.querySelectorAll('select');
      for (i = 0; i < items.length; i++)
        items[i].value = "1(完全同意)"
    }
    autoFill();
    
    image.png

    这时,你一定能想到,既然都做到这一步了,干脆让点击保存按钮这个步骤也自动化咯,这样还省去了自己按按钮的麻烦。这时候,我们再加入一个间隔计时器,设定每2秒钟进行一次自动填充,并且保存。这样只要执行一次脚本,就可以哗哗哗地运行到底啦。

    function autoFill() {
      var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
      var divJs = frame.getElementById('divJs');
      var items = divJs.querySelectorAll('select');
      for (i = 0; i < items.length; i++)
        items[i].value = "1(完全同意)"
      frame.getElementById('Button1').click();
    }
    setInterval(autoFill, 2000);
    

    设定跳转的结束边界

    很快我们就发现一个问题,当保存完最后一个科目的评价时,就应该提交了。但是由于计时器还在运行,这时候我们的框架还会不断地刷新,虽然这时你直接点击提交并且关闭页面就没事了,不过对于前端人员来说这样子太不优雅了。在这里加入一个判断方式:在进入一个新页面时,通过DOM获取课程代码,并保存在一个变量中。如果获取到的代码和上一次获取的代码是一样的,说明最后一个科目已经评价完成了,这时删除定时器就可以了。

    var courseCode;
    var timer;
    
    function autoFill() {
      var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
      var divJs = frame.getElementById('divJs');
      var items = divJs.querySelectorAll('select');
    
      var newCourseCode=frame.getElementById('pjkc').value;
      if(newCourseCode==courseCode){
        clearInterval(timer);
        return;
      }
      courseCode=newCourseCode;
    
      for (i = 0; i < items.length; i++)
        items[i].value = "1(完全同意)"
      frame.getElementById('Button1').click();
    }
    timer=setInterval(autoFill, 2000);
    

    优化轮询的方式

    这里对计时器再进行一个改进,因为现在的执行间隔是2秒,在遇到网速慢的情况,或者函数从任务队列里弹出的时候正好DOM没有加载出来,那就会产生错误。在刚才的基础上,加入一个判断,如果获取不到课程代码的DOM(忽略获取课程代码和评价选项的微小的时间差),则跳过这次轮询,进入下一次就可以了。同时我们可以把轮询时间调短到1秒1次,这对服务器来说还是没有压力的。

    var courseCode;
    var timer;
    
    function autoFill() {
      var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
      var divJs = frame.getElementById('divJs');
      var items = divJs.querySelectorAll('select');
    
      if(!frame.getElementById('pjkc'))
        return false;
    
      var newCourseCode=frame.getElementById('pjkc').value;
      if(newCourseCode==courseCode){
        clearInterval(timer);
        console.log('评价完成');
        return true;
      }
      courseCode=newCourseCode;
    
      for (i = 0; i < items.length; i++)
        items[i].value = "1(完全同意)"
      frame.getElementById('Button1').click();
    }
    timer=setInterval(autoFill, 1000);
    

    收尾

    最后,把我们的代码重新整理一下,封装到一个闭包里面,避免污染了全局作用域。一个用起来超爽的自动教评程序就完成了。

    (function() {
      var courseCode;
      var timer;
    
      var autoFill=function() {
        var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
        var divJs = frame.getElementById('divJs');
        var items = divJs.querySelectorAll('select');
    
        if (!frame.getElementById('pjkc'))
          return false;
    
        var newCourseCode = frame.getElementById('pjkc').value;
        if (newCourseCode == courseCode) {
          clearInterval(timer);
          console.log('评价完成');
          return true;
        }
        courseCode = newCourseCode;
    
        for (i = 0; i < items.length; i++)
          items[i].value = "1(完全同意)"
        frame.getElementById('Button1').click();
      }
      timer = setInterval(autoFill,1000);
    })();
    

    测试起来,速度堪比开车。本来想写成chrome插件的,不过这种一次性的东西,装上还得卸掉也麻烦,就直接附上脚本的运行方式,不学编程的同学也可以拿来用喔。


    附:大众版使用方法

    首先你要复制下面这段代码

    (function() {
      var courseCode;
      var timer;
    
      var autoFill=function() {
    
        var frame = document.getElementById('rightDiv').getElementsByTagName('iframe')[0].contentWindow.document;
    
        if (!frame || !frame.getElementById('pjkc'))
            return false;
    
        var divJs = frame.getElementById('divJs');
        var items = divJs.getElementsByTagName('select');
    
        var newCourseCode = frame.getElementById('pjkc').value;
    
        console.log(newCourseCode,courseCode)
    
        if (newCourseCode == courseCode) {
          clearInterval(timer);
          console.log('评价完成');
          return true;
        }
        courseCode = newCourseCode;
    
        for (i = 0; i < items.length; i++)
          items[i].value = "1(完全同意)"
        frame.getElementById('Button1').click();
      }
      timer = setInterval(autoFill, 2000);
    })();
    

    打开教务系统,进入教学评价页面

    image.png

    打开浏览器的控制台

    多数浏览器的控制台是按F12调出,或者在网页上点击右键->审查元素,在菜单里找一找有没有开发者工具。打开面板后,选择Console,就是控制台了。

    image.png

    粘贴代码回车,10秒搞定,这下就可以放飞自我地查成绩了!

    相关文章

      网友评论

          本文标题:一起来摆脱教务系统强制教评的痛苦

          本文链接:https://www.haomeiwen.com/subject/biixhxtx.html