题库和试卷模块构建

题库和试卷模块分为题库分类、题库管理、试卷管理

题库分类

分类是否存在

方法的返回值是false,参数是分类名称,该方法就是判断分类名称是否重复

以分类名称为参数,在题库分类表中查询,生成一个list,list不为空返回true,否则返回false

/**
     * 分类是否存在
     * 返回值是boolean 参数是分类名称
     * @param questionCategoryName
     * @return
     */
    boolean exists(String questionCategoryName);
/**
     * 分类是否存在
     * 就是根据分类名称在分类列表中查询,看是否能查到相关的分类记录列表
     * boolean exists(String questionCategoryName);
     * 参数是分类名称 返回值是boolean
     * @param questionCategoryName
     * @return
     */
    @Override
    public boolean exists(String questionCategoryName) {
        if(StrUtil.isEmpty(questionCategoryName)) {
            throw new BerryException("请输入分类名称");
        }
        QueryWrapper<CourseQuestionCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestionCategory::getQuestionCategoryName,queryWrapper);
        List<CourseQuestionCategory> list = list(queryWrapper);
        //根据分类名称查到分类列表之后,看列表中是否有数据,列表不为空,返回true,列表为为空,返回false
        if(CollUtil.isNotEmpty(list)) {
            return true;
        }
        return false;
    }

新增题库分类

/**
     * 新增题库分类
     * @param courseQuestionCategoryVO
     * @return
     * @throws BerryException
     */
    boolean addQuestionCategory(CourseQuestionCategoryVO courseQuestionCategoryVO) throws BerryException;
//先判断参数,然后创建对象,赋值属性,调用新增方法
@Override
public boolean addQuestionCategory(CourseQuestionCategoryVO courseQuestionCategoryVO) throws BerryException {
    if(courseQuestionCategoryVO==null){
        throw new BerryException("请输入分类参数!");
    }
    if(StrUtil.isEmpty(courseQuestionCategoryVO.getQuestionCategoryName())){
        throw new BerryException("请输入题库分类名称");
    }
    if (exists(courseQuestionCategoryVO.getQuestionCategoryName())) {
        throw new BerryException("分类已存在");
    }
    try {
        CourseQuestionCategory questionCategory  = new  CourseQuestionCategory();
        BeanUtils.copyProperties(courseQuestionCategoryVO,questionCategory);
        return save(questionCategory);
    } catch (BerryException e) {
        throw new BerryException(e.getMessage());
    }
}

更新题库分类

判断参数不为空,判断题库分类名称不能重复(条件是主键不相等,名称相等),然后创建要更新的分类的对象,赋值属性之后进行更新

/**
     * 更新题库分类
     * @param courseQuestionCategoryVO
     * @return
     * @throws BerryException
     */
    boolean updateQuestionCategory(CourseQuestionCategoryVO courseQuestionCategoryVO) throws BerryException;
 /**
     * 更新题库分类
     * courseQuestionCategoryVO: 分类id ,分类名称,分类说明,分类父id
     * @param courseQuestionCategoryVO
     * @return
     * @throws BerryException
     */
    @Override
    public boolean updateQuestionCategory(CourseQuestionCategoryVO courseQuestionCategoryVO) throws BerryException {
        //先判断参数
        if(courseQuestionCategoryVO == null) {
            throw new BerryException("请输入分类参数");
        }
        if(courseQuestionCategoryVO.getQuestionCategoryId() == null) {
            throw new BerryException("请输入分类id");
        }
        if(StrUtil.isEmpty(courseQuestionCategoryVO.getQuestionCategoryName())) {
            throw new BerryException("请输入分类名称");
        }
        //先从数据库中取数据,看具体的分类对象是否存在
        CourseQuestionCategory courseQuestionCategory = getById(courseQuestionCategoryVO.getQuestionCategoryId());
        if(courseQuestionCategory == null) {
            throw new BerryException("题库分类不存在");
        }
        //判断题库分类名称是否已经存在
        //就是查一下去掉我们修改的这个对象,还有没有别的分类叫这个名称
        QueryWrapper<CourseQuestionCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().ne(CourseQuestionCategory::getQuestionCategoryId,courseQuestionCategoryVO.getQuestionCategoryId());
        queryWrapper.lambda().eq(CourseQuestionCategory::getQuestionCategoryName,courseQuestionCategoryVO.getQuestionCategoryName());
        List<CourseQuestionCategory> list = list(queryWrapper);
        if(CollUtil.isNotEmpty(list)) {
            throw new BerryException("该题库分类名称已经存在");
        }
        BeanUtils.copyProperties(courseQuestionCategoryVO,courseQuestionCategory);
        return updateById(courseQuestionCategory);
    }

删除题库分类

1参数是分类id,先根据分类id查询题库,若该分类下面有题库不能删除

2该分类id为父id,查询二级分类列表,然后构建List<Long> categoryIdList,用于存放二级分类的id

循环二级分类列表,同上判断每个子分类下面是否有题库,把分类id装到categoryIdList,循环外删除子分类列表(removeByIds(categoryIdList))

3,没有二级分类列表直接删除

/**
     * 删除题库分类
     * @param id
     * @return
     * @throws BerryException
     */
    boolean deleteQuestionCategory(Long id) throws BerryException;
/**
     * 删除题库分类
     * 如果该分类下面有题库,先清除分类下的题库
     * 如果该分类的子分类下面有题库,先清除子分类下面的题库
     * 参数:分类id
     * @param id
     * @return
     * @throws BerryException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteQuestionCategory(Long id) throws BerryException {
        if(id == null) {
            throw new BerryException("请输入id");
        }
        //创建QuestionDbVo对象,这个是查询题库列表方法的参数,
        //创建对象之后,还需要传入分类id
        QuestionDbVo questionDbVo = new QuestionDbVo();
        questionDbVo.setCategoryId(id);
        //根据题库分类id查询对应的题库分类列表
        List<CourseQuestionDb> courseQuestionDbs = courseQuestionDbService.getDbList(questionDbVo);
        if(CollUtil.isNotEmpty(courseQuestionDbs)) {
            throw new BerryException("该分类下存下题库,请先删除分类下面的题库");
        }
        //以参数id为父id,查询对应的题库分类列表,循环该分类列表,就可以通过每个子分类的id,看每个子分类下面是否有对应的题库
        QueryWrapper<CourseQuestionCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestionCategory::getParentId,id);
        List<CourseQuestionCategory> list = list(queryWrapper);
        if(list != null && list.size() > 0) {
            //初始化子分类id列表
            List<Long> categoryIdList = new ArrayList<>();
            list.forEach(obj-> { 
                QuestionDbVo childDbVo = new QuestionDbVo();
                childDbVo.setCategoryId(obj.getQuestionCategoryId());
                List<CourseQuestionDb> dbList = courseQuestionDbService.getDbList(childDbVo);
                if(CollUtil.isNotEmpty(dbList)) {
                    throw new BerryException("该子分类下面存在题库,请先删除子分类下面的题库");
                }
                categoryIdList.add(obj.getQuestionCategoryId());
            });
            //若子分类下面没有题库了,批量删除子分类列表
            removeByIds(categoryIdList);
        }
        return removeById(id);
    }

分类树形二级列表展示

package com.rong.resourcestudy.question.dto;


/**
 * QuestionCategoryTreeDto 有 CourseQuestionCategory的全部属性
 * List<QuestionCategoryTreeDto> children; 是另外设置的属性
 *
 */
 @Data
public class QuestionCategoryTreeDto1 extends CourseQuestionCategory {

    /**
      * 子菜单
      */
    List<QuestionCategoryTreeDto1> children;

    /**
     * 把数据库中普通的分类列表转换成树形列表
     *      * 1判断参数分类列表是否为空
     *      * 2new HashMap<>()创建map<Long,树形类>,new ArrayList<>()创建树形类的数组列表
     *      * 3对参数列表进行循环,可以使用list.stream.forEach,也可以使用for(:)
     *      * 在循环里面创建树形类的对象,把实体类对象的属性赋值给树形类对象,再把树形类对象拿去给创建的map赋值
     *      * 4赋值完成之后,还是对参数列表进行增强for循环,通过map.get(parentId/主键)得到树形类对象
     *      * if (parentId == null) 如果父id为空,直接把主键对象放在创建的树形数组列表,
     *      * 父id 不为空,通过map和父id获取父对象,父对象为空,也是当前对象直接添加
     *      * 父对象不为空判断父对象的chirdren是否为空,
     *      * 为空的话,需要初始化children, List<FileCategoryTreeVo> children = new ArrayList<>();把当前对象放在children中,
     *      * 再把children放入父节点之中,
     *      *不为空,不用创建对象,直接放入就行
     * @param categoryList
     * @return
     */
    public static List<QuestionCategoryTreeDto1> convertCategoryList2Tree(List<CourseQuestionCategory> categoryList) {
        //先判断参数列表不能为空
        if(CollUtil.isEmpty(categoryList)) {
            return ListUtil.empty();
        }
        //2new HashMap<>()创建map<Long,树形类>
        Map<Long,QuestionCategoryTreeDto1> menuTreeDtoMap = new HashMap<>();
        categoryList.stream().forEach(item-> {
            //属性赋值
            QuestionCategoryTreeDto1 questionCategoryTreeDto1 = new QuestionCategoryTreeDto1();
            //这样子继承于父类的属性就可以完成赋值
            BeanUtils.copyProperties(item,questionCategoryTreeDto1);
            //把得到的树形类对象封装成map,键是分类id,值是树形类对象
            menuTreeDtoMap.put(item.getQuestionCategoryId(),questionCategoryTreeDto1);
        });
        //初始化树形类列表
        List<QuestionCategoryTreeDto1> questionCategoryTreeDto1s = new ArrayList<>();
        for(CourseQuestionCategory category:categoryList) {
            //循环分类列表,获取分类对象的父id,根据分类id获取对应的dto
            Long parentId = category.getParentId();
            QuestionCategoryTreeDto1 currentCategoryDto = menuTreeDtoMap.get(category.getQuestionCategoryId());
            //若该对象的父id为空,自己就是父对象,直接把自己放入初始化的树形列表之中
            if(parentId == null) {
                questionCategoryTreeDto1s.add(currentCategoryDto);
            } else {
                //下面对应的都是当前对象有父id的情况

                //若该对象的父id不为空,那么先通过父id获得该对象的父树形对象
                QuestionCategoryTreeDto1 parentCategory = menuTreeDtoMap.get(parentId);
               if(parentCategory == null) {
                   //若获取的该对象的父树形对象为空,那么自己还是父对象,直接把自己放入初始化的树形列表之中
                   questionCategoryTreeDto1s.add(currentCategoryDto);
                   continue;
               }

               //父对象不为空了,现在一级栏目是父对象,现在看是否有二级栏目
                if(parentCategory.getChildren() == null) {
                    //二级栏目列表为空
                    //初始化二级列表
                    List<QuestionCategoryTreeDto1> children = new ArrayList<>();
                    children.add(currentCategoryDto);
                    parentCategory.setChildren(children);
                } else {
                    //二级栏目列表不为空,直接把当前的对象添加进去作为二级栏目
                    parentCategory.getChildren().add(currentCategoryDto);
                }

            }

        }
        return questionCategoryTreeDto1s;
    }

}

题库管理

新增题库

判断参数,然后判断题库名称是否已经存在,然后创建对象,赋值分类id、题库名称、题库状态为1

/**
     * 新增题库
     * boolean addQuestionDb(QuestionDbVo questionDbVo);
     * @param questionDbVo
     * @return
     */
    @Override
    public boolean addQuestionDb(QuestionDbVo questionDbVo) {
        if(questionDbVo == null) {
            throw new BerryException("参数不能为空");
        }
        if(questionDbVo.getCategoryId() == null) {
            throw new BerryException("分类id不能我空!");
        }
        if(StrUtil.isBlank(questionDbVo.getDbName())) {
            throw new BerryException("请输入题库名称");
        }
        QueryWrapper<CourseQuestionDb> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestionDb::getDbName,questionDbVo.getDbName());
        if(count(queryWrapper) > 0) {
            throw new BerryException("该题库名称已经存在");
        }
        CourseQuestionDb courseQuestionDb = new CourseQuestionDb();
        courseQuestionDb.setCategoryId(questionDbVo.getCategoryId());
        courseQuestionDb.setDbName(questionDbVo.getDbName());
        courseQuestionDb.setDbStatus(1);
        return save(courseQuestionDb);
    }
}

删除题库

removeById(id);

/**
     * 删除题库
     * boolean deleteQuestionDb(Long id) throws BerryException;
     * @param id
     * @return
     * @throws BerryException
     */
    @Override
    public boolean deleteQuestionDb(Long id) throws BerryException {
        if(id == null) {
            throw new BerryException("id不能为空");
        }
        return removeById(id);
    }

题库详情

/**
     * 查询题库详情
     * CourseQuestionDb queryQuestionDbInfo(Long id) throws BerryException;
     * @param id
     * @return
     * @throws BerryException
     */
    @Override
    public CourseQuestionDb queryQuestionDbInfo(Long id) throws BerryException {
        if(id == null) {
            throw new BerryException("id不能为空");
        }
        return getById(id);
    }

题库列表

需要连带着查出来题库分类名称,我们先根据条件查出来题库列表

循环题库列表,在循环中根据分类id查询到具体的题库分类对象,然后根据对象获得分类名称,复赋值给题库对象

/**
     * 查询题库列表
     * * 题库列表(不分页,可以根据题库分类id,或者题库名称查询)
     *  * 在查询列表的时候需要把题库分类名称查出来(在循环中赋值)
     * @param questionDbVo
     * @return
     */
    @Override
    public List<CourseQuestionDb> getDbList(QuestionDbVo questionDbVo) {
        if(questionDbVo == null) {
            throw new BerryException("参数列表不为空");
        }
        QueryWrapper<CourseQuestionDb> queryWrapper = new QueryWrapper<>();
        if(!StrUtil.isEmpty(questionDbVo.getDbName())) {
            queryWrapper.lambda().like(CourseQuestionDb::getDbName,questionDbVo.getDbName());
        }
        if(questionDbVo.getCategoryId() != null) {
            queryWrapper.lambda().eq(CourseQuestionDb::getCategoryId,questionDbVo.getCategoryId());
        }
        List<CourseQuestionDb> list = list(queryWrapper);
        list.forEach(obj -> {
            //想要获取对应分类的名称,得先获取到题库分类对象
            CourseQuestionCategory questionCategory = questionCategoryService.getById(obj.getCategoryId());
            obj.setCategoryName(questionCategory.getQuestionCategoryName());
        });
        return list;
    }

更新题库信息

/**
     * 修改题库
     *  boolean updateQuestionDbInfo(CourseQuestionDb courseQuestionDb) throws BerryException;
     * @param courseQuestionDb
     * @return
     * @throws BerryException
     */
    @Override
    public boolean updateQuestionDbInfo(CourseQuestionDb courseQuestionDb) throws BerryException {
        if(courseQuestionDb.getDbId() == null) {
            throw new BerryException("题库id不存在");
        }
        //根据id查一下该题库是否存在
        CourseQuestionDb questionDb = getById(courseQuestionDb.getDbId());
        if(questionDb == null) {
            throw new BerryException("该题库不存在");
        }
        QueryWrapper<CourseQuestionDb> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestionDb::getDbName,courseQuestionDb.getDbName());
        queryWrapper.lambda().ne(CourseQuestionDb::getDbId,courseQuestionDb.getDbId());
        if(count(queryWrapper) > 0) {
            throw new BerryException("该题库名称已经存在");
        }
        return updateById(courseQuestionDb);
    }

更新题库状态

就是判断参数,然后创建题库对象,传题库id和状态两个参数之后,调用修改方法就可

 /**
     * 更改题库状态
     * boolean updateQuestionDbStatus(Long dbId, Integer status);
     * @param dbId
     * @param status
     * @return
     */
    @Override
    public boolean updateQuestionDbStatus(Long dbId, Integer status) {
        if(dbId == null) {
            throw new BerryException("请输入题库id !");
        }
        if(status == null) {
            throw new BerryException("请输入题库状态");
        }
        CourseQuestionDb courseQuestionDb = new CourseQuestionDb();
        courseQuestionDb.setDbStatus(status);
        courseQuestionDb.setDbId(dbId);
        return updateById(courseQuestionDb);
    }

题库试题管理

题库添加试题

/**
     * 题库添加试题
     * @param questionReqVO
     */
    void addQuestion(QuestionReqVO questionReqVO);

1先判断参数

2判断该题目是否已将在该题库

3初始化选项列表,因为我们在新增问题的时候会顺带把选项添加到选项列表

4如果是判断题,创建两个选项对象,分别赋值对和错对应的选项名和选项值,然后把赋值后对象添加到初始化的选项列表

5如果是选择题,选项列表从参数获得,optionList = questionReqVO.getOptionList();

6双层循环该参数中的选项列表,就可以判断选项中是否有选项值为空,是否有重复的选项值

7创建问题对象,从参数中对对象赋值,保存问题对象

8批量保存选项,先循环选项列表,把每个每个选项对象都复制上题目id,调用saveOrUpdateBatch

9改变题库题目数量

/**
     * 题库添加试题
     * @param questionReqVO
     */
    void addQuestion(QuestionReqVO questionReqVO);
/**
     * 题库添加试题
     * @param questionReqVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addQuestion(QuestionReqVO questionReqVO) {
        if(questionReqVO == null) {
            throw new BerryException("参数错误");
        }
        if(StrUtil.isEmpty(questionReqVO.getQuestionName())) {
            throw new BerryException("题干不能为空");
        }
        if(StrUtil.isEmpty(questionReqVO.getQuestionAnswerRight()) && questionReqVO.getQuestionType() != 5) {
            throw new BerryException("正确答案不能为空");
        }
        if(questionReqVO.getQuestionType() == null || questionReqVO.getQuestionType() == 0) {
            throw new BerryException("题目类型不能为空");
        }
        if ((questionReqVO.getQuestionType() != 3 && questionReqVO.getQuestionType() != 4 && questionReqVO.getQuestionType() != 5) && (questionReqVO.getOptionList() == null || questionReqVO.getOptionList().size() == 0)) {
            throw new BerryException("选项不能为空");
        }
        if(questionReqVO.getQuestionDbId() == null || questionReqVO.getQuestionDbId() == 0) {
            throw new BerryException("题库id不能为空");
        }
        //判断该题目是否已经存在,需要指定题库
        QueryWrapper<CourseQuestions> questionsQueryWrapper = new QueryWrapper<>();
        questionsQueryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,questionReqVO.getQuestionId());
        questionsQueryWrapper.lambda().eq(CourseQuestions::getQuestionName,questionReqVO.getQuestionName());
        int count = count(questionsQueryWrapper);
        if(count > 0) {
            throw new BerryException("该题目已经存在");
        }
        //判断选项,类型3代表判断题
        //初始化选项列表,为了向列表中封装数据
        List<CourseQuestionsOption> optionList = new ArrayList<>();
        if(questionReqVO.getQuestionType() == 3) {
            //创建选项对象,封装属性,那对象添加到选项列表中,下面的操作相当于会添加两条记录
            CourseQuestionsOption option = new CourseQuestionsOption();
            option.setOptionName("A");
            option.setOptionValue("对");
            optionList.add(option);
            CourseQuestionsOption optionB = new CourseQuestionsOption();
            option.setOptionName("B");
            option.setOptionValue("错");
            optionList.add(optionB);
        } else {
            optionList = questionReqVO.getOptionList();
            for(CourseQuestionsOption option :optionList) {
                if(StrUtil.isBlank(option.getOptionValue())) {
                    throw new BerryException("问题选项里有选项值为空,请重新配置并提交");
                }
                //判断选项值是否重复
                String optionValue = option.getOptionValue().trim();
                for (CourseQuestionsOption nextOption:optionList) {
                    if(StrUtil.isBlank(nextOption.getOptionValue())) {
                        throw new BerryException("问题选项里有选项值为空,请重新配置并提交");
                    }
                    String nextOptionValue = nextOption.getOptionValue().trim();
                    if(option != nextOption) {
                        if(optionValue.equals(nextOptionValue)) {
                            throw new BerryException("问题选项中有重复选项值,请重新输入");
                        }
                    }
                }
            }

        }
        CourseQuestions courseQuestions = new CourseQuestions();
        BeanUtils.copyProperties(questionReqVO,courseQuestions);
        save(courseQuestions);
        //批量保存选项
        if(optionList != null) {
            for(CourseQuestionsOption option:optionList) {
                option.setQuestionId(courseQuestions.getId());
            }
            if(optionList.size() > 0) {
                courseQuestionsOptionService.saveOrUpdateBatch(optionList);
            }
        }

        //最后改变题库的问题数量
        updateDbQuestionCount(questionReqVO.getQuestionDbId(),1);
    }

题库查询题目列表(分页查询)

参数

返回参数
public class CourseQuestionPageResVo {

    @ApiModelProperty("分页数据")
    public PageResVO pageResVo;

    @ApiModelProperty("题库题目")
    public List<CourseQuestions> courseQuestionsList;

}

@ApiModel(value = "题库题目请求VO")
@Data
public class CourseQuestionPageReqVo {

    @ApiModelProperty(value = "题库ID(非必传)")
    private Long questionDbId;

    @ApiModelProperty(value = "题目(非必传)")
    private String questionName;

    @ApiModelProperty(value = "分页请求参数")
    private PageReqVO pageReqVO;

    @ApiModelProperty(value = "题型列表")
    private List<Integer> questionTypes;
/**
     * 题库查询题目列表
     * @param courseQuestionPageReqVo
     */
    CourseQuestionPageResVo listQuestion(CourseQuestionPageReqVo courseQuestionPageReqVo);

1判断参数和分页请求参数

2使用PageHelper.startPage完成分页,参数传 的是第几页和一页几条数据

3查询,参数:题库id,题干名称,题目类型()查询结果会生成一个列表

4创建PageInfo对象,把查询出的列表封装到里面

5循环查询到的列表,根据题目id查询选项列表,把查询到的选项列表赋值给题目

6创建返回对象,赋值分页返回参数和题目列表,最后返回返回对象

/**
 * 题库查询题目列表(分页查询)
 * @param courseQuestionPageReqVo:private Long paperId;private PageReqVO pageReqVO;
 CourseQuestionPageResVo:分页参数,题目列表public List<CourseQuestions> courseQuestionsList;
 * @return
 */
@Override
public CourseQuestionPageResVo listQuestion(CourseQuestionPageReqVo courseQuestionPageReqVo) {
    if(courseQuestionPageReqVo == null) {
        courseQuestionPageReqVo = new CourseQuestionPageReqVo();
    }
    if(courseQuestionPageReqVo.getPageReqVO() == null) {
        courseQuestionPageReqVo.setPageReqVO(new PageReqVO());
    }
    PageHelper.startPage(courseQuestionPageReqVo.getPageReqVO().getCurrent(),courseQuestionPageReqVo.getPageReqVO().getPageSize());
    QueryWrapper<CourseQuestions> questionsQueryWrapper = new QueryWrapper<>();
    //题库id是最主要的查询条件
    if(courseQuestionPageReqVo.getQuestionDbId() != null) {
        questionsQueryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,courseQuestionPageReqVo.getQuestionDbId());
    }
    if(StrUtil.isNotBlank(courseQuestionPageReqVo.getQuestionName())) {
        questionsQueryWrapper.lambda().like(CourseQuestions::getQuestionName,courseQuestionPageReqVo.getQuestionName());
    }
    if(CollUtil.isNotEmpty(courseQuestionPageReqVo.getQuestionTypes())){
        questionsQueryWrapper.lambda().in(CourseQuestions::getQuestionType, courseQuestionPageReqVo.getQuestionTypes());
    }
    List<CourseQuestions> courseQuestionsList = list(questionsQueryWrapper);
    PageInfo<CourseQuestions> pageInfo = new PageInfo<>(courseQuestionsList);
    CourseQuestionPageResVo courseQuestionPageResVo = new CourseQuestionPageResVo();
    //需要把查到的问题列表附带上选项,需要使用循环
    pageInfo.getList().forEach(item-> {
        item.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(item.getId()));
    });
    courseQuestionPageResVo.setCourseQuestionsList(pageInfo.getList());
    PageResVO pageResVO = new PageResVO();
    pageResVO.setCurrent(pageInfo.getPageNum());
    pageResVO.setPageSize(pageInfo.getPageSize());
    pageResVO.setTotal(pageInfo.getTotal());
    courseQuestionPageResVo.setPageResVo(pageResVO);
    return courseQuestionPageResVo;
}

分页查询试卷所选题库中尚未使用的试题列表

请求参数

@ApiModel(value = "试题添加题库剩余题目请求VO")
@Data
public class ExamPaperOtherQuestionPageReqVo {

    @ApiModelProperty(value = "paperId")
    private Long paperId;

    @ApiModelProperty(value = "分页请求参数")
    private PageReqVO pageReqVO;
}

返回参数
public class CourseQuestionPageResVo {

    @ApiModelProperty("分页数据")
    public PageResVO pageResVo;

    @ApiModelProperty("题库题目")
    public List<CourseQuestions> courseQuestionsList;

}
/**
     * 查询试卷所选题库中尚未使用的试题列表
     * @param courseQuestionPageReqVo
     */
    CourseQuestionPageResVo listQuestionDbOtherQuestions(ExamPaperOtherQuestionPageReqVo courseQuestionPageReqVo);

1开启分页条件,创建queryWrapper查询

2我们用试卷id作为参数,在试卷问题映射表中查询映射列表,循环映射列表就可以拿到对应的试题id列表

3查询条件就是在题库中查询,指定题库id,试题id不在2查询的试题id列表里面

4查询到的列表用pageInfo封装,然后创建返回对象,赋值分页参数和试题列表,最后 返回返回对象

/**
 * 查询试卷所选题库中尚未使用的试题列表
 * 查询条件就是题库id 和 问题id不在现在已将使用过的问题列表中
 * @param examPaperOtherQuestionPageReqVo
 */
@Override
public CourseQuestionPageResVo listQuestionDbOtherQuestions(ExamPaperOtherQuestionPageReqVo examPaperOtherQuestionPageReqVo) {
    PageHelper.startPage(examPaperOtherQuestionPageReqVo.getPageReqVO().getCurrent(),examPaperOtherQuestionPageReqVo.getPageReqVO().getPageSize());
    QueryWrapper<CourseQuestions> queryWrapper = new QueryWrapper<>();
    ExamPaper examPaper = examPaperService.getById(examPaperOtherQuestionPageReqVo.getPaperId());
    if(examPaper == null) {
        return null;
    }
    if(examPaper.getQuestionDbId() != null) {
        queryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,examPaper.getQuestionDbId());
    }
    //从试卷问题映射表中拿到已有的问题id列表
    List<ExamPaperQuestionMap> examPaperQuestionMaps = examPaperQuestionMapService.paperQuestionList(examPaper.getId());
    if(CollUtil.isNotEmpty(examPaperQuestionMaps)) {
        List<Long> hasAddedQuestions = examPaperQuestionMaps.stream().map(obj -> {
            return obj.getQuestionId();
        }).collect(Collectors.toList());
        queryWrapper.lambda().notIn(CourseQuestions::getId,hasAddedQuestions);
    }
    List<CourseQuestions> courseQuestionsList = list(queryWrapper);
    PageInfo<CourseQuestions> pageInfo = new PageInfo<>(courseQuestionsList);
    CourseQuestionPageResVo courseQuestionPageResVo = new CourseQuestionPageResVo();
    courseQuestionPageResVo.setCourseQuestionsList(pageInfo.getList());
    PageResVO pageResVO = new PageResVO();
    pageResVO.setCurrent(pageInfo.getPageNum());
    pageResVO.setPageSize(pageInfo.getPageSize());
    pageResVO.setTotal(pageInfo.getTotal());
    courseQuestionPageResVo.setPageResVo(pageResVO);
    return courseQuestionPageResVo;

}

查询试卷下所有题目及选项,按照已有顺序排序或者随机排序

参数

@ApiModel("试卷题目Dto")
@Data
public class ExamPaperQuestionDto {

    @ApiModelProperty(value = "试卷题目映射表Id")
    private Long id;

    @ApiModelProperty(value = "问题Id")
    private Long questionId;

    @ApiModelProperty(value = "题干内容")
    private String questionName;

    @ApiModelProperty(value = "题库ID")
    private Long questionDbId;

    @ApiModelProperty(value = "题目类型 1 单选题 2 多选题 3 判断题 ")
    private Integer questionType;

    @ApiModelProperty(value = "是否为关键知识点 ")
    private Integer isCrucial;

    @ApiModelProperty(value = "答案解析")
    private String questionAnalization;


    @ApiModelProperty(value = "难度 1 简单 2 一般 3 略难 4 非常难")
    private Integer difficultLevel;

    @ApiModelProperty(value = "分值")
    private Integer score;

    @ApiModelProperty(value = "题目选项")
    private List<CourseQuestionsOption> optionList;
/**
     * 查询试卷下所有题目及选项
     * @param paperId
     * @return
     */
    List<ExamPaperQuestionDto> listPaperQuestions(Long paperId);

调用试卷问题映射表中的方法就能的得到我们想要的列表了,重点是我们想要的两种排序方式

如果选项默认排序,就能直接循环列表,赋值一下选项列表就可以

如果是随机排序,就调用随机工具类ListObjectRandomUtil.randomHandler

/**
 * 查询试卷下所有题目及选项
 * 按照已有顺序排序或者随机排序
 * 我们现在查询的返回是List<> 若参数为空,可以先返回ListUtil.empty();
 * @param paperId
 * @return
 */
@Override
public List<ExamPaperQuestionDto> listPaperQuestions(Long paperId) {
    if(paperId == null) {
        return ListUtil.empty();
    }
    ExamPaper examPaper = examPaperService.getById(paperId);
    if(examPaper == null) {
        return ListUtil.empty();
    }
    List<ExamPaperQuestionDto> examPaperQuestionDtos = examPaperQuestionMapService.listPaperQuestions(paperId);
    if(CollUtil.isEmpty(examPaperQuestionDtos)) {
        return ListUtil.empty();
    }
    /**
     * 未设置或者0 为 默认,按照已有顺序排序
     * 1 随机排序
     */
    boolean questionOptionDefaultSort = (examPaper.getQuestionOptionSortWay() == null || examPaper.getQuestionOptionSortWay() == 0) ? true : false;
    examPaperQuestionDtos.stream().forEach(item-> {
        //若为真,默认排序
        if(questionOptionDefaultSort) {
            item.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(item.getQuestionId()));
        } else {
            item.setOptionList(ListObjectRandomUtil.randomHandler(courseQuestionsOptionService.getOptionsByQuestionId(item.getQuestionId())));
        }
    });
    return examPaperQuestionDtos;
}

把列表随机展示的工具类

就是按照列表长度进行循环,然后生成[0,listSize)之间的随机数,若i和随机数不相等,就按照二者为索引交换位置

 public static List randomHandler1(List list) {
        if(CollUtil.isNotEmpty(list)) {
            Random random = new Random();
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                //生成的数在[0,listSize)之间
                int randomIndex = random.nextInt(listSize);
                if(i != randomIndex) {
                    //将列表中索引i对应的数据和随机索引对调位置
                    Object temp = list.get(i);
                    list.set(i,list.get(randomIndex));
                    list.set(randomIndex,temp);
                }
            }
        }
        return list;
    }

查询试卷下的所有题目和选项

查询试题列表(不带选项,不分页)

/**
     * 查询试题
     * @param questionDbId
     */
    List<CourseQuestions> listQuestionByDbId(Long questionDbId, boolean isCrucial);

1创建查询,查询条件题库id

2把查询到的试题列表循环,然后调用获得选项列表的方法给每个试题赋值选项

3最后返回试题列表

/**
     * 查询试题列表(带选项,不分页)
     * @param questionDbId
     * @param isCrucial
     * @return
     */
    @Override
    public List<CourseQuestions> listQuestionByDbId(Long questionDbId, boolean isCrucial) {
        QueryWrapper<CourseQuestions> questionsQueryWrapper = new QueryWrapper<>();
        if(questionDbId != null) {
            questionsQueryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,questionDbId);
            if(isCrucial) {
                questionsQueryWrapper.lambda().eq(CourseQuestions::getIsCrucial,1);
            } else {
                questionsQueryWrapper.lambda().eq(CourseQuestions::getIsCrucial,0);
            }
        }
        List<CourseQuestions> list = list(questionsQueryWrapper);
        list.forEach(item -> {
            item.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(item.getId()));
        });
        return list;
    }

查询单个问题的详情

/**
     * 查看问题详细信息
     * @param questionId
     * @return
     */
    CourseQuestions questionDetail(Long questionId);


根据试题id拿到试题对象,然后查询选项列表给试题赋值,最后返回试题对象

/**
     * 查看单个问题详细信息
     *就是问题带选项
     * @param questionId
     * @return
     */
    @Override
    public CourseQuestions questionDetail(Long questionId) {
        CourseQuestions courseQuestions = getById(questionId);
        if(courseQuestions != null) {
            courseQuestions.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(questionId));
        }
        return courseQuestions;
    }

更新试题

 /**
     * 更新试题
     * @param questionReqVO
     */
    void updateQuestion(QuestionReqVO questionReqVO);

1 判断 参数,判断修改的时候题干不要重复

2对选项判断,如果是判断题,初始化选项列表,创建两个选择对象,把对和错分别对应的选项名和选项值赋值后,选项对象添加到选项列表,若果不是判断题,选项列表就从前端拿到,双层循环选项列表,判断选项值不能为空,选项值不能重复

3更新操作,创建问题对象,复制属性

4对选项列表的更新,典型的对列表的多个数据进行更新操作(

先查询库中的选项列表数据

初始化新的选项列表,为了存放新的数据,初始化id列表,为了删除数据做准备

循环参数中的选项列表,把数据放入初始化的新的选项列表

找出需要删除的选项id,外城循环库中原始列表数据,定义一个初始值为0,内层循环参数列表数据,如果内城的选项id不为空(说明它是在原有数据上修改)而且 外层数据id和内层id一样,初始值自增,如果这个初始值还是0,说明原来库中的选项已经没用,把他的id添加到初始化的要删除的选项列表

添加或修改新的,删除没用的选项saveOrUpdateBatch(optionListNew);  .removeByIds(optionListDel);

5更新问题

 /**
     * 更新试题
     * @param questionReqVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuestion(QuestionReqVO questionReqVO) {
        //先判断参数
        if(questionReqVO == null) {
            throw new BerryException("参数不能为空");
        }
        if (questionReqVO.getQuestionDbId() == null) {
            throw new BerryException("题库不能为空");
        }

        if (StrUtil.isBlank(questionReqVO.getQuestionName())) {
            throw new BerryException("题干不能为空");
        }

        if (StrUtil.isBlank(questionReqVO.getQuestionAnswerRight()) && questionReqVO.getQuestionType() != 5) {
            throw new BerryException("正确答案不能为空");
        }

        if (questionReqVO.getQuestionType() == null) {
            throw new BerryException("题目类型不能为空");
        }

        if ((questionReqVO.getQuestionType() != 3 && questionReqVO.getQuestionType() != 4 && questionReqVO.getQuestionType() != 5) && (questionReqVO.getOptionList() == null || questionReqVO.getOptionList().size() == 0)) {
            throw new BerryException("选项不能为空");
        }
        //判断题干不能重复
        QueryWrapper<CourseQuestions> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,questionReqVO.getQuestionDbId());
        queryWrapper.lambda().eq(CourseQuestions::getQuestionName,questionReqVO.getQuestionName());
        queryWrapper.lambda().ne(CourseQuestions::getId,questionReqVO.getQuestionId());
        List<CourseQuestions> list = list(queryWrapper);
        if(list.size() > 0) {
            throw new BerryException("该题目已经存在,请重新设置");
        }

        //初始化选项列表,为了封装好数据之后批量添加
        List<CourseQuestionsOption> optionList = new ArrayList<>();
        if(questionReqVO.getQuestionType() == 3) {
            //如果是判断题的话,向选项列表中封装数据
            CourseQuestionsOption optionA = new CourseQuestionsOption();
            optionA.setOptionName("A");
            optionA.setOptionValue("对");
            CourseQuestionsOption optionB = new CourseQuestionsOption();
            optionB.setOptionName("B");
            optionB.setOptionValue("错");
            optionList.add(optionA);
            optionList.add(optionB);
        } else {
            //如果是选择题需要对选项做判断
            optionList = questionReqVO.getOptionList();
            for (CourseQuestionsOption option:optionList) {
                if(StrUtil.isEmpty(option.getOptionValue())) {
                    throw new BerryException("选项中有选项值为空,请重新设置")
                }
                String optionValue = option.getOptionValue().trim();
                for (CourseQuestionsOption optionNext:optionList) {
                    if(StrUtil.isEmpty(optionNext.getOptionValue())) {
                        throw new BerryException("选项中有选项值为空。请重新配置");
                    }
                    String nextOptionValue = optionNext.getOptionValue().trim();
                    if(option != optionNext) {
                        if(optionValue == nextOptionValue) {
                            throw new BerryException("选项中有重复的选项值,请重新输入");
                        }
                    }
                }
            }
        }

        //前面都是参数的判断,后面是具体的操作
        CourseQuestions courseQuestions = new CourseQuestions();
        BeanUtils.copyProperties(questionReqVO,courseQuestions);
        courseQuestions.setId(questionReqVO.getQuestionId());

        //下面的操作是对列表的多个数据的更新操作

        //1 先从库中查询之前对应的列表
        List<CourseQuestionsOption> oldOptionList = courseQuestionsOptionService.getOptionsByQuestionId(questionReqVO.getQuestionId());
        //2初始化一个新的选项列表为了存放新数据,初始化一个id列表,为了删除旧数据
        List<CourseQuestionsOption> optionListNew = new ArrayList<>();
        List<Long> optionListDel = new ArrayList<>();
        //3循环参数给的选项列表数据,把它放到新的列表之中
        for (CourseQuestionsOption option : optionList) {
            option.setQuestionId(questionReqVO.getQuestionId());
            optionListNew.add(option);
        }

        //4 找出需要删除的选项记录
        List<CourseQuestionsOption> finalOptionList = optionList;
        //外层循环库中原始列表数据,定义个初始值为0,内层循环参数中的列表数据,若参数列表中的选项id不为空且和原始列表选项id一样,初始值自增,若初始值还是0,说明库中的这个选项在页面被删掉了,把它放入到要删除的列表之中
        oldOptionList.forEach(item -> {
            int haveCount = 0;
            for (CourseQuestionsOption courseQuestionsOption:finalOptionList) {
                if(courseQuestionsOption.getOptionId() != null && courseQuestionsOption.getOptionId().equals(item.getOptionId())) {
                    haveCount ++;
                }
            }
            if(haveCount == 0) {
                optionListDel.add(item.getOptionId());
            }
        });
        if(optionListNew.size() > 0) {
            courseQuestionsOptionService.saveOrUpdateBatch(optionListNew);
        }
        if(optionListDel.size() > 0) {
            courseQuestionsOptionService.removeByIds(optionListDel);
        }
        //最后更新问题
        updateById(courseQuestions);
    }

删除试题

 /**
     * 删除试题
     * @param questionId
     */
    void deleteQuestion(Long questionId);

需要删除问题,更新题库问题数量。用map删除试卷和问题的映射关系

/**
 * 删除试题
 * @param questionId
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteQuestion(Long questionId) {
    //先看试题是否还存在
    CourseQuestions questions = getById(questionId);
    if(questions == null) {
        throw new BerryException("题目已经删除");
    }
    removeById(questionId);
    //更新题目数量
    updateDbQuestionCount(questions.getQuestionDbId(),-1);
    Map<String, Object> map = new HashMap<>();
    map.put("question_id",questionId);
    List<ExamPaperQuestionMap> list = examPaperQuestionMapService.listByMap(map);
    if(list != null && list.size() > 0) {
        throw new BerryException("题目关联试卷,抢先删除试卷关联");
    } else {
        courseQuestionsOptionService.removeByMap(map);
    }
}

题库导入题目

@SysLogAnnotation("题库导入题目")
    @ApiOperation("题库导入题目")
    @PostMapping("/batchImport/{questionDbId}")
    public BaseResponse importQuestion(@PathVariable Long questionDbId, @RequestParam("file") MultipartFile uploadFile) {
        try {
            List<CourseQuestionExcelModel> list = EasyExcelFactory.read(new BufferedInputStream(uploadFile.getInputStream())).head(CourseQuestionExcelModel.class).sheet(0).headRowNumber(1).doReadSync();
            courseQuestionsService.importQuestion(questionDbId, list);
            return BaseResponse.success();
        } catch (Exception ex) {
            ex.printStackTrace();
            log.info("exception:{}", ex.getMessage());
            return BaseResponse.fail(ex.getMessage());
        }
    }
/**
     * 题库导入题目
     * @param questionDbId
     * @param importList
     * @return
     */
    List<Long> importQuestion(Long questionDbId, List<CourseQuestionExcelModel> importList);

1参数是题库id,列表数据,根据题库id获得题库,看题库是否还存在 ,循环列表,如列表中有题干为空,移除该题目

2判断导入的题目和库中的题目是否有重复,先通过循环参数列表,抽取出来题干列表,我们拿题干列表做为参数,对实体进行in查询,若能拿到试题列表,这些试题列表中的数据就是库中已经存在,循环我们拿到的试题列表,抽取题干属性,把导入的课表中有该题干的都移除importList.removeIf(obj -> obj.getQuestionName().equals(questionName));

3正式的导入操作,循环我们的导入列表,(

//创建QuestionReqVO对象,它是新增问题的参数,下面需要封装属性,先赋值已有的题库id,从导入数据中可以知道题目类型,赋值给vo对象

//也需要给选项表赋值,先初始化选项列表,若不是判断题,初始化一个选项数组

String[] optionNameArray = "a,b,c,d,e,f,g,h,i,j,k".toUpperCase().split(",");,该数组提供选项名,循环该数组,根据选项名获取选项值,若选项值不为空,创建选项对象,把选项名和选项值都赋值进去,然后选项添加到选项列表

//如果是多选题,需要拼接正确选项:创建StringBuilder对象,用于拼接,如果导入对象的正确答案不包括(","),不包括(", "),那正确答案按照空格分割,生成数组,循环数组,把数组中的空格去掉,然后把正确答案和,拼接

//如果包含(",");正确答案按照(",")分割,循环数组,进行正确答案的拼接

//拼接之后把最后一个逗号去掉,

String nextAnswer = finalAnswer.substring(0, finalAnswer.length() - 1); 然后赋值正确答案

//如果是判断题,给选项列表赋值,设定正确答案,不是判断题的话,循环选项列表,判断选项

//把选项列表赋值给vo对象,给vo赋值正确答案,答案解析,分数,然后作为参数调用添加问题方法

最后更新问题数量

  /**
     * 题库导入题目
     * 数据导入
     * @param questionDbId
     * @param importList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> importQuestion(Long questionDbId, List<CourseQuestionExcelModel> importList) {
        CourseQuestionDb db = courseQuestionDbService.getById(questionDbId);
        if(db == null) {
            throw new BerryException("题库不存在");
        }
        //初始化一个id列表
        List<Long> idList = new ArrayList<>();
        //判断 导入列表若有空的题干,去除
        importList.forEach(obj -> {
            if(obj.getQuestionName().trim().equals("")) {
                importList.remove(obj);
            }
        });

        //获得题干列表
        List<String> questionTitleList = importList.stream().map(obj ->
                obj.getQuestionName()
        ).collect(Collectors.toList());

        //判断导入的题目和库中的题目重复需要移除,我们拿导入的题干列表作为参数,查询数据库看是否有一样的题干,若有的话直接把导入的列表中重复的题移除
        QueryWrapper<CourseQuestions> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(true,CourseQuestions::getQuestionName,questionTitleList);
        List<CourseQuestions> courseQuestionsList = list(queryWrapper);
        for (CourseQuestions courseQuestions : courseQuestionsList) {
            String questionName = courseQuestions.getQuestionName();
            importList.removeIf(obj -> obj.getQuestionName().equals(questionName));
            //这些是和导入的题干有重的问题id
            idList.add(courseQuestions.getId());
        }
        //正式的导入操作
        for(CourseQuestionExcelModel questionModel : importList) {
            //创建QuestionReqVO对象,它是新增问题的参数,下面需要封装属性
            QuestionReqVO questionReqVO = new QuestionReqVO();
            questionReqVO.setQuestionDbId(questionDbId);
            //也需要给选项表赋值,先初始化选项列表
            List<CourseQuestionsOption> optionList = new ArrayList<>();
            questionReqVO.setQuestionType(COURSE_QUESITION_TYPE.getTypeByName(questionModel.getQuestionType()));
            String[] optionNameArray = "a,b,c,d,e,f,g,h,i,j,k".toUpperCase().split(",");
            if(questionReqVO.getQuestionType() != 3) {
                //题目不是判断题
                for (String optionName : optionNameArray) {
                    String optionValue = questionModel.getOptionValue(optionName);
                    if(optionValue != null && optionValue.length() > 0) {
                        CourseQuestionsOption option = new CourseQuestionsOption();
                        option.setOptionName(optionName);
                        option.setOptionValue(optionValue);
                        optionList.add(option);
                    }
                }
            }
            //多选题
            if(questionReqVO.getQuestionType().equals(2)) {
                StringBuilder finalAnswer = new StringBuilder();
                if(!questionModel.getQuestionAnswerRight().contains(",")) {
                    if(!questionModel.getQuestionAnswerRight().contains(", ")) {
                        String[] answerArray = questionModel.getQuestionAnswerRight().split("");
                        for(String answerOption: answerArray) {
                            if(!answerOption.trim().equals("")) {
                                finalAnswer.append(answerOption).append(",");
                            }
                        }
                    } else {
                        String[] answerArray = questionModel.getQuestionAnswerRight().split(",");
                        for (String answerOption : answerArray) {
                            if (!answerOption.trim().equals("")) {
                                finalAnswer.append(answerOption).append(",");
                            }
                        }
                    }
                    //就是把正确答案去掉最后一个逗号
                    if(finalAnswer.length() > 0) {
                        String nextAnswer = finalAnswer.substring(0, finalAnswer.length() - 1);
                        questionModel.setQuestionAnswerRight(nextAnswer);
                    }
                }
            }

            //判断题
            if(questionReqVO.getQuestionType() == 3) {
                String answerValue = "";
                if(optionList.size() == 0) {
                    CourseQuestionsOption option = new CourseQuestionsOption();
                    option.setOptionName("A");
                    option.setOptionValue("对");
                    optionList.add(option);
                    CourseQuestionsOption optionB = new CourseQuestionsOption();
                    optionB.setOptionName("B");
                    optionB.setOptionValue("错");
                    optionList.add(optionB);
                }
                //设定正确答案呢
                if (questionModel.getQuestionAnswerRight().equals("对")
                        || questionModel.getQuestionAnswerRight().equals("1")
                        || questionModel.getQuestionAnswerRight().equals("A")) {
                    answerValue = "A";
                } else {
                    answerValue = "B";
                }
                questionModel.setQuestionAnswerRight(answerValue);
            } else {
                for(CourseQuestionsOption option:optionList) {
                    if(StrUtil.isEmpty(option.getOptionValue())) {
                        throw new BerryException("问题选项中有选项值为空,请重新配置")
                    }
                    String optionValue = option.getOptionValue().trim();
                    for (CourseQuestionsOption nextOption : optionList) {
                        if(StrUtil.isEmpty(nextOption.getOptionValue())) {
                            throw new BerryException("问题选项中有选项值为空,请重新配置并提交");
                        }
                        String nextOptionValue = nextOption.getOptionValue().trim();
                        if(option != nextOption) {
                            if(optionValue.equals(nextOptionValue)) {
                                throw new BerryException("选项中有选项值重复,请重新配置并且提交");
                            }
                        }

                    }
                }
            }
            if(optionList.size() > 0) {
                questionReqVO.setOptionList(optionList);
            }
            questionReqVO.setQuestionAnswerRight(questionModel.getQuestionAnswerRight());
            questionReqVO.setQuestionAnalization(questionModel.getQuestionAnalysis());
            questionReqVO.setScore(questionModel.getScore());
            addQuestion(questionReqVO);
            idList.add(questionReqVO.getQuestionId());
        }
        updateDbQuestionCount(questionDbId,importList.size());
        return idList;
    }

题库导出题目

@SysLogAnnotation("题库题目导出")
    @ApiOperation("题库题目导出")
    @GetMapping("/exportQuestion/{bookId}")
    public void exportQuestion(HttpServletResponse response,@PathVariable Long bookId) {
        try {
            List<CourseQuestionExcelModel> resultList = courseQuestionsService.exportData(bookId);
            ExcelUtil.writeExcel(response,resultList,"QuestionDb","课程题库模板",CourseQuestionExcelModel.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

/**
     * 题库题目导出
     * @param questionDbId
     * @return
     */
    List<CourseQuestionExcelModel> exportData(Long questionDbId);

1先根据题库id为条件,查询该题库的所有试题列表

2我们要返回的是ExcelModel列表,所以先初始化ExcelModel列表

3循环试题列表,在循环中创建ExcelModel对象,用来接收相关的属性,

4返回ExcelModel列表

/**
 * 题库题目导出
 * 是根据题库id为条件,查出该题库所有的问题列表,然后把该问题列表转换成对应的ExcelModel列表
 * @param questionDbId
 * @return
 */
@Override
public List<CourseQuestionExcelModel> exportData(Long questionDbId) {
    //1先通过题库id为条件,查询该题库对应的所有问题列表
    QueryWrapper<CourseQuestions> questionsQueryWrapper = new QueryWrapper<>();
    questionsQueryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,questionDbId);
    List<CourseQuestions> voList = list(questionsQueryWrapper);

    //2我们要返回的是ExcelModel列表,所以先初始化ExcelModel列表
    List<CourseQuestionExcelModel> resultList = new ArrayList<>();

    for(CourseQuestions vo : voList) {
        //3 循环问题列表,在循环中创建ExcelModel对象,用来接收相关的属性
        //4属性赋值,把ExcelModel对象加入到ExcelModel列表之中
        CourseQuestionExcelModel excelModel = new CourseQuestionExcelModel();
        List<CourseQuestionsOption> optionList = courseQuestionsOptionService.getOptionsByQuestionId(vo.getId());
        if(optionList.size() > 0) {
            for (CourseQuestionsOption option : optionList) {
                excelModel.setOptionValue(option.getOptionName(),option.getOptionValue());
            }
        }
        excelModel.setQuestionAnswerRight(vo.getQuestionAnswerRight());
        excelModel.setQuestionName(vo.getQuestionName());
        excelModel.setQuestionType(COURSE_QUESITION_TYPE.getNameByType(vo.getQuestionType()));
        resultList.add(excelModel);
    }
    return resultList;
}

随机生成试题列表,指定试题的个数

@SysLogAnnotation("题库随机题目")
    @ApiOperation("题库随机题目")
    @GetMapping("/randomQuestion/{questionDbId}")
    public BaseResponse<  List<CourseQuestions> > getNextQuestion(@PathVariable("questionDbId") Long questionDbId){
        try {
            List<CourseQuestions> randomQuestions = courseQuestionsService.getRandomQuestionByDbId(questionDbId,10);
            return BaseResponse.success(randomQuestions);
        } catch (BerryException e) {
            log.info("exception:{}", e.getMessage());
            return BaseResponse.fail(e.getMessage());
        } catch (Exception e) {
            log.info(" createQuestion  exception:{}", "题库随机题目失败");
            return BaseResponse.fail("题库随机题目失败");
        }

    }

参数是题库id,题目数量

1判断题库是否存在,根据题库Id查询试题列表

2随机有两种情况,一种是库中的试题够用,那么初始化一个接收问题的列表,创建Random对象,按照指定试题数量进行循环,生成随机数的范围为0-list.size()-1,把随机数作为问题id获得问题独享,添加的初始化的问题列表中,然后循环初始化后的列表,天骄选项,最后返回该列表

3另一种情况就是库中题目不够用,就不用随机了,直接用就行

 /**
     * 随机生成下一题
     * 随机生成试题列表,指定试题的个数
     *
     * @param questionDbId
     * @param randomNum
     * @return、
     */
    @Override
    public List<CourseQuestions> getRandomQuestionByDbId(Long questionDbId,int randomNum) {
        //先判断参数,看看题库是否还存在
        if(questionDbId == null) {
            throw new BerryException("题库id不能为空");
        }
        //随机个数不能 < 0
        if(randomNum < 0 ) {
            throw new BerryException("随机个数必须大于0");
        }
        CourseQuestionDb courseQuestionDb = courseQuestionDbService.getById(questionDbId);
        if(courseQuestionDb == null) {
            throw new BerryException("题库不存在");
        }
        //查询该题库中的所有问题列表
        QueryWrapper<CourseQuestions> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,questionDbId);
        List<CourseQuestions> courseQuestionsList = list(queryWrapper);
        if(CollUtil.isNotEmpty(courseQuestionsList)) {
            //随机的时候有两种情况,一个是指定的随机数小于 现有的题目数,也就是现有题目够用,初始化一个接收问题的列表,然后循环,在循环中用随机数作为问题的id,然后获得问题呢对象,把问题添加到初始化的问题列表之中
            if(courseQuestionsList.size() > randomNum) {
                List<CourseQuestions> backSum = new ArrayList<>();
                Random random = new Random();
                for (int i = 0; i < randomNum ; i++) {
                    //随机数的范围为0-list.size()-1
                    int target = random.nextInt(courseQuestionsList.size());
                    CourseQuestions courseQuestions = courseQuestionsList.get(target);
                    courseQuestions.setQuestionAnswerRight(null);
                    courseQuestions.setQuestionAnalization(null);
                    backSum.add(courseQuestions);
                    //删除掉已经被选择的
                    courseQuestionsList.remove(target);
                }
                //给生成的题目赋值选项
                if(backSum.size() > 0) {
                    backSum.forEach(item -> {
                        item.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(item.getId()));
                    });
                }
                return backSum;
            } else {
                //现有题目不够用,就不随了
                courseQuestionsList.forEach(item -> {
                    item.setQuestionAnswerRight(null);
                    item.setQuestionAnalization(null);
                    item.setOptionList(courseQuestionsOptionService.getOptionsByQuestionId(item.getId()));
                });
                return courseQuestionsList;
            }

        } else {
            return ListUtil.empty();
        }

    }

课程题目作答

参数

/**
 * 学生课程试题练习作答测试
 */
@Data
@ApiModel(value = "课程练习学生作答结果VO" ,description = "课程练习学生作答结果VO")
public class StudentQuestionApplyResultVO {

    /**
     * 问题Id
     */
    @ApiModelProperty("问题ID")
    private Long questionId;
    /**
     * 学生作答答案
     */
    @ApiModelProperty("学生答案")
    private String studentAnswer;


    @ApiModelProperty("作答结果 true正确 false错误")
    private Boolean answerResult;

    @ApiModelProperty("问题详情")
    private CourseQuestions courseQuestions;


}
/**
 * 学生课程试题练习作答测试
 */
@Data
@ApiModel(value = "课程练习学生作答VO" ,description = "课程练习学生作答VO")
public class StudentQuestionApplyVO {

    /**
     * 问题Id
     */
    @NotNull(message = "请输入问题ID")
    @ApiModelProperty("问题ID")
    private Long questionId;
    /**
     * 学生作答答案
     */
    @NotNull(message = "请输入问题学生作答")
    @ApiModelProperty("学生答案")
    private String studentAnswer;


}
 @SysLogAnnotation("题库题目作答")
    @ApiOperation("题库题目作答")
    @PostMapping("/questionApply")
    public BaseResponse<StudentQuestionApplyResultVO> questionApply(@Valid @RequestBody StudentQuestionApplyVO studentQuestionApplyVO,BindingResult bindingResult){

        if (bindingResult.hasErrors()) {
            throw new BerryException(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            StudentQuestionApplyResultVO studentQuestionApplyResultVO  = courseQuestionsService.studentQuestionApply(studentQuestionApplyVO);
            return BaseResponse.success(studentQuestionApplyResultVO);
        } catch (BerryException e) {
            log.info("exception:{}", e.getMessage());
            return BaseResponse.fail(e.getMessage());
        } catch (Exception e) {
            log.info(" createQuestion  exception:{}", "题库题目作答失败");
            return BaseResponse.fail("题库题目作答失败");
        }

    }
/**
     * 课程题目作答
     * @param studentQuestionApplyVO
     * @return
     */
    StudentQuestionApplyResultVO studentQuestionApply(StudentQuestionApplyVO studentQuestionApplyVO);
/**
     * 课程题目作答
     * StudentQuestionApplyResultVO:课程练习学生作答结果VO,包括问题id,学生答案,作答结果(true正确 false错误) 问题详情
     *
     * StudentQuestionApplyVO:问题id ,学生答案
     * @param studentQuestionApplyVO
     * @return
     */
    @Override
    public StudentQuestionApplyResultVO studentQuestionApply(StudentQuestionApplyVO studentQuestionApplyVO) {
        if(studentQuestionApplyVO == null) {
            throw new BerryException("请输入作答内容");
        }
        Long questionId = studentQuestionApplyVO.getQuestionId();
        CourseQuestions courseQuestions = getById(questionId);
        if(courseQuestions == null) {
            throw new BerryException("问题不存在");
        }
        //创建StudentQuestionApplyResultVO 对象,用来封装作答情况
        StudentQuestionApplyResultVO studentQuestionApplyResultVO = new StudentQuestionApplyResultVO();
        studentQuestionApplyResultVO.setStudentAnswer(studentQuestionApplyVO.getStudentAnswer());
        studentQuestionApplyResultVO.setQuestionId(studentQuestionApplyVO.getQuestionId());
        //判断是否答对
        if(courseQuestions.getQuestionAnswerRight().equals(studentQuestionApplyVO.getStudentAnswer())) {
            //回答正确
            studentQuestionApplyResultVO.setAnswerResult(true);
        } else {
            studentQuestionApplyResultVO.setAnswerResult(false);
        }
        studentQuestionApplyResultVO.setCourseQuestions(courseQuestions);
        return studentQuestionApplyResultVO;
    }

试卷题目分页列表

@Data
@ApiModel(value = "试卷题目列表请求VO")
public class QuestionPageDataReqVo {

    @ApiModelProperty(value = "分页参数")
    private PageReqVO pageReqVO;

    @ApiModelProperty(value = "试卷ID")
    private Long paperId;

    @ApiModelProperty(value = "题库ID")
    private Long questionDbId;
}


@Data
@ApiModel(value = "试卷题目分页列表Vo")
public class QuestionPageVo {

    @ApiModelProperty(value = "返回分页配置")
    private PageResVO pageResVO;

    @ApiModelProperty(value = "题目列表")
    private List<PaperQuestionData> questionList;
    
    
    
    @Data
public class PaperQuestionData {

    @ApiModelProperty(value = "题目ID")
    private Long questionId;

    @ApiModelProperty(value = "题目题干")
    private String questionName;

    @ApiModelProperty(value = "题目类型")
    private Integer questionType;

    @ApiModelProperty(value = "题目分数")
    private Integer score;

    @ApiModelProperty(value = "是否为试卷题目")
    private boolean isSelected;

}

 @SysLogAnnotation("试卷题目分页列表")
    @ApiOperation("试卷题目分页列表")
    @PostMapping("/paperQuestionList")
    public BaseResponse<QuestionPageVo> paperQuestionList(@RequestBody QuestionPageDataReqVo reqVo) {
        QuestionPageVo questionPageVo =courseQuestionsService.listQuestionPageData(reqVo);
        return BaseResponse.success(questionPageVo);
    }
/**
     * 试卷题目分页列表
     * @param reqVo
     * @return
     */
    QuestionPageVo listQuestionPageData(QuestionPageDataReqVo reqVo);
/**
 * 试卷题目分页列表
 * PaperQuestionData: 题目ID、题目题干、题目类型、题目分数、是否为试卷题目
 * QuestionPageVo 分页返回:分页参数、题目列表private List<PaperQuestionData> questionList;
 * 试卷题目列表请求VO:分页参数、试卷id、题库id
 * @param reqVo
 * @return
 */
@Override
public QuestionPageVo listQuestionPageData(QuestionPageDataReqVo reqVo) {
    //先根据题库id查询所有的问题列表
    PageHelper.startPage(reqVo.getPageReqVO().getCurrent(),reqVo.getPageReqVO().getPageSize());
    QueryWrapper<CourseQuestions> queryWrapper = new QueryWrapper<>();
    queryWrapper.lambda().eq(CourseQuestions::getQuestionDbId,reqVo.getQuestionDbId());
    queryWrapper.orderByDesc("id");
    List<CourseQuestions> resultQuestion = list(queryWrapper);
    //把查询结果封装到PageInfo
    PageInfo<CourseQuestions> pageInfo = new PageInfo<>(resultQuestion);
    //创建返回对象
    QuestionPageVo courseQuestionPageResVo = new QuestionPageVo();
    List<PaperQuestionData> resultList = pageInfo.getList().stream().map(item -> {
        PaperQuestionData paperQuestionData = new PaperQuestionData();
        paperQuestionData.setQuestionId(item.getId());
        paperQuestionData.setQuestionName(item.getQuestionName());
        paperQuestionData.setQuestionType(item.getQuestionType());
        //看试题是否和试卷有关系,从映射表中看
        ExamPaperQuestionMap examPaperQuestionMap = examPaperQuestionMapService.getDetailQuestionByPaperIdAndQuestionId(reqVo.getPaperId(), item.getId());
        if (examPaperQuestionMap != null) {
            paperQuestionData.setSelected(true);
            paperQuestionData.setScore(examPaperQuestionMap.getScore());
        } else {
            paperQuestionData.setSelected(false);
            paperQuestionData.setScore(item.getScore());
        }
        return paperQuestionData;
    }).collect(Collectors.toList());
    courseQuestionPageResVo.setQuestionList(resultList);
    PageResVO pageResVO = new PageResVO();
    pageResVO.setCurrent(pageInfo.getPageNum());
    pageResVO.setPageSize(pageInfo.getPageSize());
    pageResVO.setTotal(pageInfo.getTotal());
    courseQuestionPageResVo.setPageResVO(pageResVO);
    return courseQuestionPageResVo;
}

课程问题映射表

批量添加记录

参数是问题列表,课程id

先判断参数和判断课程是否存在

批量添加就是参数列表转为目标列表,然后批量保存列表,我们循环参数列表,循环里面创建目标对象,对目标对象赋值之后,返回目标对象,然后就可以生成目标列表

/**
     * 向课程问题映射表中批量添加记录
     *  * 参数是topicId 课程id,问题列表
     * 批量添加的思路就是循环问题列表,把关联关系添加到映射表中
     *  * 需要创建映射表对象,赋值属性,返回映射对象
     * @param list
     * @param topicId
     * @return
     */
    @Override
    public boolean addBatchMap(List<CourseQuestions> list, Long topicId) {
        if(topicId == null) {
            return false;
        }
        CourseBasicInfo courseBasicInfo = courseBasicInfoService.getById(topicId);
        if(courseBasicInfo == null) {
            return false;
        }
        //循环参数列表生成映射列表,就可以直接用列表做参数批量添加
        List<CourseQuestionsMap> courseQuestionsMapList = list.stream().map(obj -> {
            CourseQuestionsMap courseQuestionsMap = new CourseQuestionsMap();
            courseQuestionsMap.setQuestionId(obj.getId());
            courseQuestionsMap.setCourseId(topicId);
            return courseQuestionsMap;
        }).collect(Collectors.toList());
        return saveOrUpdateBatch(courseQuestionsMapList);
    }

根据课程id批量删除映射关系

根据课程id查询对应的映射列表数据,循环该列表拿到主键id列表,然后removeByIds(ids);

/**
     * 根据课程id批量删除映射表记录
     * 先通过课程id拿到在映射表中与该课程相关的记录List,再从list的循环中拿到主键列表
     * 根据removeByIds(ids)即可达到目的
     * @param courseId
     * @return
     */
    @Override
    public boolean removeList(Long courseId) {
        List<CourseQuestionsMap> list = getListByCourseId(courseId);
        List<Long> ids = list.stream().map(obj ->
                obj.getId()
        ).collect(Collectors.toList());
        boolean success = removeByIds(ids);
        return success;
    }

根据问题id批量删除映射关系

/**
     * 根据问题id批量删除映射表记录
     * @param questionId
     * @return
     */
    @Override
    public boolean removeByQuestionId(Long questionId) {
        List<CourseQuestionsMap> list = getListByQuestionId(questionId);
        List<Long> ids = list.stream().map(obj -> obj.getId()).collect(Collectors.toList());
        if (ids.size() == 0) {
            return true;
        }
        boolean success = removeByIds(ids);
        return success;
    }

单个删除

/**
     * 单个删除
     * @param id
     * @return
     */
    @Override
    public boolean removeQuestion(Long id) {
        return removeById(id);
    }

通过问题id获得映射关系列表

/**
 * 通过问题ID获得课程和问题映射列表
 * @param questionId
 * @return
 */
@Override
public List<CourseQuestionsMap> getListByQuestionId(Long questionId) {
    QueryWrapper<CourseQuestionsMap> queryWrapper = new QueryWrapper<>();
    queryWrapper.lambda().eq(CourseQuestionsMap::getQuestionId, questionId);
    return list(queryWrapper);
}

通过课程id获得映射关系列表

/**
 * 通过课程ID获得课程和问题映射列表
 * @param courseId
 * @return
 */
@Override
public List<CourseQuestionsMap> getListByCourseId(Long courseId) {
    QueryWrapper<CourseQuestionsMap> queryWrapper = new QueryWrapper<>();
    queryWrapper.lambda().eq(CourseQuestionsMap::getCourseId, courseId);
    return list(queryWrapper);
}

试卷管理

新增试卷

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值