PaperBasicInfo
parent
6d3a68921c
commit
436cc83033
|
|
@ -0,0 +1,11 @@
|
|||
-- =====================================================================
|
||||
-- 变更说明:
|
||||
-- 1. paper 表新增 paper_type(试卷类型, varchar(36), 非空, 默认fixed:
|
||||
-- fixed平台试卷,config_rule规则试卷)
|
||||
-- 2. paper 表新增 config_rule(配置规则, text, 可空)
|
||||
-- 变更时间: 2026-08-20
|
||||
-- =====================================================================
|
||||
|
||||
ALTER TABLE `paper`
|
||||
ADD COLUMN `paper_type` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'fixed' COMMENT '试卷类型 fixed平台试卷,config_rule规则试卷' AFTER `status`,
|
||||
ADD COLUMN `config_rule` text COLLATE utf8mb4_general_ci COMMENT '配置规则' AFTER `paper_type`;
|
||||
|
|
@ -3,9 +3,11 @@ package org.qinan.cedu.controller;
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.qinan.cedu.model.dto.*;
|
||||
import org.qinan.cedu.model.vo.PaperImportVO;
|
||||
import org.qinan.cedu.model.vo.PaperExamInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
import org.qinan.cedu.model.vo.PaperQuestionVO;
|
||||
import org.qinan.cedu.service.PaperService;
|
||||
|
|
@ -73,4 +75,11 @@ public class PaperController {
|
|||
IPage<PaperQuestionVO> page = questionService.pagePaperQuestions(query);
|
||||
return PageResponse.of(page.getRecords(), page.getTotal());
|
||||
}
|
||||
|
||||
@ApiOperation("试卷考试信息查询")
|
||||
@GetMapping("/paper/exam/info")
|
||||
public SingleResponse<PaperExamInfoVO> paperExamInfo(@RequestParam("paperId") @ApiParam(value = "试卷id", required = true) Long paperId) {
|
||||
PaperExamInfoVO pageInfo = paperService.paperExamInfo(paperId);
|
||||
return SingleResponse.success(pageInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.qinan.cedu.convertor;
|
|||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.qinan.cedu.model.entity.PaperDO;
|
||||
import org.qinan.cedu.model.vo.PaperBasicInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -12,4 +13,12 @@ public interface PaperConvertor {
|
|||
PaperPageVO convertEToVo(PaperDO entity);
|
||||
|
||||
List<PaperPageVO> convertEListToVoList(List<PaperDO> list);
|
||||
|
||||
/**
|
||||
* 试卷实体转试卷基础信息VO
|
||||
*
|
||||
* @param entity 试卷实体
|
||||
* @return 试卷基础信息VO
|
||||
*/
|
||||
PaperBasicInfoVO convertEToBasicVo(PaperDO entity);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package org.qinan.cedu.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 试卷类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PaperTypeEnum {
|
||||
|
||||
/**
|
||||
* 平台试卷
|
||||
*/
|
||||
FIXED("fixed", "平台试卷"),
|
||||
|
||||
/**
|
||||
* 规则试卷
|
||||
*/
|
||||
CONFIG_RULE("config_rule", "规则试卷");
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String label;
|
||||
|
||||
public static final String REMARKS = "试卷类型 fixed平台试卷,config_rule规则试卷";
|
||||
|
||||
/**
|
||||
* 根据编码获取枚举
|
||||
*/
|
||||
public static PaperTypeEnum fromCode(String code) {
|
||||
for (PaperTypeEnum type : values()) {
|
||||
if (type.value.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,14 @@ public interface QuestionMapper extends BaseMapper<QuestionDO> {
|
|||
*/
|
||||
QuestionVO findQuestion(@Param("questionId") Long questionId);
|
||||
|
||||
/**
|
||||
* 查询试卷下的试题列表(关联课件名称)
|
||||
*
|
||||
* @param paperId 试卷id
|
||||
* @return 试题VO列表
|
||||
*/
|
||||
List<QuestionVO> listPaperQuestions(@Param("paperId") Long paperId);
|
||||
|
||||
/**
|
||||
* 按题型统计试题数量(按关联课件过滤,一条SQL聚合)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package org.qinan.cedu.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PaperConfigRuleDTO {
|
||||
|
||||
// private
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel;
|
|||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.qinan.cedu.enums.PaperTypeEnum;
|
||||
import org.qinan.cedu.model.query.BasePageQuery;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
|
|
@ -20,6 +21,9 @@ public class PaperPageQueryDTO extends BasePageQuery {
|
|||
@ApiModelProperty("试卷名称(模糊)")
|
||||
private String paperName;
|
||||
|
||||
@ApiModelProperty(PaperTypeEnum.REMARKS)
|
||||
private String paperType;
|
||||
|
||||
@ApiModelProperty("创建时间-开始(yyyy-MM-dd,含当天)")
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
|
||||
private LocalDate createTimeStart;
|
||||
|
|
|
|||
|
|
@ -38,4 +38,11 @@ public class PaperUpdateDTO {
|
|||
@DecimalMin(value = "0", message = "合格分数不能小于0")
|
||||
@DecimalMax(value = "9999.99", message = "合格分数不能超过9999.99")
|
||||
private BigDecimal paperPassScore;
|
||||
|
||||
@ApiModelProperty("试卷类型 fixed平台试卷,config_rule规则试卷")
|
||||
@Size(max = 36, message = "试卷类型长度不能超过36个字符")
|
||||
private String paperType;
|
||||
|
||||
@ApiModelProperty("配置规则")
|
||||
private String configRule;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,4 +36,10 @@ public class PaperDO extends BaseEntity {
|
|||
|
||||
@ApiModelProperty("试卷状态 normal 正常")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty("试卷类型 fixed平台试卷,config_rule规则试卷")
|
||||
private String paperType;
|
||||
|
||||
@ApiModelProperty("配置规则")
|
||||
private String configRule;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package org.qinan.cedu.model.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 试卷
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "PaperBasicInfoVO", description = "试卷基础信息")
|
||||
public class PaperBasicInfoVO {
|
||||
|
||||
@ApiModelProperty("id")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ApiModelProperty("试卷名称")
|
||||
private String paperName;
|
||||
|
||||
@ApiModelProperty("试卷总分")
|
||||
private BigDecimal paperTotalScore;
|
||||
|
||||
@ApiModelProperty("合格分数")
|
||||
private BigDecimal paperPassScore;
|
||||
|
||||
@ApiModelProperty("试卷状态 normal 正常")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty("试卷类型 fixed平台试卷,config_rule规则试卷")
|
||||
private String paperType;
|
||||
|
||||
@ApiModelProperty("配置规则")
|
||||
private String configRule;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.qinan.cedu.model.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 试卷试题分页返回
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "PaperExamInfoVO", description = "试卷考试信息")
|
||||
public class PaperExamInfoVO {
|
||||
|
||||
@ApiModelProperty("试卷基本信息")
|
||||
private PaperBasicInfoVO paperBasicInfoVO;
|
||||
|
||||
@ApiModelProperty("试题信息")
|
||||
private List<QuestionVO> questionVOList;
|
||||
}
|
||||
|
|
@ -33,6 +33,12 @@ public class PaperPageVO {
|
|||
@ApiModelProperty("试卷状态 normal 正常")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty("试卷类型 fixed平台试卷,config_rule规则试卷")
|
||||
private String paperType;
|
||||
|
||||
@ApiModelProperty("配置规则")
|
||||
private String configRule;
|
||||
|
||||
@ApiModelProperty("创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.qinan.cedu.model.dto.PaperPageQueryDTO;
|
|||
import org.qinan.cedu.model.dto.PaperUpdateDTO;
|
||||
import org.qinan.cedu.model.entity.PaperDO;
|
||||
import org.qinan.cedu.model.vo.PaperImportVO;
|
||||
import org.qinan.cedu.model.vo.PaperExamInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -20,7 +21,7 @@ public interface PaperService extends IService<PaperDO> {
|
|||
/**
|
||||
* 分页查询试卷
|
||||
*
|
||||
* @param query 查询条件(试卷名称、创建时间范围)
|
||||
* @param query 查询条件(试卷名称、试卷类型、创建时间范围)
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<PaperPageVO> pageQuery(PaperPageQueryDTO query);
|
||||
|
|
@ -88,5 +89,11 @@ public interface PaperService extends IService<PaperDO> {
|
|||
*/
|
||||
String importQuestionsTemplate();
|
||||
|
||||
|
||||
/**
|
||||
* 查询试卷考试信息(试卷基础信息+试题列表含选项)
|
||||
*
|
||||
* @param paperId 试卷id
|
||||
* @return 试卷考试信息
|
||||
*/
|
||||
PaperExamInfoVO paperExamInfo(Long paperId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@ import com.baomidou.mybatisplus.extension.toolkit.Db;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.qinan.cedu.convertor.PaperConvertor;
|
||||
import org.qinan.cedu.convertor.QuestionConvertor;
|
||||
import org.qinan.cedu.enums.DeleteEnum;
|
||||
import org.qinan.cedu.enums.PaperStatusEnum;
|
||||
import org.qinan.cedu.enums.PaperTypeEnum;
|
||||
import org.qinan.cedu.mapper.PaperMapper;
|
||||
import org.qinan.cedu.mapper.PaperQuestionRelMapper;
|
||||
import org.qinan.cedu.mapper.QuestionMapper;
|
||||
import org.qinan.cedu.mapper.QuestionOptionMapper;
|
||||
import org.qinan.cedu.model.dto.PaperCopyDTO;
|
||||
import org.qinan.cedu.model.dto.PaperImportDTO;
|
||||
|
|
@ -23,8 +26,11 @@ import org.qinan.cedu.model.entity.PaperDO;
|
|||
import org.qinan.cedu.model.entity.PaperQuestionRelDO;
|
||||
import org.qinan.cedu.model.entity.QuestionDO;
|
||||
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
||||
import org.qinan.cedu.model.vo.PaperExamInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperImportVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
import org.qinan.cedu.model.vo.QuestionOptionVO;
|
||||
import org.qinan.cedu.model.vo.QuestionVO;
|
||||
import org.qinan.cedu.service.PaperService;
|
||||
import org.qinan.cedu.service.support.QuestionExcelImporter;
|
||||
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
|
||||
|
|
@ -49,9 +55,11 @@ import java.util.stream.Collectors;
|
|||
public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implements PaperService {
|
||||
|
||||
private final PaperQuestionRelMapper paperQuestionRelMapper;
|
||||
private final QuestionMapper questionMapper;
|
||||
private final QuestionOptionMapper questionOptionMapper;
|
||||
private final QuestionExcelImporter questionExcelImporter;
|
||||
private final PaperConvertor paperConvertor;
|
||||
private final QuestionConvertor questionConvertor;
|
||||
|
||||
@Value("${template.paper.importUrl:}")
|
||||
private String paperImportUrl;
|
||||
|
|
@ -131,6 +139,8 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
|||
target.setPaperTotalScore(copyDTO.getPaperTotalScore());
|
||||
target.setPaperPassScore(copyDTO.getPaperPassScore());
|
||||
target.setStatus(source.getStatus());
|
||||
target.setPaperType(source.getPaperType());
|
||||
target.setConfigRule(source.getConfigRule());
|
||||
this.savePaper(target);
|
||||
|
||||
// 复制试题+选项+试卷试题关系(id全部换新雪花id)
|
||||
|
|
@ -266,4 +276,52 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
|||
public String importQuestionsTemplate() {
|
||||
return paperImportUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaperExamInfoVO paperExamInfo(Long paperId) {
|
||||
// 1. 查询试卷基础信息
|
||||
PaperDO paper = this.lambdaQuery()
|
||||
.eq(PaperDO::getId, paperId)
|
||||
.eq(PaperDO::getDeleteEnum, DeleteEnum.FALSE.getCode())
|
||||
.one();
|
||||
if (paper == null) {
|
||||
throw new IllegalArgumentException("试卷不存在");
|
||||
}
|
||||
PaperExamInfoVO examInfoVO = new PaperExamInfoVO();
|
||||
examInfoVO.setPaperBasicInfoVO(paperConvertor.convertEToBasicVo(paper));
|
||||
|
||||
// 2. 查询试卷下试题(关联课件名称)并填充选项
|
||||
List<QuestionVO> questionVOList = questionMapper.listPaperQuestions(paperId);
|
||||
fillQuestionOptions(questionVOList);
|
||||
examInfoVO.setQuestionVOList(questionVOList);
|
||||
return examInfoVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量填充试题选项:一次查询所有试题的选项后按试题id分组回填
|
||||
*
|
||||
* @param questionVOList 试题VO列表
|
||||
*/
|
||||
private void fillQuestionOptions(List<QuestionVO> questionVOList) {
|
||||
if (CollectionUtils.isEmpty(questionVOList)) {
|
||||
return;
|
||||
}
|
||||
List<Long> questionIds = questionVOList.stream()
|
||||
.map(question -> Long.valueOf(question.getId()))
|
||||
.collect(Collectors.toList());
|
||||
// 查询选项信息(仅查询VO需要的字段,按显示顺序排序)
|
||||
List<QuestionOptionDO> optionList = questionOptionMapper.selectList(new LambdaQueryWrapper<QuestionOptionDO>()
|
||||
.select(QuestionOptionDO::getId, QuestionOptionDO::getQuestionId,
|
||||
QuestionOptionDO::getOptionKey, QuestionOptionDO::getOptionName,
|
||||
QuestionOptionDO::getOptionText, QuestionOptionDO::getIsCorrect,
|
||||
QuestionOptionDO::getSortOrder)
|
||||
.in(QuestionOptionDO::getQuestionId, questionIds)
|
||||
.eq(QuestionOptionDO::getDeleteEnum, DeleteEnum.FALSE.getCode())
|
||||
.orderByAsc(QuestionOptionDO::getSortOrder));
|
||||
Map<Long, List<QuestionOptionVO>> optionMap = questionConvertor.convertOptionEListToVoList(optionList)
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(QuestionOptionVO::getQuestionId));
|
||||
questionVOList.forEach(question -> question.setQuestionOptionVOList(
|
||||
optionMap.getOrDefault(Long.valueOf(question.getId()), new ArrayList<>())));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,19 @@
|
|||
AND q.delete_enum = 'false'
|
||||
</select>
|
||||
|
||||
<select id="listPaperQuestions" resultType="org.qinan.cedu.model.vo.QuestionVO">
|
||||
SELECT q.id, q.title, q.question_type, q.answer, q.answer_question_option_ids
|
||||
, q.score, q.analysis, q.tag_type, q.courseware_management_id
|
||||
, cm.courseware_name AS coursewareManagementName
|
||||
FROM paper_question_rel pqr
|
||||
JOIN question q ON pqr.question_id = q.id
|
||||
LEFT JOIN courseware_management cm ON cm.id = q.courseware_management_id
|
||||
WHERE pqr.paper_id = #{paperId}
|
||||
AND pqr.delete_enum = 'false'
|
||||
AND q.delete_enum = 'false'
|
||||
ORDER BY pqr.question_num ASC, pqr.id ASC
|
||||
</select>
|
||||
|
||||
<select id="countQuestionType" resultType="org.qinan.cedu.model.vo.QuestionTypeCountVO">
|
||||
SELECT q.question_type AS questionType, COUNT(*) AS `count`
|
||||
FROM question q
|
||||
|
|
|
|||
Loading…
Reference in New Issue