/** * 自然写互动课堂教学管理云平台软件 V1.0 * * 作业管理控制器 * 负责作业/试卷的发布、回收、批改结果查询等接口 */ package com.writech.cloud.controller; import com.writech.cloud.WritechCloudApplication.ApiResponse; import com.writech.cloud.WritechCloudApplication.BusinessException; import com.writech.cloud.model.Assignment; import com.writech.cloud.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.time.LocalDateTime; import java.util.*; /** * 作业控制器 - /api/v1/assignment * * 教师发布作业/试卷 → 学生纸上作答(笔迹通过点阵笔采集) * → 系统自动收集 → AI引擎识别批改 → 结果推送教师和家长 */ @RestController @RequestMapping("/api/v1/assignment") public class AssignmentController { @Autowired private UserService userService; /** * 发布作业 * POST /api/v1/assignment/publish * * 教师创建并发布作业/试卷,指定班级、截止时间、题目内容 * 发布后自动推送通知至学生端和家长端 */ @PostMapping("/publish") public ApiResponse publishAssignment( @Valid @RequestBody AssignmentPublishRequest request, @RequestHeader("Authorization") String auth) { // 验证教师身份 String teacherId = extractUserIdFromToken(auth); // 校验截止时间 if (request.getDeadline() != null && request.getDeadline().isBefore(LocalDateTime.now())) { throw new BusinessException(400, "截止时间不能早于当前时间"); } // 校验题目列表 if (request.getQuestions() == null || request.getQuestions().isEmpty()) { throw new BusinessException(400, "作业题目不能为空"); } // 创建作业记录 Assignment assignment = new Assignment(); assignment.setId(UUID.randomUUID().toString().replace("-", "")); assignment.setTeacherId(teacherId); assignment.setClassId(request.getClassId()); assignment.setTitle(request.getTitle()); assignment.setType(request.getType()); // homework/exam/practice assignment.setSubject(request.getSubject()); assignment.setDeadline(request.getDeadline()); assignment.setStatus("published"); assignment.setPublishTime(LocalDateTime.now()); assignment.setTotalScore(calculateTotalScore(request.getQuestions())); assignment.setQuestionCount(request.getQuestions().size()); // 关联点阵码页面(每道题对应特定点阵码区域) if (request.getDotCodePages() != null) { assignment.setDotCodePages(request.getDotCodePages()); } // 保存作业及题目 // assignmentService.saveWithQuestions(assignment, request.getQuestions()); // 异步推送通知至学生端和家长端 // messageService.pushAssignmentNotification(assignment); AssignmentPublishResponse response = new AssignmentPublishResponse(); response.setAssignmentId(assignment.getId()); response.setTitle(assignment.getTitle()); response.setPublishTime(assignment.getPublishTime()); response.setStudentCount(getClassStudentCount(request.getClassId())); return ApiResponse.success(response); } /** * 获取作业列表 * GET /api/v1/assignment/list * * 教师查看已发布的作业列表,支持按班级、状态、时间筛选 */ @GetMapping("/list") public ApiResponse> listAssignments( @RequestParam(required = false) String classId, @RequestParam(required = false) String status, @RequestParam(required = false) String subject, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size, @RequestHeader("Authorization") String auth) { String userId = extractUserIdFromToken(auth); // Page result = assignmentService.queryList(...) return ApiResponse.success(null); } /** * 获取作业详情 * GET /api/v1/assignment/{id} */ @GetMapping("/{id}") public ApiResponse getAssignment(@PathVariable String id) { // Assignment assignment = assignmentService.findById(id); return ApiResponse.success(null); } /** * 获取批改结果 * GET /api/v1/result/{assignmentId} * * 查询指定作业的AI批改结果,包含每个学生的识别文本、 * 得分、错误详情及AI反馈建议 */ @GetMapping("/result/{assignmentId}") public ApiResponse getResult( @PathVariable String assignmentId, @RequestParam(required = false) String studentId) { AssignmentResultResponse response = new AssignmentResultResponse(); response.setAssignmentId(assignmentId); response.setTotalStudents(40); response.setSubmittedCount(38); response.setGradedCount(38); response.setAverageScore(85.5); response.setHighestScore(100.0); response.setLowestScore(45.0); // 每个学生的批改结果 List studentResults = new ArrayList<>(); // studentResults = resultService.getStudentResults(assignmentId, studentId); response.setStudentResults(studentResults); return ApiResponse.success(response); } /** * 教师人工复核批改 * PUT /api/v1/assignment/review/{assignmentId} * * AI批改后教师可进行人工复核,修正AI评分或添加评语 */ @PutMapping("/review/{assignmentId}") public ApiResponse reviewAssignment( @PathVariable String assignmentId, @Valid @RequestBody ReviewRequest request, @RequestHeader("Authorization") String auth) { String teacherId = extractUserIdFromToken(auth); // 遍历教师的复核修改 for (ReviewItem item : request.getReviewItems()) { // resultService.updateReview(assignmentId, item.getStudentId(), // item.getQuestionId(), item.getManualScore(), // item.getTeacherComment(), teacherId); } return ApiResponse.success(); } /** * 学情报告接口 * GET /api/v1/report/student/{id} * * 获取指定学生的学情报告,包含知识点掌握度、 * 书写能力评估、成绩趋势等多维度分析数据 */ @GetMapping("/report/student/{studentId}") public ApiResponse getStudentReport( @PathVariable String studentId, @RequestParam(required = false) String subject, @RequestParam(required = false) String dateRange) { StudentReportResponse report = new StudentReportResponse(); report.setStudentId(studentId); report.setReportDate(LocalDateTime.now()); // 知识点掌握度 List knowledgePoints = new ArrayList<>(); // knowledgePoints = analyticsService.getKnowledgeMastery(studentId, subject); report.setKnowledgePoints(knowledgePoints); // 书写能力评估 WritingAbility writingAbility = new WritingAbility(); writingAbility.setStrokeOrderScore(88.5); writingAbility.setStructureScore(82.3); writingAbility.setNeatnessScore(90.1); writingAbility.setOverallScore(86.9); report.setWritingAbility(writingAbility); return ApiResponse.success(report); } // ==================== 内部方法 ==================== private String extractUserIdFromToken(String auth) { // 从JWT Token解析用户ID return "teacher_001"; } private double calculateTotalScore(List questions) { return questions.stream() .mapToDouble(QuestionItem::getScore) .sum(); } private int getClassStudentCount(String classId) { return 40; // 查询班级学生数 } // ==================== DTO 定义 ==================== public static class AssignmentPublishRequest { @NotBlank private String classId; @NotBlank private String title; private String type; // homework/exam/practice private String subject; private LocalDateTime deadline; private List questions; private List dotCodePages; // 关联的点阵码页面ID public String getClassId() { return classId; } public void setClassId(String id) { this.classId = id; } public String getTitle() { return title; } public void setTitle(String t) { this.title = t; } public String getType() { return type; } public void setType(String t) { this.type = t; } public String getSubject() { return subject; } public void setSubject(String s) { this.subject = s; } public LocalDateTime getDeadline() { return deadline; } public void setDeadline(LocalDateTime d) { this.deadline = d; } public List getQuestions() { return questions; } public void setQuestions(List q) { this.questions = q; } public List getDotCodePages() { return dotCodePages; } public void setDotCodePages(List p) { this.dotCodePages = p; } } public static class QuestionItem { private int questionNo; private String type; // choice/fill/short_answer/essay/math private String content; private String answer; private double score; private String knowledgePointId; public int getQuestionNo() { return questionNo; } public void setQuestionNo(int n) { this.questionNo = n; } public String getType() { return type; } public void setType(String t) { this.type = t; } public String getContent() { return content; } public void setContent(String c) { this.content = c; } public String getAnswer() { return answer; } public void setAnswer(String a) { this.answer = a; } public double getScore() { return score; } public void setScore(double s) { this.score = s; } public String getKnowledgePointId() { return knowledgePointId; } public void setKnowledgePointId(String id) { this.knowledgePointId = id; } } public static class AssignmentPublishResponse { private String assignmentId; private String title; private LocalDateTime publishTime; private int studentCount; public String getAssignmentId() { return assignmentId; } public void setAssignmentId(String id) { this.assignmentId = id; } public String getTitle() { return title; } public void setTitle(String t) { this.title = t; } public LocalDateTime getPublishTime() { return publishTime; } public void setPublishTime(LocalDateTime t) { this.publishTime = t; } public int getStudentCount() { return studentCount; } public void setStudentCount(int c) { this.studentCount = c; } } public static class AssignmentSummary { private String id; private String title; private String type; private String status; private int submittedCount; private int totalCount; private LocalDateTime publishTime; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String t) { this.title = t; } public String getType() { return type; } public void setType(String t) { this.type = t; } public String getStatus() { return status; } public void setStatus(String s) { this.status = s; } public int getSubmittedCount() { return submittedCount; } public void setSubmittedCount(int c) { this.submittedCount = c; } public int getTotalCount() { return totalCount; } public void setTotalCount(int c) { this.totalCount = c; } public LocalDateTime getPublishTime() { return publishTime; } public void setPublishTime(LocalDateTime t) { this.publishTime = t; } } public static class AssignmentDetailResponse { private Assignment assignment; private List questions; public Assignment getAssignment() { return assignment; } public void setAssignment(Assignment a) { this.assignment = a; } public List getQuestions() { return questions; } public void setQuestions(List q) { this.questions = q; } } public static class AssignmentResultResponse { private String assignmentId; private int totalStudents; private int submittedCount; private int gradedCount; private double averageScore; private double highestScore; private double lowestScore; private List studentResults; public String getAssignmentId() { return assignmentId; } public void setAssignmentId(String id) { this.assignmentId = id; } public int getTotalStudents() { return totalStudents; } public void setTotalStudents(int c) { this.totalStudents = c; } public int getSubmittedCount() { return submittedCount; } public void setSubmittedCount(int c) { this.submittedCount = c; } public int getGradedCount() { return gradedCount; } public void setGradedCount(int c) { this.gradedCount = c; } public double getAverageScore() { return averageScore; } public void setAverageScore(double s) { this.averageScore = s; } public double getHighestScore() { return highestScore; } public void setHighestScore(double s) { this.highestScore = s; } public double getLowestScore() { return lowestScore; } public void setLowestScore(double s) { this.lowestScore = s; } public List getStudentResults() { return studentResults; } public void setStudentResults(List r) { this.studentResults = r; } } public static class StudentResult { private String studentId; private String studentName; private double totalScore; private List questionResults; public String getStudentId() { return studentId; } public void setStudentId(String id) { this.studentId = id; } public String getStudentName() { return studentName; } public void setStudentName(String n) { this.studentName = n; } public double getTotalScore() { return totalScore; } public void setTotalScore(double s) { this.totalScore = s; } public List getQuestionResults() { return questionResults; } public void setQuestionResults(List r) { this.questionResults = r; } } public static class QuestionResult { private int questionNo; private String ocrText; private double score; private boolean isCorrect; private String aiFeedback; public int getQuestionNo() { return questionNo; } public void setQuestionNo(int n) { this.questionNo = n; } public String getOcrText() { return ocrText; } public void setOcrText(String t) { this.ocrText = t; } public double getScore() { return score; } public void setScore(double s) { this.score = s; } public boolean isCorrect() { return isCorrect; } public void setCorrect(boolean c) { this.isCorrect = c; } public String getAiFeedback() { return aiFeedback; } public void setAiFeedback(String f) { this.aiFeedback = f; } } public static class ReviewRequest { private List reviewItems; public List getReviewItems() { return reviewItems; } public void setReviewItems(List items) { this.reviewItems = items; } } public static class ReviewItem { private String studentId; private int questionId; private Double manualScore; private String teacherComment; public String getStudentId() { return studentId; } public void setStudentId(String id) { this.studentId = id; } public int getQuestionId() { return questionId; } public void setQuestionId(int id) { this.questionId = id; } public Double getManualScore() { return manualScore; } public void setManualScore(Double s) { this.manualScore = s; } public String getTeacherComment() { return teacherComment; } public void setTeacherComment(String c) { this.teacherComment = c; } } public static class StudentReportResponse { private String studentId; private LocalDateTime reportDate; private List knowledgePoints; private WritingAbility writingAbility; public String getStudentId() { return studentId; } public void setStudentId(String id) { this.studentId = id; } public LocalDateTime getReportDate() { return reportDate; } public void setReportDate(LocalDateTime d) { this.reportDate = d; } public List getKnowledgePoints() { return knowledgePoints; } public void setKnowledgePoints(List kp) { this.knowledgePoints = kp; } public WritingAbility getWritingAbility() { return writingAbility; } public void setWritingAbility(WritingAbility wa) { this.writingAbility = wa; } } public static class KnowledgePoint { private String id; private String name; private double masteryRate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String n) { this.name = n; } public double getMasteryRate() { return masteryRate; } public void setMasteryRate(double r) { this.masteryRate = r; } } public static class WritingAbility { private double strokeOrderScore; private double structureScore; private double neatnessScore; private double overallScore; public double getStrokeOrderScore() { return strokeOrderScore; } public void setStrokeOrderScore(double s) { this.strokeOrderScore = s; } public double getStructureScore() { return structureScore; } public void setStructureScore(double s) { this.structureScore = s; } public double getNeatnessScore() { return neatnessScore; } public void setNeatnessScore(double s) { this.neatnessScore = s; } public double getOverallScore() { return overallScore; } public void setOverallScore(double s) { this.overallScore = s; } } }