在线留痕阅卷系统功能说明及其演示

引言

追求速度浏览者可以直接跳到项目图文展示下

本在线阅卷系统主要服务于高校,支持试卷导入到系统,动态分配任务给多个教师,同时在阅卷工作完成后从班级,知识点,试卷高分低分区分度,评判试卷难度,得分率,及格率,分数标准差等多角度多维度统计学生成绩展示考试成果。在支持成绩统计分析和成绩到处这方面极大的减轻了考试阅卷后试题改卷携带试卷的负担,减少了阅卷工作完成后,统计成绩分析成绩的工作量。在传统的考试情况中,每个老师的阅卷工作上报成绩流程及其繁琐麻烦,老师往往需要与学生试卷卷不离身导致便携性很差,即使在改完试卷后,上传分数至教务系统也需要人工参与。在考试完成后,统计成绩也需要一个精通Excel操作的办公人员,这中间的曲折流程,诸多繁琐的过程都需要很多的人力成本。而在线阅卷系统,仅仅需要一个浏览器,就可以完成以上所有工作,在满足分配任务,改卷,上传成绩,分析成绩的一系列服务上,还达到了诸多传统阅卷很难以完成的功能 。
比如试卷复查,试卷评价,错误时可撤销式改卷,节约大量阅卷人员的负担和减少考试后统计分析成绩的人力成本时间成本。
在线阅卷系统教务端是一个基于Java编程语言,前后端分离的B/S架构系统。
本系统应用主要技术有:

  • (1)应用层:使用Spring家族的SpringBoot,Spring,SpringMVC达到大部分对象的管理和解耦。
  • (2)持久层:使用MyBatis家族的MyBatis,Tk-MyBatis,MyBatisCodeHelpPro对MySQL数据库的访问和其他操作。
  • (3)其他:阿里的EasyExcel解析Excel文件,Thumbnailator切割试卷,Pagehelper辅助数据分页 。

项目亮点

1. 文件分片上传/断点续传/秒传功能的实现
2. 人性化的留痕阅卷功能
3.有损试卷的完整性还原
4.支持Excel批量操作和对用户输入的自动纠错
5 .根据不同的条件导出查询结果

项目图文展示

新增考试功能

介绍
考试使本项目的核心,所以新增考试也是必须要做的事情。在本系统中,新增考试的同时需要指定:

  • 本场考试的所有试卷(以压缩包的形式上传)
  • 考试的学期(根据数据库查询得出)
  • 考试所涉及的班级(用于判断哪些学生缺考和成绩分析)
  • 考试样卷(用于试卷预览和试卷切割参考)
    等等其他必要信息请看图。
    所设计到的技术
  • 文件的分片上传/秒传/断点续传
  • 文件的解压(如果解压失败数据库的本次新增信息能正确回滚,且磁盘解压的残留文件能够删除
    在线留痕阅卷系统功能说明及其演示_第1张图片
    上传成功在线留痕阅卷系统功能说明及其演示_第2张图片
    在上传考试完成后,在考试管理界面能够预览试卷,查看缺考的学生。
    在线留痕阅卷系统功能说明及其演示_第3张图片
    查看缺考学生
    在线留痕阅卷系统功能说明及其演示_第4张图片
    预览试卷
    在线留痕阅卷系统功能说明及其演示_第5张图片

试卷切割

查询出来还没有分配的考试,对试卷进行区域划分,便于后面将每个区域分配个不同的老师批阅试卷。

细节考虑:

  • 如果切割时候指定的分数大于考试满分,将不予通过本次操作。
  • 如果切割过程中发生意外,残留文件要删除。

切割开始界面
在线留痕阅卷系统功能说明及其演示_第6张图片
在线留痕阅卷系统功能说明及其演示_第7张图片
在线留痕阅卷系统功能说明及其演示_第8张图片
在线留痕阅卷系统功能说明及其演示_第9张图片

任务分配

试卷的切割为分配任务奠定数据基础,任务分配支持将一个任务分配给不同的老师。

细节考虑:

  • 分配的任务数不能大于可分配的数量。
  • 可以随意动态调整教师的任务数量。

展示了所有没有改完的卷子
在线留痕阅卷系统功能说明及其演示_第10张图片
在线留痕阅卷系统功能说明及其演示_第11张图片

教师改卷

分配好任务之后,教师端就可以看到自己被分配的任务。这里我登陆2222教师端。

在线留痕阅卷系统功能说明及其演示_第12张图片

教师阅卷
在线留痕阅卷系统功能说明及其演示_第13张图片
在线留痕阅卷系统功能说明及其演示_第14张图片

试卷分析

对试卷的总体分析。

术语介绍:

难度系数:根据考试的平均分和考试的总分计算得出。难度系数越高,说明试题越加简单。
区分度:根据高分段学生的成绩和低分段学生的成绩计算得出,判断试卷是否很好的区分出了学生梯度。
在线留痕阅卷系统功能说明及其演示_第15张图片
在线留痕阅卷系统功能说明及其演示_第16张图片
在线留痕阅卷系统功能说明及其演示_第17张图片

分数分析

显示考试的分数分布情况,可以按照班级分类显示。

在线留痕阅卷系统功能说明及其演示_第18张图片
在线留痕阅卷系统功能说明及其演示_第19张图片

成绩表

在线留痕阅卷系统功能说明及其演示_第20张图片
试卷复查(试卷合成)
在线留痕阅卷系统功能说明及其演示_第21张图片
本来试卷应该是这个样子:
在线留痕阅卷系统功能说明及其演示_第22张图片
通过算法补充了缺失的部分。
在线留痕阅卷系统功能说明及其演示_第23张图片

学期管理

不能删除已有考试的学期

在线留痕阅卷系统功能说明及其演示_第24张图片

在线留痕阅卷系统功能说明及其演示_第25张图片
Excel批量初始化班级

自动判断学生的唯一性质,一个学生不能存在于不同的班级。且能校验文件的合法性。

在线留痕阅卷系统功能说明及其演示_第26张图片
在线留痕阅卷系统功能说明及其演示_第27张图片
其他细节请看视频演示。
视频地址:视频地址

关键代码展示

比如如何实现文件秒传,断点续传,分片上传。

实现这个功能 需要前后端一起配合。
主要思路:
1.前端对整个文件计算MD5值,首先将这个MD5值传到后端的CHECK接口,后端通过这个值判断是否已经存在与服务器。如果存在,就返回存在的信息。前端根据这个信息可以直接略过文件上传的时间花费。(秒传的实现)
2.如果不存在,前端对文件进行分片,同时每个分片的MD5值也要计算。每次上传都要校验MD5值,如果存在,就略过,如果不存在,就接受文件上传。
3.所有分片上传完整后,对分片文件进行合成就是了。
4.如果中途断案,因为已经成果的部分已经保存了MD5值,所以断点续传和秒传是一个原理。

图片的还原
之所以能够达到图片的完整还原,是因为碎片在本地我存了两份。
在线留痕阅卷系统功能说明及其演示_第28张图片
一份是改了的,一份是没有改的。如果有改了的,就优先使用改了的合成。这样合成的试卷永远都是最新状态的样子。但是缺失的部分如何补充呢?
在线留痕阅卷系统功能说明及其演示_第29张图片
道理也很简单,因为我并没有把原来的试卷删除,切割的碎片在一个文件夹,原来的样子在一个文件夹。
在线留痕阅卷系统功能说明及其演示_第30张图片
在合成的时候判断哪里缺失,缺失的部分去unzip文件夹的图片寻找,就可以了。
代码展示:

  /**
     *
     * @param list 试卷碎片集合
     * @param paper 父试卷信息
     * @param exmple 样卷地址
     * @return
     * @throws Exception
     */
    public static synchronized String mergePaperAndCoverLoss(List<Studentblock> list, Paper paper, String exmple) throws Exception {
        //获取到样卷
        //还原样卷地址
//        String examplePaperAddr = PathUtil.getRealBasePath() + PathUtil.getPathWithOutHttpPaper(exmple);
        String examplePaperAddr =  PathUtil.getRealBasePath() + exmple;
        //样卷信息
        BufferedImage img = ImageIO.read(new File(examplePaperAddr));
        //获取改卷子的总大小
        int totalX = paper.getWidth(),
                totalY=paper.getHeight();
        //创建 这么大一个图片缓存
        BufferedImage bi=new BufferedImage(totalX,totalY,BufferedImage.TYPE_INT_RGB);
        //读取所有的子图片信息
        List<ImageBlock> imageBlocks = getImageBlocks(list);
        for (int i = 0; i <bi.getWidth() ; i++) {
            for (int j = 0; j <bi.getHeight() ; j++) {
                //判断需要补充的地方
                int rbg = getRbg(imageBlocks,img,i,j);
                bi.setRGB(i,j,rbg);
            }
        }
        //使用原来的目录
        String outPath = PathUtil.getRealBasePath() + "合成"+File.separator+paper.getPaperurl();
        File outFile = new File(outPath);
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        //生成高清图片
        ImageIO.write(bi,"jpeg",outFile);
        FileOutputStream out = new FileOutputStream(outFile.getAbsolutePath());
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param=encoder.getDefaultJPEGEncodeParam(bi);//
        param.setQuality(1, true);//设置质量
        encoder.encode(bi, param);
        out.close();
        //返回的HTTP地址
        String s = PathUtil.getHttpPaperLen() + PathUtil.getRelativePath(outFile.getAbsolutePath());
        return s;
    }
 /**
     * 返回 需要的 颜色
     * @param imageBlocks
     * @param exampleImg
     * @param i
     * @param j
     * @return
     */
    private static int getRbg(List<ImageBlock> imageBlocks, BufferedImage exampleImg, int i, int j) throws Exception {
        for (ImageBlock block : imageBlocks) {
            boolean b = block.contains(i, j);
            if (b){
                //传入的是全坐标
                return block.getRgb(i,j);
            }
        }
       /* System.out.println("此时的坐标不存在于数据库"+i+","+j);*/
        return exampleImg.getRGB(i,j);
    }

    private static List<ImageBlock> getImageBlocks(List<Studentblock> list) {
        List<ImageBlock> res = new ArrayList<>(list.size());
        for (Studentblock i : list) {
            //http://139.9.220.20:1997/edu/paper/2015180122\某某学期\subject\2020-05-11\1,2,3.jpg
            String blockurl = i.getBlockurl();
            blockurl = PathUtil.getRealBasePath() + PathUtil.getPathWithOutHttpPaper(blockurl);
            String markedPath = PathUtil.getMarkedPath(blockurl);
            //临时文件
            File file = new File(markedPath);
            if (file.exists() == true){
                blockurl = markedPath;
            }
            //判断置是否存在
            ImageBlock block = new ImageBlock(new File(blockurl));
            //数据库的坐标是全坐标
            block.setX(i.getX());
            block.setY(i.getY());
            block.setEx(i.getX()+i.getWidth());
            block.setEy(i.getY()+i.getHeight());
            res.add(block);
        }
        return res;
    }


    @Data
    @NoArgsConstructor
    protected static class ImageBlock{
        public ImageBlock(File file){
            try {
              /*  System.out.println(file.getAbsolutePath());*/
                this.bufferedImage = ImageIO.read(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private BufferedImage bufferedImage;
        //这里可是还原了全坐标(意思就是大)
        private int x;
        private int y;
        private int ex;
        private int ey;
        //判断合成需要的像素点是否是我能够提供的
        public boolean  contains(int a,int b){
          if ((a>x && a < ex) && (b > y && b < ey)){
              //在里面
              return true;
          }
          return  false;
      }
      //获取像素点方法
        public int getRgb(int i, int j)  {
//                return bufferedImage.getRGB(i-(ex-x),j-(ey-y));
                return bufferedImage.getRGB(i-x,j-y);
        }
    }

结语

本系统能够完全应付高校的阅卷需求,且在细节方面考虑完全,能够屏蔽很多非法操作和不正确的操作以免对数据造成删改。
例如:
删除失败时候的残留文件
删除一场考试删除与此考试相关的所有数据。
对教师打分的合法校验
在使用上,人性化的留痕阅卷和多角度的成绩分析统计功能充分发挥了在线阅卷的优势。

视频地址:项目演示视频B站地址

目的:我是想找个工作,才发这个博客的!(兄弟们,校招一定要保底啊,应届生想实习还是太难了。我已经工作了,555.)
另外我还自研了仿造Spring的框架.实现了IOC,AOP,MVC,ORM。框架地址:git地址
技术路程:!自己手写一个AOP动态代理框架(1)

我微信:qazwsxFuYouJie

你可能感兴趣的:(Java)