diff --git a/docs/sql/2026-10-16-task-review-ai-comment.sql b/docs/sql/2026-10-16-task-review-ai-comment.sql
new file mode 100644
index 0000000..950bebc
--- /dev/null
+++ b/docs/sql/2026-10-16-task-review-ai-comment.sql
@@ -0,0 +1,3 @@
+-- 教师任务评阅评语字段;应用启动时也会由 schema initializer 自动补列。
+ALTER TABLE student_training_answer
+ ADD COLUMN teacher_comment varchar(1000) NULL AFTER teacher_score;
diff --git a/pom.xml b/pom.xml
index 2f3e74c..9447651 100644
--- a/pom.xml
+++ b/pom.xml
@@ -140,6 +140,9 @@
org.projectlombok
lombok
+
+ 1.18.32
org.hibernate
diff --git a/src/main/java/com/sztzjy/linkCommerce/config/StudentTrainingAnswerTeacherScoreSchemaInitializer.java b/src/main/java/com/sztzjy/linkCommerce/config/StudentTrainingAnswerTeacherScoreSchemaInitializer.java
index fe2ffd1..57a3558 100644
--- a/src/main/java/com/sztzjy/linkCommerce/config/StudentTrainingAnswerTeacherScoreSchemaInitializer.java
+++ b/src/main/java/com/sztzjy/linkCommerce/config/StudentTrainingAnswerTeacherScoreSchemaInitializer.java
@@ -18,6 +18,7 @@ public class StudentTrainingAnswerTeacherScoreSchemaInitializer {
addColumnIfMissing("teacher_score", "decimal(5,2) NULL");
addColumnIfMissing("teacher_scored_by", "varchar(64) NULL");
addColumnIfMissing("teacher_scored_at", "datetime NULL");
+ addColumnIfMissing("teacher_comment", "varchar(1000) NULL");
}
private void addColumnIfMissing(String columnName, String definition) {
diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/AiTrainingEvaluationController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/AiTrainingEvaluationController.java
index 2b88298..aec941e 100644
--- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/AiTrainingEvaluationController.java
+++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/AiTrainingEvaluationController.java
@@ -56,8 +56,10 @@ public class AiTrainingEvaluationController {
@ApiOperation("Generate AI assessment")
public ResultEntity assessment(@PathVariable String taskKey, HttpServletRequest request) {
try {
- return new ResultEntity<>(HttpStatus.OK, "AI assessment generated",
- aiTrainingEvaluationService.generateAssessment(taskKey, currentUser(request)));
+ AiTrainingEvaluationView view = aiTrainingEvaluationService.startAssessment(taskKey, currentUser(request));
+ // 兼容旧版服务实现/测试替身;正式实现始终立即返回 PROCESSING 状态。
+ if (view == null) view = aiTrainingEvaluationService.generateAssessment(taskKey, currentUser(request));
+ return new ResultEntity<>(HttpStatus.OK, "AI assessment submitted", view);
} catch (ServiceException e) {
return new ResultEntity<>(e.getCode(), e.getMessage());
}
diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java
index 5d3001a..4a3387a 100644
--- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java
+++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java
@@ -14,25 +14,35 @@ import com.sztzjy.linkCommerce.mapper.StudentTrainingAnswerMapper;
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
import com.sztzjy.linkCommerce.mapper.TeachingClassStudentMapper;
import com.sztzjy.linkCommerce.mapper.TrainingTaskMapper;
+import com.sztzjy.linkCommerce.mapper.TrainingTaskClassConfigMapper;
import com.sztzjy.linkCommerce.mapper.UserinfoMapper;
import com.sztzjy.linkCommerce.mapper.WeightMapper;
import com.sztzjy.linkCommerce.entity.dto.*;
import com.sztzjy.linkCommerce.service.ScoreRankService;
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
import com.sztzjy.linkCommerce.service.TeacherScoreService;
+import com.sztzjy.linkCommerce.service.AiTrainingEvaluationService;
import com.sztzjy.linkCommerce.util.ResultEntity;
import com.sztzjy.linkCommerce.util.excel.FilePortUtil;
+import com.sztzjy.linkCommerce.util.file.IFileUtil;
+import com.sztzjy.linkCommerce.util.pdfUtils.PDFConvertUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.File;
+import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
@@ -58,6 +68,8 @@ public class TeaScoreController {
@Autowired(required = false)
TrainingTaskMapper trainingTaskMapper;
@Autowired(required = false)
+ TrainingTaskClassConfigMapper trainingTaskClassConfigMapper;
+ @Autowired(required = false)
StudentTrainingAnswerMapper studentTrainingAnswerMapper;
@Autowired(required = false)
SchoolDefaultTaskService schoolDefaultTaskService;
@@ -65,6 +77,78 @@ public class TeaScoreController {
UserinfoMapper userinfoMapper;
@Autowired
TeacherScoreService teacherScoreService;
+ @Autowired
+ IFileUtil fileUtil;
+ @Autowired
+ AiTrainingEvaluationService aiTrainingEvaluationService;
+
+ @PostMapping("/taskReview/ai-assessment")
+ @ApiOperation("异步发起单个任务AI评分")
+ public ResultEntity startTaskAiAssessment(@RequestParam String classId,
+ @RequestParam String taskId,
+ @RequestParam String studentUserId,
+ HttpServletRequest request) {
+ try {
+ JwtUser teacher = currentUser(request);
+ teacherScoreService.requireOwnedClass(teacher, classId);
+ return new ResultEntity<>(HttpStatus.OK, "AI评分任务已提交",
+ aiTrainingEvaluationService.startAssessmentForTeacher(classId, taskId, studentUserId, teacher));
+ } catch (com.sztzjy.linkCommerce.config.exception.handler.ServiceException e) {
+ return new ResultEntity<>(e.getCode(), e.getMessage());
+ }
+ }
+
+ @GetMapping("/taskReview/ai-assessment")
+ @ApiOperation("查询任务AI评分状态")
+ public ResultEntity getTaskAiAssessment(@RequestParam String classId,
+ @RequestParam String taskId,
+ @RequestParam String studentUserId,
+ HttpServletRequest request) {
+ try {
+ JwtUser teacher = currentUser(request);
+ teacherScoreService.requireAccessibleClass(teacher, classId);
+ return new ResultEntity<>(HttpStatus.OK, "查询成功",
+ aiTrainingEvaluationService.getForTeacher(classId, taskId, studentUserId, teacher));
+ } catch (com.sztzjy.linkCommerce.config.exception.handler.ServiceException e) {
+ return new ResultEntity<>(e.getCode(), e.getMessage());
+ }
+ }
+
+ @PostMapping("/taskReview/ai-comment")
+ @ApiOperation("基于AI评分与助学报告生成10-50字教师评语")
+ public ResultEntity