PaperBasicInfo

dev-tmp1
luotaiqian 2026-08-20 11:04:01 +08:00
parent 8e55eda450
commit a4e5283f86
8 changed files with 171 additions and 10 deletions

View File

@ -6,10 +6,7 @@ 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.model.vo.*;
import org.qinan.cedu.service.PaperService;
import org.qinan.cedu.service.QuestionService;
import org.qinan.safetyeval.client.dto.PageResponse;
@ -69,6 +66,12 @@ public class PaperController {
return SingleResponse.success(paperService.importQuestionsTemplate());
}
@ApiOperation("新建试卷-自动生成试卷")
@PostMapping("/courseware/question/rule")
public SingleResponse<PaperBasicInfoVO> coursewareQuestionRule(@Validated @RequestBody PaperCoursewareQuestionRuleDTO dto) {
return SingleResponse.success(paperService.coursewareQuestionRule(dto));
}
@ApiOperation("试卷试题分页查询")
@GetMapping("/paper/question/page")
public PageResponse<PaperQuestionVO> page(@Validated PaperQuestionPageQueryDTO query) {

View File

@ -51,4 +51,16 @@ public interface QuestionMapper extends BaseMapper<QuestionDO> {
* @return
*/
List<QuestionTypeCountVO> countQuestionType(@Param("dto") QuestionTypeCountQueryDTO dto);
/**
* id+id
*
* @param coursewareManagementIdList id
* @param questionType
* @param num
* @return id
*/
List<Long> listRandomQuestionIds(@Param("coursewareManagementIdList") List<Long> coursewareManagementIdList,
@Param("questionType") String questionType,
@Param("num") Integer num);
}

View File

@ -1,9 +1,38 @@
package org.qinan.cedu.model.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.qinan.cedu.enums.QuestionTypeEnum;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
@Data
public class PaperConfigRuleDTO {
// private
@Data
public static class QuestionTypeRule {
@ApiModelProperty(QuestionTypeEnum.REMARKS)
@NotNull(message = QuestionTypeEnum.REMARKS)
@Pattern(regexp = QuestionTypeEnum.PATTERN)
private String questionType;
@ApiModelProperty("需要的试题数量")
@NotNull(message = "试题数量1-1024")
@Range(min = 1, max = 1024, message = "试题数量1-1024")
private Integer num;
@ApiModelProperty("每题的分数")
@NotNull(message = "每题的分数")
@DecimalMin(value = "0.1")
@DecimalMax(value = "999.9")
private BigDecimal score;
}
}

View File

@ -0,0 +1,49 @@
package org.qinan.cedu.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.List;
/**
* -
*/
@Data
@ApiModel(value = "PaperImportDTO", description = "新建试卷-导入试题请求")
public class PaperCoursewareQuestionRuleDTO {
@ApiModelProperty(value = "试卷名称", required = true)
@NotBlank(message = "试卷名称 不能为空")
@Size(max = 128, message = "试卷名称长度不能超过128个字符")
private String paperName;
@ApiModelProperty(value = "试卷总分", required = true)
@NotNull(message = "试卷总分不能为空")
@DecimalMin(value = "0.1", message = "试卷总分必须大于0")
@DecimalMax(value = "9999.9", message = "试卷总分不能超过9999.99")
private BigDecimal paperTotalScore;
@ApiModelProperty(value = "合格分数", required = true)
@NotNull(message = "合格分数不能为空")
@DecimalMin(value = "0", message = "合格分数不能小于0")
@DecimalMax(value = "9999.9", message = "合格分数不能超过9999.99")
private BigDecimal paperPassScore;
@ApiModelProperty("考试时长(分钟)")
@Range(min = 1, max = 3600, message = "考试时长必须大于0小于3600")
private Integer examTime;
@ApiModelProperty("课件id")
@NotNull(message = "请选择课程课件")
@Size(min = 1, max = 1024, message = "请选择课程课件")
private List<Long> coursewareManagementIdList;
@NotNull(message = "试题规则不能为空")
@Valid
private List<PaperConfigRuleDTO.QuestionTypeRule> questionTypeRuleList;
}

View File

@ -3,13 +3,10 @@ package org.qinan.cedu.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.*;
import java.math.BigDecimal;
/**
@ -37,7 +34,7 @@ public class PaperImportDTO {
private BigDecimal paperPassScore;
@ApiModelProperty("考试时长(分钟)")
@Min(value = 1, message = "考试时长必须大于0")
@Range(min = 1, max = 3600, message = "考试时长必须大于0小于3600")
private Integer examTime;
@ApiModelProperty(value = "试题Excel文件第一个sheet单选题第二个sheet多选题第三个sheet判断题", required = true)

View File

@ -3,10 +3,12 @@ package org.qinan.cedu.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.qinan.cedu.model.dto.PaperCopyDTO;
import org.qinan.cedu.model.dto.PaperCoursewareQuestionRuleDTO;
import org.qinan.cedu.model.dto.PaperImportDTO;
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.PaperBasicInfoVO;
import org.qinan.cedu.model.vo.PaperImportVO;
import org.qinan.cedu.model.vo.PaperExamInfoVO;
import org.qinan.cedu.model.vo.PaperPageVO;
@ -89,6 +91,15 @@ public interface PaperService extends IService<PaperDO> {
*/
String importQuestionsTemplate();
/**
* -
*
*
* @param dto +id+
* @return
*/
PaperBasicInfoVO coursewareQuestionRule(PaperCoursewareQuestionRuleDTO dto);
/**
* +
*

View File

@ -1,6 +1,7 @@
package org.qinan.cedu.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -14,11 +15,14 @@ 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.enums.QuestionTypeEnum;
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.PaperConfigRuleDTO;
import org.qinan.cedu.model.dto.PaperCopyDTO;
import org.qinan.cedu.model.dto.PaperCoursewareQuestionRuleDTO;
import org.qinan.cedu.model.dto.PaperImportDTO;
import org.qinan.cedu.model.dto.PaperPageQueryDTO;
import org.qinan.cedu.model.dto.PaperUpdateDTO;
@ -26,6 +30,7 @@ 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.PaperBasicInfoVO;
import org.qinan.cedu.model.vo.PaperExamInfoVO;
import org.qinan.cedu.model.vo.PaperImportVO;
import org.qinan.cedu.model.vo.PaperPageVO;
@ -278,6 +283,48 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
return paperImportUrl;
}
@Override
@Transactional(rollbackFor = Exception.class)
public PaperBasicInfoVO coursewareQuestionRule(PaperCoursewareQuestionRuleDTO dto) {
// 1. 循环题型规则从关联课件下随机抽题,某题型数量不足直接报错
List<Long> questionIds = new ArrayList<>();
for (PaperConfigRuleDTO.QuestionTypeRule rule : dto.getQuestionTypeRuleList()) {
List<Long> ids = questionMapper.listRandomQuestionIds(
dto.getCoursewareManagementIdList(), rule.getQuestionType(), rule.getNum());
if (ids.size() < rule.getNum()) {
QuestionTypeEnum typeEnum = QuestionTypeEnum.fromCode(rule.getQuestionType());
String typeDesc = typeEnum != null ? typeEnum.getDesc() : rule.getQuestionType();
throw new IllegalArgumentException(
typeDesc + "题数量不足:需要" + rule.getNum() + "道,当前仅有" + ids.size() + "道");
}
questionIds.addAll(ids);
}
// 2. 创建试卷(规则试卷,保存抽题规则)
PaperDO paper = new PaperDO();
paper.setPaperName(dto.getPaperName().trim());
paper.setPaperTotalScore(dto.getPaperTotalScore());
paper.setPaperPassScore(dto.getPaperPassScore());
paper.setExamTime(dto.getExamTime());
paper.setPaperType(PaperTypeEnum.CONFIG_RULE.getValue());
paper.setConfigRule(JSONUtil.toJsonStr(dto.getQuestionTypeRuleList()));
InsertFieldDefaults.applyIgnoreOrgId(paper);
this.savePaper(paper);
// 3. 绑定试卷试题关系(含试题号)
List<PaperQuestionRelDO> rels = new ArrayList<>(questionIds.size());
for (int i = 0; i < questionIds.size(); i++) {
PaperQuestionRelDO rel = new PaperQuestionRelDO();
rel.setPaperId(paper.getId());
rel.setQuestionId(questionIds.get(i));
rel.setQuestionNum(i + 1);
InsertFieldDefaults.applyIgnoreOrgId(rel);
rels.add(rel);
}
Db.saveBatch(rels);
return paperConvertor.convertEToBasicVo(paper);
}
@Override
public PaperExamInfoVO paperExamInfo(Long paperId) {
// 1. 查询试卷基础信息

View File

@ -55,4 +55,17 @@
AND q.delete_enum = 'false'
GROUP BY q.question_type
</select>
<select id="listRandomQuestionIds" resultType="java.lang.Long">
SELECT q.id
FROM question q
WHERE q.courseware_management_id IN
<foreach collection="coursewareManagementIdList" item="coursewareManagementId" open="(" separator="," close=")">
#{coursewareManagementId}
</foreach>
AND q.delete_enum = 'false'
AND q.question_type = #{questionType}
ORDER BY RAND()
LIMIT #{num}
</select>
</mapper>