refactor(exam): 重构摸底测试为考试词汇模块
- 删除原 Assessment 相关的实体、Mapper、Service 接口及实现和 Controller - 重命名常量类 AssessmentConstant 为 ExamWordsConstant 并调整相关常量值 - 新增 ExamWordsController 替代 AssessmentController,使用新模板生成试卷 - 新增 ExamWordsService 及其实现,实现按年级、等级和学生列表生成考试词汇 - 新增 ListWordIdTypeHandler 处理 List<Integer> 与数据库间的 JSON 转换 - 调整 PngUtil 中常量引用改为 ExamWordsConstant - 修改配置文件新增模板路径及临时目录设置 - 新增单元测试 ExamTest 验证考试词汇生成及文档导出功能 - 修改生成配置文件,支持 student_exam_words 表的数据操作 - 清理未使用的 Assessment 相关代码,精简项目结构
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
package com.yinlihupo.enlish.service.config;
|
||||||
|
|
||||||
|
import com.yinlihupo.framework.common.util.JsonUtils;
|
||||||
|
import org.apache.ibatis.type.BaseTypeHandler;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ListWordIdTypeHandler extends BaseTypeHandler<List<Integer>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNonNullParameter(PreparedStatement ps, int i, List<Integer> parameter, JdbcType jdbcType) throws SQLException {
|
||||||
|
try {
|
||||||
|
String json = JsonUtils.toJsonString(parameter);
|
||||||
|
ps.setString(i, json);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SQLException("转换List<Word>为JSON字符串失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取结果(从ResultSet中按列名获取):将JSON字符串转换为List<Word>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||||
|
return parseJson(rs.getString(columnName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取结果(从ResultSet中按列索引获取)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||||
|
return parseJson(rs.getString(columnIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取结果(从CallableStatement中获取)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||||
|
return parseJson(cs.getString(columnIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> parseJson(String json) {
|
||||||
|
if (json == null || json.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JsonUtils.parseList(json, Integer.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("转换JSON字符串为List<Word>失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.yinlihupo.enlish.service.constant;
|
package com.yinlihupo.enlish.service.constant;
|
||||||
|
|
||||||
public interface AssessmentConstant {
|
public interface ExamWordsConstant {
|
||||||
|
|
||||||
int PGN_COL = 53;
|
int PGN_COL = 53;
|
||||||
// 文件暂存目录 linux
|
// 文件暂存目录 linux
|
||||||
String ASSESSMENT_FELT = "enlish/assessment/";
|
String ASSESSMENT_FELT = "enlish/exam_words/";
|
||||||
}
|
}
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.controller;
|
|
||||||
|
|
||||||
|
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
|
||||||
import com.deepoove.poi.config.Configure;
|
|
||||||
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
|
||||||
import com.yinlihupo.enlish.service.constant.AssessmentConstant;
|
|
||||||
import com.yinlihupo.enlish.service.enums.AssessmentsType;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
import com.yinlihupo.enlish.service.model.vo.assessment.AssessmentStudentReqVO;
|
|
||||||
import com.yinlihupo.enlish.service.service.AssessmentService;
|
|
||||||
import com.yinlihupo.enlish.service.utils.PngUtil;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequestMapping("/assessment/")
|
|
||||||
@RestController
|
|
||||||
@Slf4j
|
|
||||||
public class AssessmentController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AssessmentService assessmentService;
|
|
||||||
|
|
||||||
@PatchMapping("felt")
|
|
||||||
public void generateAssessmentDocxStudent(@RequestBody AssessmentStudentReqVO assessmentStudentReqVO, HttpServletResponse response) {
|
|
||||||
Integer studentId = assessmentStudentReqVO.getStudentId();
|
|
||||||
HashMap<Integer, Integer> unitIdAndWordCount = assessmentStudentReqVO.getUnitIdAndWordCount();
|
|
||||||
|
|
||||||
int assessmentDocxId = assessmentService.getAssessmentDocxId(studentId, AssessmentsType.ASSESSMENT_FELT);
|
|
||||||
List<Word> assessmentWords;
|
|
||||||
if (assessmentDocxId == 0) {
|
|
||||||
assessmentWords = assessmentService.genAssessmentWords(studentId, unitIdAndWordCount);
|
|
||||||
assessmentDocxId = assessmentService.getAssessmentDocxId(studentId, AssessmentsType.ASSESSMENT_FELT);
|
|
||||||
} else {
|
|
||||||
assessmentWords = assessmentService.getAssessmentWordsById(assessmentDocxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
|
||||||
Configure config = Configure.builder()
|
|
||||||
.bind("words", policy)
|
|
||||||
.bind("answer", policy)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
|
||||||
data.put("assessment_id", assessmentDocxId);
|
|
||||||
data.put("words", assessmentWords);
|
|
||||||
data.put("answer", assessmentWords);
|
|
||||||
|
|
||||||
// 4. 渲染并输出
|
|
||||||
try (XWPFTemplate template = XWPFTemplate.compile("C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\main\\resources\\templates\\assessment_v3.docx", config)) {
|
|
||||||
template.render(data);
|
|
||||||
String fileName = URLEncoder.encode( assessmentDocxId + "摸底测试.docx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
|
||||||
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
|
|
||||||
|
|
||||||
OutputStream out = response.getOutputStream();
|
|
||||||
template.write(out);
|
|
||||||
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("analyze")
|
|
||||||
public void generateAssessmentDocxAnalyze(@RequestParam("file") MultipartFile file, @RequestParam("id") Integer assessmentId) {
|
|
||||||
// 把文件暂存在本地
|
|
||||||
String filePath = AssessmentConstant.ASSESSMENT_FELT + assessmentId + ".png";
|
|
||||||
try {
|
|
||||||
file.transferTo(new File(filePath));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CoordinatesXY> coordinatesXIES = PngUtil.analysisXY(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package com.yinlihupo.enlish.service.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
|
import com.deepoove.poi.config.Configure;
|
||||||
|
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
import com.yinlihupo.enlish.service.model.bo.Word;
|
||||||
|
import com.yinlihupo.enlish.service.model.vo.exam.GenerateExamWordsReqVO;
|
||||||
|
import com.yinlihupo.enlish.service.service.ExamWordsService;
|
||||||
|
import com.yinlihupo.enlish.service.service.VocabularyService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequestMapping("/exam/words/")
|
||||||
|
@RestController
|
||||||
|
@Slf4j
|
||||||
|
public class ExamWordsController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExamWordsService examWordsService;
|
||||||
|
@Resource
|
||||||
|
private VocabularyService vocabularyService;
|
||||||
|
@Value("${templates.word}")
|
||||||
|
private String templateWordPath;
|
||||||
|
|
||||||
|
@PostMapping("submit")
|
||||||
|
public void generateFeltExamWords(@RequestBody GenerateExamWordsReqVO generateExamWordsReqVO, HttpServletResponse response) {
|
||||||
|
Integer gradeId = generateExamWordsReqVO.getGradeId();
|
||||||
|
Integer level = generateExamWordsReqVO.getLevel();
|
||||||
|
List<Integer> studentIds = generateExamWordsReqVO.getStudentIds();
|
||||||
|
if (studentIds == null || studentIds.isEmpty() || gradeId == null || level == null) {
|
||||||
|
throw new RuntimeException("参数错误");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ExamWordsDO examWordsDO = examWordsService.generateExamWords(gradeId, level, studentIds);
|
||||||
|
List<VocabularyBankDO> vocabularyBankDOS = vocabularyService.findVocabularyBankDOListById(examWordsDO.getWordIds());
|
||||||
|
|
||||||
|
List<Word> assessmentWords = vocabularyBankDOS.stream().map(vocabularyBankDO -> Word.builder()
|
||||||
|
.id(vocabularyBankDO.getId())
|
||||||
|
.title(vocabularyBankDO.getWord())
|
||||||
|
.definition(vocabularyBankDO.getDefinition())
|
||||||
|
.build()).toList();
|
||||||
|
|
||||||
|
// 配置 POI-TL
|
||||||
|
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
||||||
|
Configure config = Configure.builder()
|
||||||
|
.bind("words", policy)
|
||||||
|
.bind("answer", policy)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("assessment_id", examWordsDO.getId());
|
||||||
|
data.put("words", assessmentWords);
|
||||||
|
data.put("answer", assessmentWords);
|
||||||
|
|
||||||
|
// 2. 设置文件名编码
|
||||||
|
String fileName = URLEncoder.encode(examWordsDO.getId() + "摸底测试.docx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
||||||
|
|
||||||
|
// 3. 设置响应头
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
|
||||||
|
|
||||||
|
try (InputStream inputStream = new FileInputStream(this.templateWordPath);
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(inputStream, config);
|
||||||
|
OutputStream out = response.getOutputStream()) {
|
||||||
|
|
||||||
|
template.render(data);
|
||||||
|
template.write(out);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
if (!response.isCommitted()) {
|
||||||
|
response.reset();
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
throw new RuntimeException("生成试卷失败: " + e.getMessage());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("生成试卷导出中断", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,28 +5,24 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.util.List;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
public class AssessmentsDO {
|
public class ExamWordsDO {
|
||||||
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
private Integer studentId;
|
private Integer gradeId;
|
||||||
|
|
||||||
private LocalDateTime testDate;
|
|
||||||
|
|
||||||
private Integer testType;
|
|
||||||
|
|
||||||
private Integer level;
|
private Integer level;
|
||||||
|
|
||||||
private Integer estimatedVocabSize;
|
private String title;
|
||||||
|
|
||||||
private String contentDetailsJson;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
private List<Integer> wordIds;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.yinlihupo.enlish.service.domain.dataobject;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class GradeUnitDO {
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer gradeId;
|
||||||
|
|
||||||
|
private Integer unitId;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.yinlihupo.enlish.service.domain.dataobject;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class StudentExamWordsDO {
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer studentId;
|
||||||
|
|
||||||
|
private Integer examWordsId;
|
||||||
|
|
||||||
|
private Integer isCompleted;
|
||||||
|
|
||||||
|
private Date startData;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.domain.mapper;
|
|
||||||
|
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
public interface AssessmentsDOMapper {
|
|
||||||
int deleteByPrimaryKey(Integer id);
|
|
||||||
|
|
||||||
int insert(AssessmentsDO record);
|
|
||||||
|
|
||||||
int insertSelective(AssessmentsDO record);
|
|
||||||
|
|
||||||
AssessmentsDO selectByPrimaryKey(Integer id);
|
|
||||||
|
|
||||||
int updateByPrimaryKeySelective(AssessmentsDO record);
|
|
||||||
|
|
||||||
int updateByPrimaryKeyWithBLOBs(AssessmentsDO record);
|
|
||||||
|
|
||||||
int updateByPrimaryKey(AssessmentsDO record);
|
|
||||||
|
|
||||||
Integer selectAssessmentsIdByStudentIdAndTestType(@Param("studentId") Integer studentId, @Param("testType") Integer testType);
|
|
||||||
|
|
||||||
String selectContentDetailsJsonByAssessmentsId(@Param("assessmentsId") Integer assessmentsId);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.yinlihupo.enlish.service.domain.mapper;
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
|
|
||||||
|
public interface ExamWordsDOMapper {
|
||||||
|
|
||||||
|
int insert(ExamWordsDO record);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.yinlihupo.enlish.service.domain.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface GradeUnitDOMapper {
|
||||||
|
|
||||||
|
List<Integer> selectUnitIdsByGradeId(@Param("gradeId") Integer gradeId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.yinlihupo.enlish.service.domain.mapper;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface StudentExamWordsDOMapper {
|
||||||
|
|
||||||
|
int insertStudentsExam(@Param("studentIds") List<Integer> studentIds, @Param("examWordsId") Integer examWordsId);
|
||||||
|
}
|
||||||
@@ -6,17 +6,10 @@ import org.apache.ibatis.annotations.Param;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface VocabularyBankDOMapper {
|
public interface VocabularyBankDOMapper {
|
||||||
int deleteByPrimaryKey(Integer id);
|
|
||||||
|
|
||||||
int insert(VocabularyBankDO record);
|
|
||||||
|
|
||||||
int insertSelective(VocabularyBankDO record);
|
int insertSelective(VocabularyBankDO record);
|
||||||
|
|
||||||
VocabularyBankDO selectByPrimaryKey(Integer id);
|
|
||||||
|
|
||||||
int updateByPrimaryKeySelective(VocabularyBankDO record);
|
|
||||||
|
|
||||||
int updateByPrimaryKey(VocabularyBankDO record);
|
|
||||||
|
|
||||||
List<VocabularyBankDO> selectVocabularyBankDOListByUnitId(@Param("unitId") Integer unitId, @Param("wordCount") Integer wordCount);
|
List<VocabularyBankDO> selectVocabularyBankDOListByUnitId(@Param("unitId") Integer unitId, @Param("wordCount") Integer wordCount);
|
||||||
|
|
||||||
|
List<VocabularyBankDO> selectVocabularyBankDOListByIds(@Param("ids") List<Integer> ids);
|
||||||
}
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.model.vo.assessment;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
// 进行摸底测试
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class AssessmentStudentReqVO {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 学生 id
|
|
||||||
*/
|
|
||||||
private Integer studentId;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单元 id 和词数
|
|
||||||
*/
|
|
||||||
private HashMap<Integer, Integer> unitIdAndWordCount;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.yinlihupo.enlish.service.model.vo.exam;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class GenerateExamWordsReqVO {
|
||||||
|
|
||||||
|
private Integer gradeId;
|
||||||
|
private Integer level;
|
||||||
|
private List<Integer> studentIds;
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.service;
|
|
||||||
|
|
||||||
|
|
||||||
import com.yinlihupo.enlish.service.enums.AssessmentsType;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface AssessmentService {
|
|
||||||
|
|
||||||
List<Word> genAssessmentWords(Integer studentId, HashMap<Integer, Integer> unitIdAndWordCount);
|
|
||||||
|
|
||||||
Integer getAssessmentDocxId(Integer studentId, AssessmentsType assessmentsType);
|
|
||||||
|
|
||||||
List<Word> getAssessmentWordsById(Integer id);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.yinlihupo.enlish.service.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ExamWordsService {
|
||||||
|
|
||||||
|
ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.yinlihupo.enlish.service.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface VocabularyService {
|
||||||
|
|
||||||
|
List<VocabularyBankDO> findVocabularyBankDOListById(List<Integer> ids);
|
||||||
|
}
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.service.assessment;
|
|
||||||
|
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO;
|
|
||||||
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.AssessmentsDOMapper;
|
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
|
||||||
import com.yinlihupo.enlish.service.domain.mapper.WordMasteryLogDOMapper;
|
|
||||||
import com.yinlihupo.enlish.service.enums.AssessmentsType;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
import com.yinlihupo.enlish.service.service.AssessmentService;
|
|
||||||
import com.yinlihupo.framework.common.util.JsonUtils;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class AssessmentServiceImpl implements AssessmentService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private VocabularyBankDOMapper vocabularyBankDOMapper;
|
|
||||||
@Resource
|
|
||||||
private WordMasteryLogDOMapper wordMasteryLogDOMapper;
|
|
||||||
@Resource
|
|
||||||
private AssessmentsDOMapper assessmentsDOMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Word> genAssessmentWords(Integer studentId, HashMap<Integer, Integer> unitIdAndWordCount) {
|
|
||||||
|
|
||||||
List<Word> words = new ArrayList<>();
|
|
||||||
for (Map.Entry<Integer, Integer> entry : unitIdAndWordCount.entrySet()) {
|
|
||||||
Integer unitId = entry.getKey();
|
|
||||||
Integer wordCount = entry.getValue();
|
|
||||||
|
|
||||||
List<VocabularyBankDO> vocabularyBankDOS = vocabularyBankDOMapper.selectVocabularyBankDOListByUnitId(unitId, wordCount);
|
|
||||||
words.addAll(
|
|
||||||
vocabularyBankDOS.stream()
|
|
||||||
.map(vocabularyBankDO -> Word.builder()
|
|
||||||
.id(vocabularyBankDO.getId())
|
|
||||||
.title(vocabularyBankDO.getWord())
|
|
||||||
.definition(vocabularyBankDO.getDefinition())
|
|
||||||
.build())
|
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
assessmentsDOMapper.insertSelective(
|
|
||||||
AssessmentsDO.builder()
|
|
||||||
.studentId(studentId)
|
|
||||||
.level(0)
|
|
||||||
.testType(AssessmentsType.ASSESSMENT_FELT.getId())
|
|
||||||
.testDate(LocalDateTime.now())
|
|
||||||
.estimatedVocabSize(0)
|
|
||||||
.contentDetailsJson(JsonUtils.toJsonString(words))
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
return words;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer getAssessmentDocxId(Integer studentId, AssessmentsType assessmentsType) {
|
|
||||||
return assessmentsDOMapper.selectAssessmentsIdByStudentIdAndTestType(studentId, assessmentsType.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Word> getAssessmentWordsById(Integer id) {
|
|
||||||
String contentJson = assessmentsDOMapper.selectContentDetailsJsonByAssessmentsId(id);
|
|
||||||
try {
|
|
||||||
return JsonUtils.parseList(contentJson, Word.class);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.yinlihupo.enlish.service.service.exam;
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.ExamWordsDOMapper;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.GradeUnitDOMapper;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.StudentExamWordsDOMapper;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
||||||
|
import com.yinlihupo.enlish.service.service.ExamWordsService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class ExamWordsServiceImpl implements ExamWordsService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private GradeUnitDOMapper gradeUnitDOMapper;
|
||||||
|
@Resource
|
||||||
|
private VocabularyBankDOMapper vocabularyBankDOMapper;
|
||||||
|
@Value("${templates.count}")
|
||||||
|
private Integer wordCount;
|
||||||
|
@Resource
|
||||||
|
private ExamWordsDOMapper examWordsDOMapper;
|
||||||
|
@Resource
|
||||||
|
private StudentExamWordsDOMapper studentExamWordsDOMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
public ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds) {
|
||||||
|
|
||||||
|
List<Integer> unitIds = gradeUnitDOMapper.selectUnitIdsByGradeId(gradeId);
|
||||||
|
List<VocabularyBankDO> vocabularyBankDOS = new ArrayList<>();
|
||||||
|
int count = wordCount;
|
||||||
|
for (Integer unitId : unitIds) {
|
||||||
|
List<VocabularyBankDO> words = vocabularyBankDOMapper.selectVocabularyBankDOListByUnitId(unitId, 20);
|
||||||
|
vocabularyBankDOS.addAll(words);
|
||||||
|
count -= 20;
|
||||||
|
if (count <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExamWordsDO examWordsDO = ExamWordsDO.builder()
|
||||||
|
.gradeId(gradeId)
|
||||||
|
.level(level)
|
||||||
|
.title("测试")
|
||||||
|
.createdAt(LocalDateTime.now())
|
||||||
|
.wordIds(vocabularyBankDOS.stream().map(VocabularyBankDO::getId).toList())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
int insert = examWordsDOMapper.insert(examWordsDO);
|
||||||
|
if (insert <= 0) {
|
||||||
|
throw new RuntimeException("插入考试失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
int insertStudentsExam = studentExamWordsDOMapper.insertStudentsExam(studentIds, examWordsDO.getId());
|
||||||
|
if (insertStudentsExam <= 0) {
|
||||||
|
throw new RuntimeException("插入学生关联考试失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return examWordsDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("analyze")
|
||||||
|
public void generateAssessmentDocxAnalyze(@RequestParam("file") MultipartFile file, @RequestParam("id") Integer id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yinlihupo.enlish.service.service.vocabulary;
|
||||||
|
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
||||||
|
import com.yinlihupo.enlish.service.service.VocabularyService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class VocabularyServiceImpl implements VocabularyService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private VocabularyBankDOMapper vocabularyBankDOMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VocabularyBankDO> findVocabularyBankDOListById(List<Integer> ids) {
|
||||||
|
return vocabularyBankDOMapper.selectVocabularyBankDOListByIds(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.yinlihupo.enlish.service.utils;
|
package com.yinlihupo.enlish.service.utils;
|
||||||
|
|
||||||
import com.yinlihupo.enlish.service.constant.AssessmentConstant;
|
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.Word;
|
import com.yinlihupo.enlish.service.model.bo.Word;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -91,7 +91,7 @@ public class PngUtil {
|
|||||||
|
|
||||||
// 获取每一列的宽度
|
// 获取每一列的宽度
|
||||||
list.sort(Comparator.comparingInt(CoordinatesXY::getHeight));
|
list.sort(Comparator.comparingInt(CoordinatesXY::getHeight));
|
||||||
int height = list.get(list.size() - 1).getHeight() / AssessmentConstant.PGN_COL;
|
int height = list.get(list.size() - 1).getHeight() / ExamWordsConstant.PGN_COL;
|
||||||
|
|
||||||
// 删除两列答题卡区块
|
// 删除两列答题卡区块
|
||||||
list.sort(Comparator.comparingInt(CoordinatesXY::getWidth));
|
list.sort(Comparator.comparingInt(CoordinatesXY::getWidth));
|
||||||
@@ -139,7 +139,7 @@ public class PngUtil {
|
|||||||
int currentX = coordinatesXY.getX();
|
int currentX = coordinatesXY.getX();
|
||||||
int currentY = coordinatesXY.getY();
|
int currentY = coordinatesXY.getY();
|
||||||
|
|
||||||
int count = i == 0 ? AssessmentConstant.PGN_COL - 1 : AssessmentConstant.PGN_COL;
|
int count = i == 0 ? ExamWordsConstant.PGN_COL - 1 : ExamWordsConstant.PGN_COL;
|
||||||
|
|
||||||
// 内层循环:遍历这一列的每一行
|
// 内层循环:遍历这一列的每一行
|
||||||
for (int j = 0; j < count; j++) {
|
for (int j = 0; j < count; j++) {
|
||||||
|
|||||||
@@ -19,3 +19,10 @@ spring:
|
|||||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||||
min-idle: 0 # 连接池中的最小空闲连接
|
min-idle: 0 # 连接池中的最小空闲连接
|
||||||
max-idle: 10 # 连接池中的最大空闲连接
|
max-idle: 10 # 连接池中的最大空闲连接
|
||||||
|
|
||||||
|
|
||||||
|
templates:
|
||||||
|
word: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\assessment_v5.docx
|
||||||
|
count: 100
|
||||||
|
tmp:
|
||||||
|
png: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\tmp\png
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
targetProject="src/main/java"/>
|
targetProject="src/main/java"/>
|
||||||
|
|
||||||
<!-- 需要生成的表-实体类 -->
|
<!-- 需要生成的表-实体类 -->
|
||||||
<table tableName="student" domainObjectName="StudentDO"
|
<table tableName="student_exam_words" domainObjectName="StudentExamWordsDO"
|
||||||
enableCountByExample="false"
|
enableCountByExample="false"
|
||||||
enableUpdateByExample="false"
|
enableUpdateByExample="false"
|
||||||
enableDeleteByExample="false"
|
enableDeleteByExample="false"
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.yinlihupo.enlish.service.domain.mapper.AssessmentsDOMapper">
|
|
||||||
<resultMap id="BaseResultMap" type="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
<id column="id" jdbcType="INTEGER" property="id" />
|
|
||||||
<result column="student_id" jdbcType="INTEGER" property="studentId" />
|
|
||||||
<result column="test_date" jdbcType="TIMESTAMP" property="testDate" />
|
|
||||||
<result column="test_type" jdbcType="INTEGER" property="testType" />
|
|
||||||
<result column="level" jdbcType="INTEGER" property="level" />
|
|
||||||
<result column="estimated_vocab_size" jdbcType="INTEGER" property="estimatedVocabSize" />
|
|
||||||
</resultMap>
|
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
<result column="content_details_json" jdbcType="LONGVARCHAR" property="contentDetailsJson" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<sql id="Base_Column_List">
|
|
||||||
id, student_id, test_date, test_type, level, estimated_vocab_size
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<sql id="Blob_Column_List">
|
|
||||||
content_details_json
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="ResultMapWithBLOBs">
|
|
||||||
select
|
|
||||||
<include refid="Base_Column_List" />
|
|
||||||
,
|
|
||||||
<include refid="Blob_Column_List" />
|
|
||||||
from assessments
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
|
|
||||||
delete from assessments
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</delete>
|
|
||||||
|
|
||||||
<insert id="insert" parameterType="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
insert into assessments (id, student_id, test_date,
|
|
||||||
test_type, level, estimated_vocab_size,
|
|
||||||
content_details_json)
|
|
||||||
values (#{id,jdbcType=INTEGER}, #{studentId,jdbcType=INTEGER}, #{testDate,jdbcType=TIMESTAMP},
|
|
||||||
#{testType,jdbcType=INTEGER}, #{level,jdbcType=INTEGER}, #{estimatedVocabSize,jdbcType=INTEGER},
|
|
||||||
#{contentDetailsJson,jdbcType=LONGVARCHAR})
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<insert id="insertSelective" parameterType="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
insert into assessments
|
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
|
||||||
<if test="id != null">
|
|
||||||
id,
|
|
||||||
</if>
|
|
||||||
<if test="studentId != null">
|
|
||||||
student_id,
|
|
||||||
</if>
|
|
||||||
<if test="testDate != null">
|
|
||||||
test_date,
|
|
||||||
</if>
|
|
||||||
<if test="testType != null">
|
|
||||||
test_type,
|
|
||||||
</if>
|
|
||||||
<if test="level != null">
|
|
||||||
level,
|
|
||||||
</if>
|
|
||||||
<if test="estimatedVocabSize != null">
|
|
||||||
estimated_vocab_size,
|
|
||||||
</if>
|
|
||||||
<if test="contentDetailsJson != null">
|
|
||||||
content_details_json,
|
|
||||||
</if>
|
|
||||||
</trim>
|
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
|
||||||
<if test="id != null">
|
|
||||||
#{id,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="studentId != null">
|
|
||||||
#{studentId,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="testDate != null">
|
|
||||||
#{testDate,jdbcType=TIMESTAMP},
|
|
||||||
</if>
|
|
||||||
<if test="testType != null">
|
|
||||||
#{testType,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="level != null">
|
|
||||||
#{level,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="estimatedVocabSize != null">
|
|
||||||
#{estimatedVocabSize,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="contentDetailsJson != null">
|
|
||||||
#{contentDetailsJson,jdbcType=LONGVARCHAR},
|
|
||||||
</if>
|
|
||||||
</trim>
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<update id="updateByPrimaryKeySelective" parameterType="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
update assessments
|
|
||||||
<set>
|
|
||||||
<if test="studentId != null">
|
|
||||||
student_id = #{studentId,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="testDate != null">
|
|
||||||
test_date = #{testDate,jdbcType=TIMESTAMP},
|
|
||||||
</if>
|
|
||||||
<if test="testType != null">
|
|
||||||
test_type = #{testType,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="level != null">
|
|
||||||
level = #{level,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="estimatedVocabSize != null">
|
|
||||||
estimated_vocab_size = #{estimatedVocabSize,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
<if test="contentDetailsJson != null">
|
|
||||||
content_details_json = #{contentDetailsJson,jdbcType=LONGVARCHAR},
|
|
||||||
</if>
|
|
||||||
</set>
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
update assessments
|
|
||||||
set student_id = #{studentId,jdbcType=INTEGER},
|
|
||||||
test_date = #{testDate,jdbcType=TIMESTAMP},
|
|
||||||
test_type = #{testType,jdbcType=INTEGER},
|
|
||||||
level = #{level,jdbcType=INTEGER},
|
|
||||||
estimated_vocab_size = #{estimatedVocabSize,jdbcType=INTEGER},
|
|
||||||
content_details_json = #{contentDetailsJson,jdbcType=LONGVARCHAR}
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateByPrimaryKey" parameterType="com.yinlihupo.enlish.service.domain.dataobject.AssessmentsDO">
|
|
||||||
update assessments
|
|
||||||
set student_id = #{studentId,jdbcType=INTEGER},
|
|
||||||
test_date = #{testDate,jdbcType=TIMESTAMP},
|
|
||||||
test_type = #{testType,jdbcType=INTEGER},
|
|
||||||
level = #{level,jdbcType=INTEGER},
|
|
||||||
estimated_vocab_size = #{estimatedVocabSize,jdbcType=INTEGER}
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<select id="selectAssessmentsIdByStudentIdAndTestType">
|
|
||||||
select id
|
|
||||||
from assessments
|
|
||||||
where student_id = #{studentId,jdbcType=INTEGER}
|
|
||||||
and test_type = #{testType,jdbcType=INTEGER}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectContentDetailsJsonByAssessmentsId">
|
|
||||||
select content_details_json
|
|
||||||
from assessments
|
|
||||||
where id = #{assessmentsId,jdbcType=INTEGER}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.yinlihupo.enlish.service.domain.mapper.ExamWordsDOMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO">
|
||||||
|
<id column="id" jdbcType="INTEGER" property="id" />
|
||||||
|
<result column="grade_id" jdbcType="INTEGER" property="gradeId" />
|
||||||
|
<result column="level" jdbcType="INTEGER" property="level" />
|
||||||
|
<result column="title" jdbcType="VARCHAR" property="title" />
|
||||||
|
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
||||||
|
</resultMap>
|
||||||
|
<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" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into exam_words (grade_id, level, title, word_ids, created_at)
|
||||||
|
VALUES (#{gradeId}, #{level}, #{title}, #{wordIds, typeHandler=com.yinlihupo.enlish.service.config.ListWordIdTypeHandler}, #{createdAt})
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.yinlihupo.enlish.service.domain.mapper.GradeUnitDOMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.yinlihupo.enlish.service.domain.dataobject.GradeUnitDO">
|
||||||
|
<id column="id" jdbcType="INTEGER" property="id" />
|
||||||
|
<result column="grade_id" jdbcType="INTEGER" property="gradeId" />
|
||||||
|
<result column="unit_id" jdbcType="INTEGER" property="unitId" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="selectUnitIdsByGradeId" resultType="java.lang.Integer">
|
||||||
|
select unit_id
|
||||||
|
from grade_unit
|
||||||
|
where grade_id = #{gradeId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.yinlihupo.enlish.service.domain.mapper.StudentExamWordsDOMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.yinlihupo.enlish.service.domain.dataobject.StudentExamWordsDO">
|
||||||
|
<id column="id" jdbcType="INTEGER" property="id" />
|
||||||
|
<result column="student_id" jdbcType="INTEGER" property="studentId" />
|
||||||
|
<result column="exam_words_id" jdbcType="INTEGER" property="examWordsId" />
|
||||||
|
<result column="is_completed" jdbcType="INTEGER" property="isCompleted" />
|
||||||
|
<result column="start_data" jdbcType="TIMESTAMP" property="startData" />
|
||||||
|
</resultMap>
|
||||||
|
<insert id="insertStudentsExam">
|
||||||
|
insert into student_exam_words
|
||||||
|
(student_id, exam_words_id, is_completed, start_data)
|
||||||
|
values
|
||||||
|
<foreach collection="studentIds" item="studentId" separator=",">
|
||||||
|
(#{studentId}, #{examWordsId}, 0, now())
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -9,27 +9,6 @@
|
|||||||
<result column="unit_id" jdbcType="INTEGER" property="unitId" />
|
<result column="unit_id" jdbcType="INTEGER" property="unitId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="Base_Column_List">
|
|
||||||
id, word, `definition`, pronunciation, unit_id
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
|
|
||||||
select
|
|
||||||
<include refid="Base_Column_List" />
|
|
||||||
from vocabulary_bank
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
|
|
||||||
delete from vocabulary_bank
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</delete>
|
|
||||||
|
|
||||||
<insert id="insert" parameterType="com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO">
|
|
||||||
insert into vocabulary_bank (id, word, `definition`, pronunciation, unit_id)
|
|
||||||
values (#{id,jdbcType=INTEGER}, #{word,jdbcType=VARCHAR}, #{definition,jdbcType=VARCHAR},
|
|
||||||
#{pronunciation,jdbcType=VARCHAR}, #{unitId,jdbcType=INTEGER})
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<insert id="insertSelective" parameterType="com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO">
|
<insert id="insertSelective" parameterType="com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO">
|
||||||
insert into vocabulary_bank
|
insert into vocabulary_bank
|
||||||
@@ -69,39 +48,19 @@
|
|||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="updateByPrimaryKeySelective" parameterType="com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO">
|
|
||||||
update vocabulary_bank
|
|
||||||
<set>
|
|
||||||
<if test="word != null">
|
|
||||||
word = #{word,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="definition != null">
|
|
||||||
`definition` = #{definition,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="pronunciation != null">
|
|
||||||
pronunciation = #{pronunciation,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="unitId != null">
|
|
||||||
unit_id = #{unitId,jdbcType=INTEGER},
|
|
||||||
</if>
|
|
||||||
</set>
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateByPrimaryKey" parameterType="com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO">
|
|
||||||
update vocabulary_bank
|
|
||||||
set word = #{word,jdbcType=VARCHAR},
|
|
||||||
`definition` = #{definition,jdbcType=VARCHAR},
|
|
||||||
pronunciation = #{pronunciation,jdbcType=VARCHAR},
|
|
||||||
unit_id = #{unitId,jdbcType=INTEGER}
|
|
||||||
where id = #{id,jdbcType=INTEGER}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<select id="selectVocabularyBankDOListByUnitId" resultMap="BaseResultMap">
|
<select id="selectVocabularyBankDOListByUnitId" resultMap="BaseResultMap">
|
||||||
select *
|
select *
|
||||||
from vocabulary_bank
|
from vocabulary_bank
|
||||||
where unit_id = #{unitId}
|
where unit_id = #{unitId}
|
||||||
limit #{wordCount}
|
limit #{wordCount}
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectVocabularyBankDOListByIds" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from vocabulary_bank
|
||||||
|
where id in
|
||||||
|
<foreach item="id" collection="ids" separator="," open="(" close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
BIN
enlish-service/src/main/resources/templates/assessment_v5.docx
Normal file
BIN
enlish-service/src/main/resources/templates/assessment_v5.docx
Normal file
Binary file not shown.
@@ -1,28 +1,20 @@
|
|||||||
package com.yinlihupo.enlish.service.omr;
|
package com.yinlihupo.enlish.service.omr;
|
||||||
|
|
||||||
import com.yinlihupo.enlish.service.enums.AssessmentsType;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
|
import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
import com.yinlihupo.enlish.service.service.AssessmentService;
|
|
||||||
import com.yinlihupo.enlish.service.utils.PngUtil;
|
import com.yinlihupo.enlish.service.utils.PngUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import nu.pattern.OpenCV;
|
import nu.pattern.OpenCV;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.opencv.core.*;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TestOmr {
|
public class TestOmr {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AssessmentService assessmentService;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOmr(){
|
public void testOmr(){
|
||||||
OpenCV.loadLocally();
|
OpenCV.loadLocally();
|
||||||
@@ -38,28 +30,7 @@ public class TestOmr {
|
|||||||
String path = "C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\main\\resources\\templates\\p3.png";
|
String path = "C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\main\\resources\\templates\\p3.png";
|
||||||
List<CoordinatesXY> coordinatesXIES = PngUtil.analysisXY(path);
|
List<CoordinatesXY> coordinatesXIES = PngUtil.analysisXY(path);
|
||||||
|
|
||||||
for (CoordinatesXY coordinatesXY : coordinatesXIES) {
|
|
||||||
log.info("坐标: {}", coordinatesXY);
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer studentId = 1;
|
|
||||||
HashMap<Integer, Integer> unitIdAndWordCount = new HashMap<>();
|
|
||||||
unitIdAndWordCount.put(142, 30);
|
|
||||||
unitIdAndWordCount.put(132, 40);
|
|
||||||
|
|
||||||
Integer assessmentDocxId = assessmentService.getAssessmentDocxId(studentId, AssessmentsType.ASSESSMENT_FELT);
|
|
||||||
List<Word> assessmentWords;
|
|
||||||
if (assessmentDocxId == null || assessmentDocxId == 0) {
|
|
||||||
assessmentWords = assessmentService.genAssessmentWords(studentId, unitIdAndWordCount);
|
|
||||||
} else {
|
|
||||||
assessmentWords = assessmentService.getAssessmentWordsById(assessmentDocxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Integer> integers = PngUtil.analyzePngForUnmemorizedWordIds(path, assessmentWords, coordinatesXIES);
|
|
||||||
|
|
||||||
for (Integer integer : integers) {
|
|
||||||
log.info("未背熟的单词ID: {}", integer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
package com.yinlihupo.enlish.service.service;
|
|
||||||
|
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
|
||||||
import com.deepoove.poi.config.Configure;
|
|
||||||
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
|
||||||
import com.yinlihupo.enlish.service.enums.AssessmentsType;
|
|
||||||
import com.yinlihupo.enlish.service.model.bo.Word;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
public class assessmentTest {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AssessmentService assessmentService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void generateAssessmentDocxStudent() {
|
|
||||||
|
|
||||||
Integer studentId = 1;
|
|
||||||
HashMap<Integer, Integer> unitIdAndWordCount = new HashMap<>();
|
|
||||||
unitIdAndWordCount.put(142, 30);
|
|
||||||
unitIdAndWordCount.put(132, 40);
|
|
||||||
|
|
||||||
Integer assessmentDocxId = assessmentService.getAssessmentDocxId(studentId, AssessmentsType.ASSESSMENT_FELT);
|
|
||||||
List<Word> assessmentWords;
|
|
||||||
if (assessmentDocxId == null || assessmentDocxId == 0) {
|
|
||||||
assessmentWords = assessmentService.genAssessmentWords(studentId, unitIdAndWordCount);
|
|
||||||
assessmentDocxId = assessmentService.getAssessmentDocxId(studentId, AssessmentsType.ASSESSMENT_FELT);
|
|
||||||
} else {
|
|
||||||
assessmentWords = assessmentService.getAssessmentWordsById(assessmentDocxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
|
||||||
Configure config = Configure.builder()
|
|
||||||
.bind("words", policy)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
|
||||||
data.put("assessment_id", assessmentDocxId);
|
|
||||||
data.put("words", assessmentWords);
|
|
||||||
|
|
||||||
// 4. 渲染并输出
|
|
||||||
try (XWPFTemplate template = XWPFTemplate.compile("C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\main\\resources\\templates\\assessment_v4.docx", config)) {
|
|
||||||
template.render(data);
|
|
||||||
template.write(new FileOutputStream("学生单词测试卷.docx"));
|
|
||||||
System.out.println("文档生成成功!");
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.yinlihupo.enlish.service.service.exam;
|
||||||
|
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
|
import com.deepoove.poi.config.Configure;
|
||||||
|
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
|
||||||
|
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
|
||||||
|
import com.yinlihupo.enlish.service.model.bo.Word;
|
||||||
|
import com.yinlihupo.enlish.service.service.ExamWordsService;
|
||||||
|
import com.yinlihupo.enlish.service.service.VocabularyService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
@Slf4j
|
||||||
|
public class ExamTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExamWordsService examWordsService;
|
||||||
|
@Resource
|
||||||
|
private VocabularyService vocabularyService;
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
ExamWordsDO examWordsDO = examWordsService.generateExamWords(5, 0, List.of(1));
|
||||||
|
log.info("{}", examWordsDO);
|
||||||
|
List<VocabularyBankDO> vocabularyBankDOS = vocabularyService.findVocabularyBankDOListById(examWordsDO.getWordIds());
|
||||||
|
List<Word> assessmentWords = vocabularyBankDOS.stream().map(vocabularyBankDO -> Word.builder()
|
||||||
|
.id(vocabularyBankDO.getId())
|
||||||
|
.title(vocabularyBankDO.getWord())
|
||||||
|
.definition(vocabularyBankDO.getDefinition())
|
||||||
|
.build()).toList();
|
||||||
|
|
||||||
|
|
||||||
|
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
||||||
|
Configure config = Configure.builder()
|
||||||
|
.bind("words", policy)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("id", examWordsDO.getId());
|
||||||
|
data.put("words", assessmentWords);
|
||||||
|
|
||||||
|
// 4. 渲染并输出
|
||||||
|
try (XWPFTemplate template = XWPFTemplate.compile("C:\\project\\java\\enlish_edu\\enlish\\enlish-service\\src\\main\\resources\\templates\\assessment_v5.docx", config)) {
|
||||||
|
template.render(data);
|
||||||
|
template.write(new FileOutputStream("学生单词测试卷.docx"));
|
||||||
|
System.out.println("文档生成成功!");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user