feat(exam): 支持按单个学生和考试类型生成考试试题
- 修改生成试题按钮仅在选中特定一个学生时可用,避免多选时误操作 - 在考试生成对话框新增“类型”选择项,支持“摸底”和“期中|期末”类型 - 调整后台接口,使用单个学生ID和考试类型替代学生ID列表参数 - 优化考试生成服务,新增摸底考试生成逻辑,按年级分区随机抽词汇 - 考试相关数据对象新增类型字段,保持数据完整性和一致性 - 修改考试判卷服务,将错误信息字段统一为msg,避免字段混淆 - 调整数据库操作,支持单个学生考试与词汇随机获取 - 同步更新测试用例和词汇库数据插入逻辑,确保环境一致性 - 修复界面生成按钮状态和对话框提交按钮的校验逻辑,提升用户体验
This commit is contained in:
@@ -1,6 +1,108 @@
|
|||||||
package com.yinlihupo.enlish.service.constant;
|
package com.yinlihupo.enlish.service.constant;
|
||||||
|
|
||||||
public interface ExamWordsConstant {
|
public class ExamWordsConstant {
|
||||||
|
|
||||||
int PGN_COL = 53;
|
public static final int PGN_COL = 53;
|
||||||
|
|
||||||
|
public static final int GRADE_1 = 1;
|
||||||
|
public static final int GRADE_2 = 2;
|
||||||
|
public static final int GRADE_3 = 3;
|
||||||
|
public static final int GRADE_4 = 4;
|
||||||
|
public static final int GRADE_5 = 5;
|
||||||
|
public static final int GRADE_6 = 7;
|
||||||
|
public static final int GRADE_7 = 8;
|
||||||
|
public static final int GRADE_8 = 9;
|
||||||
|
|
||||||
|
public static final int ZONE_A_SIZE = 10;
|
||||||
|
public static final int ZONE_B_SIZE = 20;
|
||||||
|
public static final int ZONE_C_SIZE = 28;
|
||||||
|
public static final int ZONE_D_SIZE = 21;
|
||||||
|
public static final int ZONE_E_SIZE = 14;
|
||||||
|
public static final int ZONE_F_SIZE = 7;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int EXAM_TYPE_BASELINE = 1;
|
||||||
|
|
||||||
|
public static int getZoneA(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_2;
|
||||||
|
case GRADE_2 -> GRADE_3;
|
||||||
|
case GRADE_3 -> GRADE_4;
|
||||||
|
case GRADE_4 -> GRADE_5;
|
||||||
|
case GRADE_5 -> GRADE_6;
|
||||||
|
case GRADE_6 -> GRADE_7;
|
||||||
|
case GRADE_7 -> GRADE_8;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getZoneB(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_1;
|
||||||
|
case GRADE_2 -> GRADE_2;
|
||||||
|
case GRADE_3 -> GRADE_3;
|
||||||
|
case GRADE_4 -> GRADE_4;
|
||||||
|
case GRADE_5 -> GRADE_5;
|
||||||
|
case GRADE_6 -> GRADE_6;
|
||||||
|
case GRADE_7 -> GRADE_7;
|
||||||
|
case GRADE_8 -> GRADE_8;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getZoneC(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_1;
|
||||||
|
case GRADE_2 -> GRADE_1;
|
||||||
|
case GRADE_3 -> GRADE_2;
|
||||||
|
case GRADE_4 -> GRADE_3;
|
||||||
|
case GRADE_5 -> GRADE_4;
|
||||||
|
case GRADE_6 -> GRADE_5;
|
||||||
|
case GRADE_7 -> GRADE_6;
|
||||||
|
case GRADE_8 -> GRADE_7;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getZoneD(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_1;
|
||||||
|
case GRADE_2 -> GRADE_1;
|
||||||
|
case GRADE_3 -> GRADE_1;
|
||||||
|
case GRADE_4 -> GRADE_2;
|
||||||
|
case GRADE_5 -> GRADE_3;
|
||||||
|
case GRADE_6 -> GRADE_4;
|
||||||
|
case GRADE_7 -> GRADE_5;
|
||||||
|
case GRADE_8 -> GRADE_6;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getZoneE(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_1;
|
||||||
|
case GRADE_2 -> GRADE_1;
|
||||||
|
case GRADE_3 -> GRADE_1;
|
||||||
|
case GRADE_4 -> GRADE_1;
|
||||||
|
case GRADE_5 -> GRADE_2;
|
||||||
|
case GRADE_6 -> GRADE_3;
|
||||||
|
case GRADE_7 -> GRADE_4;
|
||||||
|
case GRADE_8 -> GRADE_5;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getZoneF(int gradeId) {
|
||||||
|
return switch (gradeId) {
|
||||||
|
case GRADE_1 -> GRADE_1;
|
||||||
|
case GRADE_2 -> GRADE_1;
|
||||||
|
case GRADE_3 -> GRADE_1;
|
||||||
|
case GRADE_4 -> GRADE_1;
|
||||||
|
case GRADE_5 -> GRADE_1;
|
||||||
|
case GRADE_6 -> GRADE_2;
|
||||||
|
case GRADE_7 -> GRADE_3;
|
||||||
|
case GRADE_8 -> GRADE_4;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,13 @@ public class ExamWordsController {
|
|||||||
public void generateFeltExamWords(@RequestBody GenerateExamWordsReqVO generateExamWordsReqVO, HttpServletResponse response) {
|
public void generateFeltExamWords(@RequestBody GenerateExamWordsReqVO generateExamWordsReqVO, HttpServletResponse response) {
|
||||||
Integer gradeId = generateExamWordsReqVO.getGradeId();
|
Integer gradeId = generateExamWordsReqVO.getGradeId();
|
||||||
Integer level = generateExamWordsReqVO.getLevel();
|
Integer level = generateExamWordsReqVO.getLevel();
|
||||||
List<Integer> studentIds = generateExamWordsReqVO.getStudentIds();
|
Integer type = generateExamWordsReqVO.getType();
|
||||||
if (studentIds == null || studentIds.isEmpty() || gradeId == null || level == null) {
|
Integer studentId = generateExamWordsReqVO.getStudentId();
|
||||||
|
if (studentId == null || gradeId == null || level == null) {
|
||||||
throw new RuntimeException("参数错误");
|
throw new RuntimeException("参数错误");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ExamWordsDO examWordsDO = examWordsService.generateExamWords(gradeId, level, studentIds);
|
ExamWordsDO examWordsDO = examWordsService.generateExamWords(gradeId, level, studentId, type);
|
||||||
if (examWordsDO == null || examWordsDO.getWordIds().isEmpty()) {
|
if (examWordsDO == null || examWordsDO.getWordIds().isEmpty()) {
|
||||||
throw new RuntimeException("没有单词");
|
throw new RuntimeException("没有单词");
|
||||||
}
|
}
|
||||||
@@ -60,7 +61,7 @@ public class ExamWordsController {
|
|||||||
.definition(vocabularyBankDO.getDefinition())
|
.definition(vocabularyBankDO.getDefinition())
|
||||||
.build()).toList();
|
.build()).toList();
|
||||||
|
|
||||||
List<StudentDetail> studentDetailList = studentService.getStudentDetailList(studentIds);
|
List<StudentDetail> studentDetailList = studentService.getStudentDetailList(Collections.singletonList(studentId));
|
||||||
List<Map<String, Object>> maps = studentDetailList.stream().map(studentDetail -> {
|
List<Map<String, Object>> maps = studentDetailList.stream().map(studentDetail -> {
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
data.put("examId", examWordsDO.getId());
|
data.put("examId", examWordsDO.getId());
|
||||||
@@ -115,7 +116,7 @@ public class ExamWordsController {
|
|||||||
.correctWordCount(examWordsJudgeResultDO.getCorrectWordCount())
|
.correctWordCount(examWordsJudgeResultDO.getCorrectWordCount())
|
||||||
.wrongWordCount(examWordsJudgeResultDO.getWrongWordCount())
|
.wrongWordCount(examWordsJudgeResultDO.getWrongWordCount())
|
||||||
.isFinished(examWordsJudgeResultDO.getIsFinished())
|
.isFinished(examWordsJudgeResultDO.getIsFinished())
|
||||||
.errorMsg(examWordsJudgeResultDO.getErrorMsg())
|
.errorMsg(examWordsJudgeResultDO.getMsg())
|
||||||
.build()
|
.build()
|
||||||
).toList();
|
).toList();
|
||||||
return PageResponse.success(list, page, total, size);
|
return PageResponse.success(list, page, total, size);
|
||||||
@@ -134,7 +135,7 @@ public class ExamWordsController {
|
|||||||
.correctWordCount(examWordsJudgeResultDO.getCorrectWordCount())
|
.correctWordCount(examWordsJudgeResultDO.getCorrectWordCount())
|
||||||
.wrongWordCount(examWordsJudgeResultDO.getWrongWordCount())
|
.wrongWordCount(examWordsJudgeResultDO.getWrongWordCount())
|
||||||
.isFinished(examWordsJudgeResultDO.getIsFinished())
|
.isFinished(examWordsJudgeResultDO.getIsFinished())
|
||||||
.errorMsg(examWordsJudgeResultDO.getErrorMsg())
|
.errorMsg(examWordsJudgeResultDO.getMsg())
|
||||||
.correctWordIds(examWordsJudgeResultDO.getCorrectWordIds())
|
.correctWordIds(examWordsJudgeResultDO.getCorrectWordIds())
|
||||||
.wrongWordIds(examWordsJudgeResultDO.getWrongWordIds())
|
.wrongWordIds(examWordsJudgeResultDO.getWrongWordIds())
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public class ExamWordsDO {
|
|||||||
|
|
||||||
private Integer level;
|
private Integer level;
|
||||||
|
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ public class ExamWordsJudgeResultDO {
|
|||||||
|
|
||||||
private Integer isFinished;
|
private Integer isFinished;
|
||||||
|
|
||||||
|
private Integer ansGradeId;
|
||||||
|
|
||||||
private LocalDateTime startDate;
|
private LocalDateTime startDate;
|
||||||
|
|
||||||
private List<Integer> correctWordIds;
|
private List<Integer> correctWordIds;
|
||||||
|
|
||||||
private List<Integer> wrongWordIds;
|
private List<Integer> wrongWordIds;
|
||||||
|
|
||||||
private String errorMsg;
|
private String msg;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ public interface ExamWordsJudgeResultDOMapper {
|
|||||||
|
|
||||||
List<ExamWordsJudgeResultDO> selectUnfinishedExamWordsJudgeResultDOList(int count);
|
List<ExamWordsJudgeResultDO> selectUnfinishedExamWordsJudgeResultDOList(int count);
|
||||||
|
|
||||||
int updateErrorMsg(@Param("id") Integer id, @Param("errorMsg") String errorMsg);
|
int updateMsg(@Param("id") Integer id, @Param("msg") String msg);
|
||||||
|
|
||||||
int updateExamWordsJudgeResultDO(@Param("examWordsJudgeResultDO") ExamWordsJudgeResultDO examWordsJudgeResultDO);
|
int updateExamWordsJudgeResultDO(@Param("examWordsJudgeResultDO") ExamWordsJudgeResultDO examWordsJudgeResultDO);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface StudentExamWordsDOMapper {
|
public interface StudentExamWordsDOMapper {
|
||||||
|
|
||||||
int insertStudentsExam(@Param("studentIds") List<Integer> studentIds, @Param("examWordsId") Integer examWordsId);
|
int insertStudentsExam(@Param("studentId") Integer studentId, @Param("examWordsId") Integer examWordsId);
|
||||||
|
|
||||||
StudentExamWordsDO selectByStudentIdAndExamWordsId(@Param("studentId") Integer studentId, @Param("examWordsId") Integer examWordsId);
|
StudentExamWordsDO selectByStudentIdAndExamWordsId(@Param("studentId") Integer studentId, @Param("examWordsId") Integer examWordsId);
|
||||||
|
|
||||||
|
|||||||
@@ -21,5 +21,7 @@ public interface VocabularyBankDOMapper {
|
|||||||
|
|
||||||
List<VocabularyBankDO> selectVocabularyBankListSelfCheck(@Param("gradeId") Integer gradeId, @Param("studentId") Integer studentId, @Param("ids") List<Integer> ids, @Param("wordCount") Integer wordCount);
|
List<VocabularyBankDO> selectVocabularyBankListSelfCheck(@Param("gradeId") Integer gradeId, @Param("studentId") Integer studentId, @Param("ids") List<Integer> ids, @Param("wordCount") Integer wordCount);
|
||||||
|
|
||||||
|
List<VocabularyBankDO> selectVocabularyBankListByGradeIdRandom(@Param("gradeId") Integer gradeId, @Param("wordCount") Integer wordCount);
|
||||||
|
|
||||||
Integer selectWordTotal();
|
Integer selectWordTotal();
|
||||||
}
|
}
|
||||||
@@ -16,5 +16,6 @@ public class GenerateExamWordsReqVO {
|
|||||||
|
|
||||||
private Integer gradeId;
|
private Integer gradeId;
|
||||||
private Integer level;
|
private Integer level;
|
||||||
private List<Integer> studentIds;
|
private Integer type;
|
||||||
|
private Integer studentId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface ExamWordsService {
|
public interface ExamWordsService {
|
||||||
|
|
||||||
ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds);
|
ExamWordsDO generateExamWords(Integer gradeId, Integer level, Integer studentId, Integer type);
|
||||||
|
|
||||||
int saveExamWordsPngToDbAndLocal(MultipartFile file);
|
int saveExamWordsPngToDbAndLocal(MultipartFile file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.yinlihupo.enlish.service.service.exam;
|
package com.yinlihupo.enlish.service.service.exam;
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.constant.ExamWordsConstant;
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO;
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.StudentDO;
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.*;
|
import com.yinlihupo.enlish.service.domain.mapper.*;
|
||||||
import com.yinlihupo.enlish.service.service.ExamWordsService;
|
import com.yinlihupo.enlish.service.service.ExamWordsService;
|
||||||
@@ -16,6 +18,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -33,6 +36,9 @@ public class ExamWordsServiceImpl implements ExamWordsService {
|
|||||||
private StudentExamWordsDOMapper studentExamWordsDOMapper;
|
private StudentExamWordsDOMapper studentExamWordsDOMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper;
|
private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper;
|
||||||
|
@Resource
|
||||||
|
private StudentDOMapper studentDOMapper;
|
||||||
|
|
||||||
@Value("${templates.count}")
|
@Value("${templates.count}")
|
||||||
private Integer wordCount;
|
private Integer wordCount;
|
||||||
@Value("${tmp.png}")
|
@Value("${tmp.png}")
|
||||||
@@ -40,23 +46,55 @@ public class ExamWordsServiceImpl implements ExamWordsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = RuntimeException.class)
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
public ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds) {
|
public ExamWordsDO generateExamWords(Integer gradeId, Integer level, Integer studentId, Integer type) {
|
||||||
|
|
||||||
List<Integer> unitIds = gradeUnitDOMapper.selectUnitIdsByGradeId(gradeId);
|
|
||||||
List<VocabularyBankDO> vocabularyBankDOS = new ArrayList<>();
|
ExamWordsDO examWordsDO;
|
||||||
int count = wordCount;
|
|
||||||
for (Integer unitId : unitIds) {
|
if (type == ExamWordsConstant.EXAM_TYPE_BASELINE) {
|
||||||
List<VocabularyBankDO> words = vocabularyBankDOMapper.selectVocabularyBankDOListByUnitId(unitId, 20);
|
log.info("生成摸底测试");
|
||||||
vocabularyBankDOS.addAll(words);
|
examWordsDO = generateBaselineExamWords(studentId);
|
||||||
count -= 20;
|
} else {
|
||||||
if (count <= 0) {
|
// todo 生成期中考试待实现
|
||||||
break;
|
examWordsDO = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return examWordsDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExamWordsDO generateBaselineExamWords(Integer studentId) {
|
||||||
|
StudentDO studentDO = studentDOMapper.selectStudentById(studentId);
|
||||||
|
Integer gradeId = studentDO.getGradeId();
|
||||||
|
|
||||||
|
int zoneA = ExamWordsConstant.getZoneA(gradeId);
|
||||||
|
int zoneASize = ExamWordsConstant.ZONE_A_SIZE;
|
||||||
|
List<VocabularyBankDO> vocabularyBankDOS = new ArrayList<>(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneA, zoneASize));
|
||||||
|
|
||||||
|
int zoneB = ExamWordsConstant.getZoneB(gradeId);
|
||||||
|
int zoneBSize = ExamWordsConstant.ZONE_B_SIZE;
|
||||||
|
vocabularyBankDOS.addAll(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneB, zoneBSize));
|
||||||
|
|
||||||
|
int zoneC = ExamWordsConstant.getZoneC(gradeId);
|
||||||
|
int zoneCSize = ExamWordsConstant.ZONE_C_SIZE;
|
||||||
|
vocabularyBankDOS.addAll(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneC, zoneCSize));
|
||||||
|
|
||||||
|
int zoneD = ExamWordsConstant.getZoneD(gradeId);
|
||||||
|
int zoneDSize = ExamWordsConstant.ZONE_D_SIZE;
|
||||||
|
vocabularyBankDOS.addAll(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneD, zoneDSize));
|
||||||
|
|
||||||
|
int zoneE = ExamWordsConstant.getZoneE(gradeId);
|
||||||
|
int zoneESize = ExamWordsConstant.ZONE_E_SIZE;
|
||||||
|
vocabularyBankDOS.addAll(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneE, zoneESize));
|
||||||
|
|
||||||
|
int zoneF = ExamWordsConstant.getZoneF(gradeId);
|
||||||
|
int zoneFSize = ExamWordsConstant.ZONE_F_SIZE;
|
||||||
|
vocabularyBankDOS.addAll(vocabularyBankDOMapper.selectVocabularyBankListByGradeIdRandom(zoneF, zoneFSize));
|
||||||
|
|
||||||
ExamWordsDO examWordsDO = ExamWordsDO.builder()
|
ExamWordsDO examWordsDO = ExamWordsDO.builder()
|
||||||
.gradeId(gradeId)
|
.gradeId(gradeId)
|
||||||
.level(level)
|
.level(1)
|
||||||
.title(LocalDateTime.now() + "测试")
|
.type(ExamWordsConstant.EXAM_TYPE_BASELINE)
|
||||||
|
.title("摸低测试测试" + studentDO.getName())
|
||||||
.createdAt(LocalDateTime.now())
|
.createdAt(LocalDateTime.now())
|
||||||
.wordIds(vocabularyBankDOS.stream().map(VocabularyBankDO::getId).toList())
|
.wordIds(vocabularyBankDOS.stream().map(VocabularyBankDO::getId).toList())
|
||||||
.build();
|
.build();
|
||||||
@@ -66,7 +104,7 @@ public class ExamWordsServiceImpl implements ExamWordsService {
|
|||||||
throw new RuntimeException("插入考试失败");
|
throw new RuntimeException("插入考试失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
int insertStudentsExam = studentExamWordsDOMapper.insertStudentsExam(studentIds, examWordsDO.getId());
|
int insertStudentsExam = studentExamWordsDOMapper.insertStudentsExam(studentId, examWordsDO.getId());
|
||||||
if (insertStudentsExam <= 0) {
|
if (insertStudentsExam <= 0) {
|
||||||
throw new RuntimeException("插入学生关联考试失败");
|
throw new RuntimeException("插入学生关联考试失败");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
|
|||||||
StudentExamId studentExamId = PngUtil.analyzeExamWordsIdAndStudentId(ansSheetPath, tessdataPath, coordinatesXIES);
|
StudentExamId studentExamId = PngUtil.analyzeExamWordsIdAndStudentId(ansSheetPath, tessdataPath, coordinatesXIES);
|
||||||
Integer examWordsJudgeResultDOId = examWordsJudgeResultDO.getId();
|
Integer examWordsJudgeResultDOId = examWordsJudgeResultDO.getId();
|
||||||
if (studentExamId == null) {
|
if (studentExamId == null) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "未识别学生 id 和考试 id");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "未识别学生 id 和考试 id");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,18 +59,18 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
|
|||||||
Integer examWordsId = studentExamId.getExamId();
|
Integer examWordsId = studentExamId.getExamId();
|
||||||
StudentExamWordsDO studentExamWordsDO = studentExamWordsDOMapper.selectByStudentIdAndExamWordsId(studentId, examWordsId);
|
StudentExamWordsDO studentExamWordsDO = studentExamWordsDOMapper.selectByStudentIdAndExamWordsId(studentId, examWordsId);
|
||||||
if (studentExamWordsDO == null) {
|
if (studentExamWordsDO == null) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "未找到学生 id 和考试 id 对应的考试记录");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "未找到学生 id 和考试 id 对应的考试记录");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log.info("studentId:{},examWordsId:{}", studentId, examWordsId);
|
log.info("studentId:{},examWordsId:{}", studentId, examWordsId);
|
||||||
if (studentExamWordsDO.getIsCompleted() == 1) {
|
if (studentExamWordsDO.getIsCompleted() == 1) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "考试记录此前已识别");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "考试记录此前已识别");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExamWordsDO examWordsDO = examWordsDOMapper.selectById(examWordsId);
|
ExamWordsDO examWordsDO = examWordsDOMapper.selectById(examWordsId);
|
||||||
if(examWordsDO == null) {
|
if(examWordsDO == null) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "未找到考试");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "未找到考试");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
|
|||||||
.build();
|
.build();
|
||||||
int updated = examWordsJudgeResultDOMapper.updateExamWordsJudgeResultDO(wordsJudgeResultDO);
|
int updated = examWordsJudgeResultDOMapper.updateExamWordsJudgeResultDO(wordsJudgeResultDO);
|
||||||
if (updated != 1) {
|
if (updated != 1) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "更新考试记录失败");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "更新考试记录失败");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log.info("更新考试记录成功");
|
log.info("更新考试记录成功");
|
||||||
@@ -114,13 +114,13 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
|
|||||||
).toList());
|
).toList());
|
||||||
int batched = wordMasteryLogDOMapper.batchUpdateStudentMastery(wordMasteryLogDOS);
|
int batched = wordMasteryLogDOMapper.batchUpdateStudentMastery(wordMasteryLogDOS);
|
||||||
if (batched == 0) {
|
if (batched == 0) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "更新学生记忆力记录失败");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "更新学生记忆力记录失败");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int updateStudentExamWordsFinished = studentExamWordsDOMapper.updateStudentExamWordsFinished(studentId, examWordsId);
|
int updateStudentExamWordsFinished = studentExamWordsDOMapper.updateStudentExamWordsFinished(studentId, examWordsId);
|
||||||
if (updateStudentExamWordsFinished != 1) {
|
if (updateStudentExamWordsFinished != 1) {
|
||||||
examWordsJudgeResultDOMapper.updateErrorMsg(examWordsJudgeResultDOId, "更新学生考试为结束时失败");
|
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "更新学生考试为结束时失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean delete = new File(ansSheetPath).delete();
|
boolean delete = new File(ansSheetPath).delete();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.yinlihupo.enlish.service.utils;
|
|||||||
import com.yinlihupo.enlish.service.constant.ExamWordsConstant;
|
import com.yinlihupo.enlish.service.constant.ExamWordsConstant;
|
||||||
import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
|
import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
|
||||||
import com.yinlihupo.enlish.service.model.bo.StudentExamId;
|
import com.yinlihupo.enlish.service.model.bo.StudentExamId;
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sourceforge.tess4j.ITesseract;
|
import net.sourceforge.tess4j.ITesseract;
|
||||||
import net.sourceforge.tess4j.Tesseract;
|
import net.sourceforge.tess4j.Tesseract;
|
||||||
@@ -13,7 +12,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.opencv.core.*;
|
import org.opencv.core.*;
|
||||||
import org.opencv.imgcodecs.Imgcodecs;
|
import org.opencv.imgcodecs.Imgcodecs;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBufferByte;
|
import java.awt.image.DataBufferByte;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<result column="level" jdbcType="INTEGER" property="level" />
|
<result column="level" jdbcType="INTEGER" property="level" />
|
||||||
<result column="title" jdbcType="VARCHAR" property="title" />
|
<result column="title" jdbcType="VARCHAR" property="title" />
|
||||||
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
||||||
|
<result column="type" jdbcType="INTEGER" property="type" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO">
|
||||||
<result column="word_ids" jdbcType="LONGVARCHAR" property="wordIds" typeHandler="com.yinlihupo.enlish.service.config.ListWordIdTypeHandler" />
|
<result column="word_ids" jdbcType="LONGVARCHAR" property="wordIds" typeHandler="com.yinlihupo.enlish.service.config.ListWordIdTypeHandler" />
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
<result column="wrong_word_count" jdbcType="INTEGER" property="wrongWordCount" />
|
<result column="wrong_word_count" jdbcType="INTEGER" property="wrongWordCount" />
|
||||||
<result column="is_finished" jdbcType="INTEGER" property="isFinished" />
|
<result column="is_finished" jdbcType="INTEGER" property="isFinished" />
|
||||||
<result column="start_date" jdbcType="TIMESTAMP" property="startDate" />
|
<result column="start_date" jdbcType="TIMESTAMP" property="startDate" />
|
||||||
<result column="error_msg" jdbcType="VARCHAR" property="errorMsg" />
|
<result column="msg" jdbcType="VARCHAR" property="msg" />
|
||||||
|
<result column="ans_grade_id" jdbcType="INTEGER" property="ansGradeId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO">
|
||||||
@@ -31,9 +32,9 @@
|
|||||||
limit #{count}
|
limit #{count}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<update id="updateErrorMsg">
|
<update id="updateMsg">
|
||||||
update exam_words_judge_result
|
update exam_words_judge_result
|
||||||
set error_msg = #{errorMsg}
|
set msg = #{msg}
|
||||||
and is_finished = 2
|
and is_finished = 2
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|||||||
@@ -13,9 +13,7 @@
|
|||||||
insert into student_exam_words
|
insert into student_exam_words
|
||||||
(student_id, exam_words_id, is_completed, start_data)
|
(student_id, exam_words_id, is_completed, start_data)
|
||||||
values
|
values
|
||||||
<foreach collection="studentIds" item="studentId" separator=",">
|
|
||||||
(#{studentId}, #{examWordsId}, 0, now())
|
(#{studentId}, #{examWordsId}, 0, now())
|
||||||
</foreach>
|
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<select id="selectByStudentIdAndExamWordsId" resultMap="BaseResultMap">
|
<select id="selectByStudentIdAndExamWordsId" resultMap="BaseResultMap">
|
||||||
|
|||||||
@@ -122,4 +122,16 @@
|
|||||||
from vocabulary_bank
|
from vocabulary_bank
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectVocabularyBankListByGradeIdRandom" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from vocabulary_bank
|
||||||
|
where unit_id in (
|
||||||
|
select unit_id
|
||||||
|
from grade_unit
|
||||||
|
where grade_id = #{gradeId}
|
||||||
|
)
|
||||||
|
order by rand()
|
||||||
|
limit #{wordCount}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
Binary file not shown.
@@ -1,7 +1,9 @@
|
|||||||
package com.yinlihupo.enlish.service.mapper;
|
package com.yinlihupo.enlish.service.mapper;
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.GradeUnitDO;
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.UnitDO;
|
import com.yinlihupo.enlish.service.domain.dataobject.UnitDO;
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.GradeUnitDOMapper;
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.UnitDOMapper;
|
import com.yinlihupo.enlish.service.domain.mapper.UnitDOMapper;
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.WordMasteryLogDOMapper;
|
import com.yinlihupo.enlish.service.domain.mapper.WordMasteryLogDOMapper;
|
||||||
@@ -29,11 +31,13 @@ public class TestVocabularyBankInsert {
|
|||||||
private UnitDOMapper unitDOMapper;
|
private UnitDOMapper unitDOMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private WordMasteryLogDOMapper wordMasteryLogDOMapper;
|
private WordMasteryLogDOMapper wordMasteryLogDOMapper;
|
||||||
|
@Resource
|
||||||
|
private GradeUnitDOMapper gradeUnitDOMapper;
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
String file = "C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\test\\java\\com\\yinlihupo\\enlish\\service\\mapper\\min.xlsx";
|
String file = "C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\test\\java\\com\\yinlihupo\\enlish\\service\\mapper\\3上.xlsx";
|
||||||
HashMap<String, Integer> map = new HashMap<>();
|
HashMap<String, Integer> map = new HashMap<>();
|
||||||
|
int gradeId = 3;
|
||||||
try (FileInputStream fis = new FileInputStream(file); Workbook workbook = new XSSFWorkbook(fis)) {
|
try (FileInputStream fis = new FileInputStream(file); Workbook workbook = new XSSFWorkbook(fis)) {
|
||||||
|
|
||||||
Sheet sheet = workbook.getSheetAt(0);
|
Sheet sheet = workbook.getSheetAt(0);
|
||||||
@@ -44,10 +48,14 @@ public class TestVocabularyBankInsert {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String gradeUnit = row.getCell(0).getStringCellValue();
|
|
||||||
String word = row.getCell(1).getStringCellValue();
|
String word = row.getCell(0).getStringCellValue();
|
||||||
String phonetic = row.getCell(2) != null ? row.getCell(2).getStringCellValue() : "";
|
String meaning = row.getCell(1) != null ? row.getCell(1).getStringCellValue() : "";
|
||||||
String meaning = row.getCell(3) != null ? row.getCell(3).getStringCellValue() : "";
|
String gradeUnit = row.getCell(2) != null ? row.getCell(2).getStringCellValue() : "";
|
||||||
|
|
||||||
|
if (word.contains("Unit")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int gradeUnitId = 0;
|
int gradeUnitId = 0;
|
||||||
if (map.containsKey(gradeUnit)) {
|
if (map.containsKey(gradeUnit)) {
|
||||||
@@ -61,6 +69,7 @@ public class TestVocabularyBankInsert {
|
|||||||
.createAt(LocalDateTime.now())
|
.createAt(LocalDateTime.now())
|
||||||
.build();
|
.build();
|
||||||
unitDOMapper.insert(unitDO);
|
unitDOMapper.insert(unitDO);
|
||||||
|
gradeUnitDOMapper.insert(GradeUnitDO.builder().unitId(unitDO.getId()).gradeId(gradeId).build());
|
||||||
gradeUnitId = unitDO.getId();
|
gradeUnitId = unitDO.getId();
|
||||||
} else {
|
} else {
|
||||||
gradeUnitId = unitDO.getId();
|
gradeUnitId = unitDO.getId();
|
||||||
@@ -71,7 +80,7 @@ public class TestVocabularyBankInsert {
|
|||||||
VocabularyBankDO vocabularyBankDO = VocabularyBankDO.builder()
|
VocabularyBankDO vocabularyBankDO = VocabularyBankDO.builder()
|
||||||
.word(word)
|
.word(word)
|
||||||
.definition(meaning)
|
.definition(meaning)
|
||||||
.pronunciation(phonetic)
|
.pronunciation("")
|
||||||
.unitId(gradeUnitId)
|
.unitId(gradeUnitId)
|
||||||
.build();
|
.build();
|
||||||
vocabularyBankMapper.insertSelective(vocabularyBankDO);
|
vocabularyBankMapper.insertSelective(vocabularyBankDO);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class ExamTest {
|
|||||||
private VocabularyService vocabularyService;
|
private VocabularyService vocabularyService;
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
ExamWordsDO examWordsDO = examWordsService.generateExamWords(5, 0, List.of(1));
|
ExamWordsDO examWordsDO = examWordsService.generateExamWords(5, 0, 1, 0);
|
||||||
log.info("{}", examWordsDO);
|
log.info("{}", examWordsDO);
|
||||||
List<VocabularyBankDO> vocabularyBankDOS = vocabularyService.findVocabularyBankDOListById(examWordsDO.getWordIds());
|
List<VocabularyBankDO> vocabularyBankDOS = vocabularyService.findVocabularyBankDOListById(examWordsDO.getWordIds());
|
||||||
List<Word> assessmentWords = vocabularyBankDOS.stream().map(vocabularyBankDO -> Word.builder()
|
List<Word> assessmentWords = vocabularyBankDOS.stream().map(vocabularyBankDO -> Word.builder()
|
||||||
|
|||||||
@@ -14,6 +14,12 @@
|
|||||||
<el-option :label="'三级'" :value="3" />
|
<el-option :label="'三级'" :value="3" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="类型">
|
||||||
|
<el-select v-model="type" placeholder="请选择类型" style="width: 240px">
|
||||||
|
<el-option :label="'摸底'" :value="1" />
|
||||||
|
<el-option :label="'期中|期末'" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="text-sm text-gray-500">
|
<div class="text-sm text-gray-500">
|
||||||
已选学生数量:{{ studentIds.length }}
|
已选学生数量:{{ studentIds.length }}
|
||||||
@@ -22,7 +28,7 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="flex justify-end gap-2">
|
<div class="flex justify-end gap-2">
|
||||||
<el-button @click="visible = false">取消</el-button>
|
<el-button @click="visible = false">取消</el-button>
|
||||||
<el-button type="primary" :disabled="!gradeId || !level" @click="handleGenerate">生成并下载</el-button>
|
<el-button type="primary" :disabled="!gradeId || !level || !type" @click="handleGenerate">生成并下载</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -49,7 +55,7 @@ const loading = ref(false)
|
|||||||
const gradeOptions = ref([])
|
const gradeOptions = ref([])
|
||||||
const gradeId = ref(null)
|
const gradeId = ref(null)
|
||||||
const level = ref(null)
|
const level = ref(null)
|
||||||
|
const type = ref(null)
|
||||||
async function fetchGrades() {
|
async function fetchGrades() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
@@ -65,11 +71,12 @@ async function fetchGrades() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleGenerate() {
|
async function handleGenerate() {
|
||||||
if (!gradeId.value || !level.value || props.studentIds.length === 0) return
|
if (!gradeId.value || !level.value || !type.value || props.studentIds.length === 0) return
|
||||||
await generateExamWords({
|
await generateExamWords({
|
||||||
gradeId: Number(gradeId.value),
|
gradeId: Number(gradeId.value),
|
||||||
level: Number(level.value),
|
level: Number(level.value),
|
||||||
studentIds: props.studentIds
|
type: Number(type.value),
|
||||||
|
studentId: props.studentIds[0]
|
||||||
})
|
})
|
||||||
ElMessage.success('生成任务已提交,正在下载')
|
ElMessage.success('生成任务已提交,正在下载')
|
||||||
visible.value = false
|
visible.value = false
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
selectedGradeId }})</el-tag>
|
selectedGradeId }})</el-tag>
|
||||||
<el-button type="primary" @click="fetchStudents">查询</el-button>
|
<el-button type="primary" @click="fetchStudents">查询</el-button>
|
||||||
<el-button @click="resetStudentFilters">重置</el-button>
|
<el-button @click="resetStudentFilters">重置</el-button>
|
||||||
<el-button type="success" :disabled="selectedStudentIds.length === 0"
|
<el-button type="success" :disabled="selectedStudentIds.length !== 1"
|
||||||
@click="showGenerateDialog = true">
|
@click="showGenerateDialog = true">
|
||||||
生成试题
|
生成试题
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|||||||
Reference in New Issue
Block a user