feat(examWords): 新增识别题目图片上传接口及相关功能

- 添加ExamWordsJudgeResultDO及对应数据库表映射与Mapper接口
- 实现ExamWordsJudgeResultType枚举,管理判题状态
- 在ExamWordsService及实现类中新增保存图片并记录数据库的方法
- 在ExamWordsController中新增上传图片接口submit,处理上传文件并返回操作结果
- 调整application-dev.yml中的png临时文件目录路径配置
- 更新MyBatis生成配置,新增exam_words_judge_result表支持
- 优化ExamWordsConstant,清理未使用常量和注释内容
This commit is contained in:
lbw
2025-12-12 18:41:19 +08:00
parent feabb6d4b1
commit a5b23057d3
10 changed files with 150 additions and 21 deletions

View File

@@ -3,6 +3,4 @@ package com.yinlihupo.enlish.service.constant;
public interface ExamWordsConstant { public interface ExamWordsConstant {
int PGN_COL = 53; int PGN_COL = 53;
// 文件暂存目录 linux
String ASSESSMENT_FELT = "enlish/exam_words/";
} }

View File

@@ -10,14 +10,13 @@ import com.yinlihupo.enlish.service.model.bo.Word;
import com.yinlihupo.enlish.service.model.vo.exam.GenerateExamWordsReqVO; import com.yinlihupo.enlish.service.model.vo.exam.GenerateExamWordsReqVO;
import com.yinlihupo.enlish.service.service.ExamWordsService; import com.yinlihupo.enlish.service.service.ExamWordsService;
import com.yinlihupo.enlish.service.service.VocabularyService; import com.yinlihupo.enlish.service.service.VocabularyService;
import com.yinlihupo.framework.common.response.Response;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
@@ -40,7 +39,7 @@ public class ExamWordsController {
@Value("${templates.word}") @Value("${templates.word}")
private String templateWordPath; private String templateWordPath;
@PostMapping("submit") @PostMapping("genexam")
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();
@@ -101,5 +100,16 @@ public class ExamWordsController {
} }
} }
@PostMapping("submit")
public Response<String> submitExamWords(@RequestParam("file") MultipartFile file) {
try {
int saveExamWordsPngToDbAndLocal = examWordsService.saveExamWordsPngToDbAndLocal(file);
if (saveExamWordsPngToDbAndLocal > 0) {
return Response.success("保存成功");
}
return Response.fail("保存失败");
} catch (Exception e) {
return Response.fail("保存失败: " + e.getMessage());
}
}
} }

View File

@@ -0,0 +1,38 @@
package com.yinlihupo.enlish.service.domain.dataobject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class ExamWordsJudgeResultDO {
private Integer id;
private String ansSheetPath;
private Integer studentId;
private Integer examWordsId;
private Integer correctWordCount;
private Integer wrongWordCount;
private Integer isFinished;
private LocalDateTime startDate;
private List<Integer> correctWordIds;
private List<Integer> wrongWordIds;
private String errorMsg;
}

View File

@@ -0,0 +1,8 @@
package com.yinlihupo.enlish.service.domain.mapper;
import org.apache.ibatis.annotations.Param;
public interface ExamWordsJudgeResultDOMapper {
int insert(@Param("path") String path);
}

View File

@@ -0,0 +1,17 @@
package com.yinlihupo.enlish.service.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ExamWordsJudgeResultType {
WAIT(0, "未开始判题"),
SUCCESS(1, "判题成功"),
FAIL(2, "判题失败"),
;
final int code;
final String message;
}

View File

@@ -2,6 +2,7 @@ package com.yinlihupo.enlish.service.service;
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO; import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
@@ -9,5 +10,5 @@ public interface ExamWordsService {
ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds); ExamWordsDO generateExamWords(Integer gradeId, Integer level, List<Integer> studentIds);
int saveExamWordsPngToDbAndLocal(MultipartFile file);
} }

View File

@@ -1,24 +1,23 @@
package com.yinlihupo.enlish.service.service.exam; package com.yinlihupo.enlish.service.service.exam;
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.VocabularyBankDO; import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.domain.mapper.ExamWordsDOMapper; import com.yinlihupo.enlish.service.domain.mapper.*;
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 com.yinlihupo.enlish.service.service.ExamWordsService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; 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 org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
@Service @Service
@Slf4j @Slf4j
@@ -28,12 +27,16 @@ public class ExamWordsServiceImpl implements ExamWordsService {
private GradeUnitDOMapper gradeUnitDOMapper; private GradeUnitDOMapper gradeUnitDOMapper;
@Resource @Resource
private VocabularyBankDOMapper vocabularyBankDOMapper; private VocabularyBankDOMapper vocabularyBankDOMapper;
@Value("${templates.count}")
private Integer wordCount;
@Resource @Resource
private ExamWordsDOMapper examWordsDOMapper; private ExamWordsDOMapper examWordsDOMapper;
@Resource @Resource
private StudentExamWordsDOMapper studentExamWordsDOMapper; private StudentExamWordsDOMapper studentExamWordsDOMapper;
@Resource
private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper;
@Value("${templates.count}")
private Integer wordCount;
@Value("${tmp.png}")
String tmpPng;
@Override @Override
@Transactional(rollbackFor = RuntimeException.class) @Transactional(rollbackFor = RuntimeException.class)
@@ -71,8 +74,33 @@ public class ExamWordsServiceImpl implements ExamWordsService {
return examWordsDO; return examWordsDO;
} }
@PostMapping("analyze") @Override
public void generateAssessmentDocxAnalyze(@RequestParam("file") MultipartFile file, @RequestParam("id") Integer id) { @Transactional(rollbackFor = RuntimeException.class)
public int saveExamWordsPngToDbAndLocal(MultipartFile file) {
File dir = new File(tmpPng);
if (!dir.exists()) {
dir.mkdirs();
}
try {
String originalFilename = file.getOriginalFilename();
String suffix = "";
if (originalFilename != null && originalFilename.contains(".")) {
suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
}
String newFileName = UUID.randomUUID() + suffix;
String path = tmpPng + newFileName;
File dest = new File(path);
file.transferTo(dest);
return examWordsJudgeResultDOMapper.insert(path);
} catch (IOException e) {
throw new RuntimeException("上传失败", e);
}
} }
} }

View File

@@ -26,4 +26,4 @@ templates:
count: 100 count: 100
data: C:\project\tess data: C:\project\tess
tmp: tmp:
png: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\tmp\png png: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\tmp\png\

View File

@@ -45,7 +45,7 @@
targetProject="src/main/java"/> targetProject="src/main/java"/>
<!-- 需要生成的表-实体类 --> <!-- 需要生成的表-实体类 -->
<table tableName="student_exam_words" domainObjectName="StudentExamWordsDO" <table tableName="exam_words_judge_result" domainObjectName="ExamWordsJudgeResultDO"
enableCountByExample="false" enableCountByExample="false"
enableUpdateByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableDeleteByExample="false"

View File

@@ -0,0 +1,29 @@
<?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.ExamWordsJudgeResultDOMapper">
<resultMap id="BaseResultMap" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="ans_sheet_path" jdbcType="VARCHAR" property="ansSheetPath" />
<result column="student_id" jdbcType="INTEGER" property="studentId" />
<result column="exam_words_id" jdbcType="INTEGER" property="examWordsId" />
<result column="correct_word_count" jdbcType="INTEGER" property="correctWordCount" />
<result column="wrong_word_count" jdbcType="INTEGER" property="wrongWordCount" />
<result column="is_finished" jdbcType="INTEGER" property="isFinished" />
<result column="start_date" jdbcType="TIMESTAMP" property="startDate" />
<result column="error_msg" jdbcType="VARCHAR" property="errorMsg" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO">
<result column="correct_word_ids" jdbcType="LONGVARCHAR" property="correctWordIds" typeHandler="com.yinlihupo.enlish.service.config.ListWordIdTypeHandler" />
<result column="wrong_word_ids" jdbcType="LONGVARCHAR" property="wrongWordIds" typeHandler="com.yinlihupo.enlish.service.config.ListWordIdTypeHandler" />
</resultMap>
<insert id="insert" parameterType="com.yinlihupo.enlish.service.domain.dataobject.ExamWordsJudgeResultDO">
insert into exam_words_judge_result
(ans_sheet_path, is_finished, start_date)
values (#{path}, 0, now())
</insert>
</mapper>