| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- package com.njuzr.eaibackend.service.impl;
- import com.alibaba.fastjson2.JSONObject;
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.baomidou.mybatisplus.core.metadata.IPage;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.njuzr.eaibackend.dto.AssignmentDTO;
- import com.njuzr.eaibackend.dto.AssignmentQueryDTO;
- import com.njuzr.eaibackend.dto.AssignmentUpdateDTO;
- import com.njuzr.eaibackend.dto.CorrectDTO;
- import com.njuzr.eaibackend.enums.AssignmentCompletionStatus;
- import com.njuzr.eaibackend.enums.AssignmentStatus;
- import com.njuzr.eaibackend.enums.Role;
- import com.njuzr.eaibackend.exception.MyException;
- import com.njuzr.eaibackend.mapper.*;
- import com.njuzr.eaibackend.po.*;
- import com.njuzr.eaibackend.po.Class;
- import com.njuzr.eaibackend.service.AssignmentService;
- import com.njuzr.eaibackend.service.ClassService;
- import com.njuzr.eaibackend.service.ExamTimerService;
- import com.njuzr.eaibackend.service.TextAnalysisService;
- import com.njuzr.eaibackend.utils.*;
- import com.njuzr.eaibackend.vo.*;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.BeanUtils;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.http.HttpStatus;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.time.LocalDateTime;
- import java.util.*;
- import java.util.function.Function;
- import java.util.stream.Collectors;
- /**
- * @author: Leonezhurui
- * @Date: 2024/3/15 - 00:40
- * @Package: EAI-Backend
- */
- @Slf4j
- @Service
- public class AssignmentServiceImpl implements AssignmentService {
- private final AssignmentMapper assignmentMapper;
- private final CourseMapper courseMapper;
- private final StudentAssignmentMapper studentAssignmentMapper;
- private final UserMapper userMapper;
- private final ClassService classService;
- private final OssUtil ossUtil;
- private final ExamTimerService examTimerService;
- private final FileUtil fileUtil = new FileUtil();
- private final TextAnalysisService textAnalysisService;
- public AssignmentServiceImpl(AssignmentMapper assignmentMapper,
- CourseMapper courseMapper,
- StudentAssignmentMapper studentAssignmentMapper,
- UserMapper userMapper,
- OssUtil ossUtil,
- CourseServiceImpl courseServiceImpl,
- CourseStudentMapper courseStudentMapper,
- ClassService classService,
- TextAnalysisService textAnalysisService,
- ExamTimerService examTimerService) {
- this.assignmentMapper = assignmentMapper;
- this.courseMapper = courseMapper;
- this.studentAssignmentMapper = studentAssignmentMapper;
- this.userMapper = userMapper;
- this.ossUtil = ossUtil;
- this.textAnalysisService = textAnalysisService;
- this.classService = classService;
- this.examTimerService = examTimerService;
- }
- @Override
- public AssignmentVO createAssignment(MyUserDetails user, Long courseId, AssignmentDTO assignmentDTO) {
- Course course = courseMapper.selectById(courseId);
- if (course == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "课程不存在");
- if (user.getRole() != Role.ADMIN) {
- List<String> teacherIds = Collections.singletonList(Optional.ofNullable(course.getTeacherIds())
- .orElse(Collections.emptyList().toString()));
- String userIdStr = String.valueOf(user.getId());
- boolean hasTeacherId = teacherIds.contains(userIdStr);
- boolean pidMatches = Objects.equals(course.getTeacherPid(), user.getPid());
- if (!hasTeacherId && !pidMatches) {
- throw MyException.create(HttpStatus.BAD_REQUEST, "无权限创建");
- }
- }
- Assignment target = convertToPO(assignmentDTO);
- target.setCourseId(courseId);
- target.setTeacherId(user.getId());
- target.setEngageNumber(0);
- target.setCorrectNumber(0);
- // TODO:权宜之计
- // target.setTeacherId(Long.valueOf(user.getPid()));
- target.setCreateTime(new Date());
- try {
- int code = assignmentMapper.insert(target);
- if (code == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "创建作业失败");
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "创建作业失败");
- }
- return convertToVO(target);
- }
- @Override
- // @Cacheable(value = "assignmentInfo", key = "'assignment_' + #assignmentId")
- public AssignmentVO findAssignmentById(Long assignmentId) {
- QueryWrapper<Assignment> wrapper = new QueryWrapper<>();
- wrapper.eq("assignment_id", assignmentId);
- Assignment res = assignmentMapper.selectOne(wrapper);
- log.info("数据库查询作业:{}", assignmentId);
- if (res == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
- return convertToVO(res);
- }
- @Override
- public IPage<AssignmentVO> findAssignmentPage(Page<Assignment> page, AssignmentQueryDTO assignmentQueryDTO) {
- log.info("作业查询服务:{}", assignmentQueryDTO);
- QueryWrapper<Assignment> wrapper = new QueryWrapper<>();
- if (assignmentQueryDTO.getAssignmentId() != null) { // assignmentId直接判断是否相等
- // TODO 检测assignmentId是否正确
- wrapper.eq("assignmentId", assignmentQueryDTO.getAssignmentId());
- }
- if (assignmentQueryDTO.getTeacherId() != null) { // teacherId直接匹配
- wrapper.eq("teacher_id", assignmentQueryDTO.getTeacherId());
- }
- if (assignmentQueryDTO.getCourseId() != null) { // teacherId直接匹配
- wrapper.eq("course_id", assignmentQueryDTO.getCourseId());
- }
- if (assignmentQueryDTO.getAssignmentName() != null) { // 模糊匹配作业名字
- wrapper.like("assignment_name", assignmentQueryDTO.getAssignmentName());
- }
- if(assignmentQueryDTO.getType() != null){
- wrapper.eq("type",assignmentQueryDTO.getType());
- }
- if (assignmentQueryDTO.getStatus() != null) {
- AssignmentStatus status = assignmentQueryDTO.getStatus();
- if (status == AssignmentStatus.NOT_STARTED) {
- wrapper.gt("start_time", LocalDateTime.now()); // 意思是start_time > now()
- } else if (status == AssignmentStatus.PROCEEDING) {
- wrapper.le("start_time", LocalDateTime.now())
- .ge("end_time", LocalDateTime.now());
- } else {
- wrapper.lt("end_time", LocalDateTime.now());
- }
- }
- IPage<Assignment> assignments = assignmentMapper.selectPage(page, wrapper);
- return PageMapperUtil.convert(assignments, this::convertToVO);
- }
- @Override
- @CacheEvict(value = "assignmentInfo", key = "'assignment_' + #assignmentId")
- public AssignmentVO updateAssignment(MyUserDetails user, Long assignmentId, AssignmentUpdateDTO assignmentUpdateDTO) {
- Assignment target = assignmentMapper.selectById(assignmentId);
- if (!Objects.equals(target.getTeacherId(), user.getId()) && !Objects.equals(target.getTeacherPid(), user.getPid()))
- throw MyException.create(HttpStatus.BAD_REQUEST, "无权限更新");
- Assignment ope = convertToPO(assignmentUpdateDTO);
- ope.setAssignmentId(assignmentId);
- try {
- int code = assignmentMapper.updateById(ope);
- if (code == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "服务器更新失败");
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "服务器更新失败");
- }
- return convertToVO(assignmentMapper.selectById(assignmentId));
- }
- /**
- * 教师删除作业
- */
- @Override
- @Transactional
- @CacheEvict(value = "assignmentInfo", key = "'assignment_' + #assignmentId")
- public void deleteById(Long teacherId, Long assignmentId) {
- Assignment target = assignmentMapper.selectById(assignmentId);
- if (!Objects.equals(target.getTeacherId(), teacherId))
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "无权限删除");
- try {
- List<Engagement> engagements = studentAssignmentMapper.findEngagementByAssignmentId(assignmentId);
- for(Engagement engagement : engagements) {
- studentAssignmentMapper.delete(engagement.getStudentId(), assignmentId);
- }
- int code = assignmentMapper.deleteById(assignmentId);
- if (code == 0) {
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "删除作业错误");
- }
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "删除作业错误");
- }
- }
- @Override
- public void engageAssignment(Long studentId, Long assignmentId) {
- if(studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId) != null){
- return;
- }
- // 1创建Engagement实体类,初始化基本信息
- Engagement engagement = new Engagement();
- engagement.setStudentId(studentId);
- engagement.setAssignmentId(assignmentId);
- engagement.setVersion(0); // 初始版本从0开始,首次提交后变为1
- engagement.setStatus(AssignmentCompletionStatus.NOT_SUBMITTED); // 已经进入到页面编辑,但是还没有提交
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- assignment.setEngageNumber(assignment.getEngageNumber() + 1);
- if (Boolean.TRUE.equals(assignment.getExamMode()) && assignment.getExamDuration() != null) {
- examTimerService.startExamTimer(studentId, assignmentId, assignment.getExamDuration());
- }
- // // 2通过FileUtil创建一个空的docx文件
- // InputStream inputStream = fileUtil.createEmptyDocx();
- //
- // String filePath = assignmentId + "_" + studentId + ".docx";
- // // 3通过OssUtil工具类上传空文件,注意给其命名为`assignmentId/studentId.docx`,并得到文件链接
- // String fileName = ossUtil.uploadEnduringFile(inputStream, filePath);
- // engagement.setFileUrl(fileName);
- try {
- int code = studentAssignmentMapper.insert(engagement);
- int code1 = assignmentMapper.updateById(assignment);
- if (code == 0 || code1 == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "参加作业失败");
- } catch (Exception e) {
- log.error(e.getMessage());
- // ossUtil.deleteFile(filePath);
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "参加作业失败");
- }
- }
- /**
- * 根据两个外键,搜索学生参与作业的情况(需要在mysql中设置索引)
- *
- * @param studentId
- * @param assignmentId
- * @return
- */
- @Override
- public EngagementVO getEngagement(Long studentId, Long assignmentId) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- return convertToVO(engagement);
- }
- // 返回顺序: 先是未批改的,然后是批改的按照成绩从高到低返回
- @Override
- public IPage<EngagementVO> findEngagementPage(Page<Engagement> page, Long assignmentId) {
- IPage<Engagement> engagements = studentAssignmentMapper.findEngagementByAssignmentId(page, assignmentId);
- return PageMapperUtil.convert(engagements, this::convertToVO);
- }
- @Override
- public EngagementDetailVO getDetailEngagement(Long studentId, Long assignmentId) {
- // 1 获取用户详细信息
- User student = userMapper.selectById(studentId);
- if (student == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "学生不存在");
- // 2 获取作业详细信息
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if (assignment == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
- // 3 获取作业参与详细信息
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- EngagementDetailVO detailVO = ModelMapperUtil.map(engagement, EngagementDetailVO.class);
- detailVO.setUserVO(ModelMapperUtil.map(student, UserVO.class));
- detailVO.setAssignmentVO(convertToVO(assignment));
- // detailVO.setFileKey(assignmentId + "_" + studentId + "_" + engagement.getVersion());
- log.info("请求到详细信息:" + detailVO);
- return detailVO;
- }
- @Override
- public List<EngagementHistoryVO> getEngagementHistory(Long studentId, Long assignmentId) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null) {
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- }
- List<StudentAssignmentHistory> historyRecords =
- studentAssignmentMapper.findHistoryByStudentIdAndAssignmentId(studentId, assignmentId);
- return historyRecords.stream()
- .map(item -> {
- EngagementHistoryVO vo = new EngagementHistoryVO();
- vo.setVersion(item.getVersion());
- vo.setQuillContent(item.getQuillContent());
- vo.setTextContent(item.getTextContent());
- vo.setHtmlContent(item.getHtmlContent());
- vo.setSubmitTime(item.getSubmitTime());
- if (item.getStatus() != null) {
- vo.setStatus(new AssignmentCompletionStatusVO(item.getStatus().getCode(), item.getStatus().getStatus()));
- }
- return vo;
- })
- .toList();
- }
- @Override
- public List<EngagementHistoryVO> getEngagementHistoryAllowEmpty(Long studentId, Long assignmentId) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null) {
- return Collections.emptyList();
- }
- List<StudentAssignmentHistory> historyRecords =
- studentAssignmentMapper.findHistoryByStudentIdAndAssignmentId(studentId, assignmentId);
- return historyRecords.stream()
- .map(item -> {
- EngagementHistoryVO vo = new EngagementHistoryVO();
- vo.setVersion(item.getVersion());
- vo.setQuillContent(item.getQuillContent());
- vo.setTextContent(item.getTextContent());
- vo.setHtmlContent(item.getHtmlContent());
- vo.setSubmitTime(item.getSubmitTime());
- if (item.getStatus() != null) {
- vo.setStatus(new AssignmentCompletionStatusVO(item.getStatus().getCode(), item.getStatus().getStatus()));
- }
- return vo;
- })
- .toList();
- }
- /**
- * 作业提交,更新文件版本和作业状态
- *
- * @param studentId
- * @param assignmentId
- */
- @Override
- @Transactional
- public void engagementSubmit(Long studentId, Long assignmentId) {
- log.info("studentId: {}, assignmentId: {}", studentId, assignmentId);
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null) {
- log.error("参与作业情况不存在 - studentId: {}, assignmentId: {}", studentId, assignmentId);
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- }
- int originalVersion = engagement.getVersion();
- engagement.setVersion(originalVersion + 1);
- engagement.setStatus(AssignmentCompletionStatus.SUBMITTED);
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if (Boolean.TRUE.equals(assignment.getExamMode())) {
- examTimerService.submitExam(studentId, assignmentId);
- engagement.setSubmitted(true);
- }
- try {
- int code = studentAssignmentMapper.updateById(engagement);
- if (code == 0) {
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- }
- // 基于主表当前行落一条快照(幂等),避免漏写/并发导致 history 缺版本
- studentAssignmentMapper.insertHistorySnapshot(assignmentId, studentId);
- } catch (Exception e) {
- log.error("更新异常: {}", e.getMessage(), e);
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- }
- }
- /**
- * 补交作业,更新文件版本和作业状态为已补交
- *
- * @param studentId
- * @param assignmentId
- */
- @Override
- @Transactional
- public void engagementLateSubmit(Long studentId, Long assignmentId) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- int originalVersion = engagement.getVersion();
- engagement.setVersion(originalVersion + 1);
- engagement.setStatus(AssignmentCompletionStatus.LATE_SUBMITTED);
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if (Boolean.TRUE.equals(assignment.getExamMode())) {
- examTimerService.submitExam(studentId, assignmentId);
- engagement.setSubmitted(true);
- }
- try {
- int code = studentAssignmentMapper.updateById(engagement);
- if (code == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- studentAssignmentMapper.insertHistorySnapshot(assignmentId, studentId);
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- }
- }
- /**
- * 作业暂存,更新文件版本,不修改作业状态
- *
- * @param studentId
- * @param assignmentId
- */
- @Override
- public void engagementStage(Long studentId, Long assignmentId, JSONObject jsonObject) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- log.info("[ENGAGE][STAGE] start assignmentId={}, studentId={}, version(before)={}, status={}",
- assignmentId, studentId, engagement.getVersion(), engagement.getStatus());
- String quillContent = jsonObject.getString("quillContent");
- String textContent = jsonObject.getString("textContent");
- String htmlContent = jsonObject.getString("htmlContent");
- engagement.setQuillContent(quillContent);
- engagement.setTextContent(textContent);
- engagement.setHtmlContent(htmlContent);
- try {
- int code = studentAssignmentMapper.updateById(engagement);
- if (code == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- log.info("[ENGAGE][STAGE] success assignmentId={}, studentId={}, version(after)={}, textLen={}",
- assignmentId, studentId, engagement.getVersion(),
- textContent == null ? -1 : textContent.length());
- // 异步启动文本分析,不影响主流程返回速度
- try {
- textAnalysisService.analyzeAndSaveTextContentAsync(studentId, assignmentId);
- log.info("已启动异步文本分析 - studentId: {}, assignmentId: {}", studentId, assignmentId);
- } catch (Exception e) {
- log.error("启动异步文本分析失败 - studentId: {}, assignmentId: {}, error: {}",
- studentId, assignmentId, e.getMessage());
- // 不抛出异常,避免影响主流程
- }
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
- }
- }
- @Override
- public void engagementCorrect(Long teacherId, Long studentId, Long assignmentId, CorrectDTO correctDTO) {
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
- if (engagement == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if (assignment == null)
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
- if (!Objects.equals(assignment.getTeacherId(), teacherId))
- throw MyException.create(HttpStatus.BAD_REQUEST, "无权限批改");
- if(engagement.getStatus() != AssignmentCompletionStatus.CORRECTED && engagement.getStatus() != AssignmentCompletionStatus.LATE_SUBMITTED_CORRECTED){
- assignment.setCorrectNumber(assignment.getCorrectNumber() + 1);
- if(engagement.getStatus() == AssignmentCompletionStatus.SUBMITTED){
- engagement.setStatus(AssignmentCompletionStatus.CORRECTED);
- } else if(engagement.getStatus() == AssignmentCompletionStatus.LATE_SUBMITTED){
- engagement.setStatus(AssignmentCompletionStatus.LATE_SUBMITTED_CORRECTED);
- }
- }
- engagement.setScore(correctDTO.getScore());
- engagement.setRemark(correctDTO.getRemark());
- try {
- int code = studentAssignmentMapper.updateById(engagement);
- int code1 = assignmentMapper.updateById(assignment);
- if (code == 0 || code1 == 0)
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "批改作业失败");
- } catch (Exception e) {
- log.error(e.getMessage());
- throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "批改作业失败");
- }
- }
- @Override
- public long getNextStudentId(Long assignmentId, Long studentId) {
- List<Engagement> allRecords = studentAssignmentMapper.selectList(
- new QueryWrapper<Engagement>()
- .eq("assignment_id", assignmentId)
- .exists("""
- SELECT 1
- FROM assignment a
- JOIN course_student cs ON cs.course_id = a.course_id
- WHERE a.assignment_id = student_assignment.assignment_id
- AND cs.student_id = student_assignment.student_id
- """)
- );
- if (allRecords.isEmpty()) {
- throw MyException.create(HttpStatus.BAD_REQUEST, "当前作业没有可批改的在课学生");
- }
- // 对记录进行排序:status为4或6的记录排到最后,其他记录保持原始顺序
- List<Engagement> sortedList = allRecords.stream()
- .sorted(Comparator.comparing(
- e -> e.getStatus() == AssignmentCompletionStatus.PUBLISHED ||
- e.getStatus() == AssignmentCompletionStatus.CORRECTED
- )).toList();
- int currentIndex = -1;
- for (int i = 0; i < sortedList.size(); i++) {
- if (sortedList.get(i).getStudentId().equals(studentId)) {
- currentIndex = i;
- break;
- }
- }
- if (currentIndex == sortedList.size() - 1 || currentIndex == -1) {
- return sortedList.get(0).getStudentId();
- }
- return sortedList.get(currentIndex + 1).getStudentId();
- }
- @Override
- public EngageNumberVo getEngageNumber(Long assignmentId) {
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if(assignment == null){
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
- }
- return studentAssignmentMapper.countEngageNumberByCurrentClassStudents(assignmentId);
- }
- private Assignment convertToPO(AssignmentDTO assignmentDTO) {
- Assignment assignment = new Assignment();
- BeanUtils.copyProperties(assignmentDTO, assignment);
- if (assignmentDTO.getAttachments() != null)
- assignment.setAttachments(ConvertUtil.listToString(assignmentDTO.getAttachments()));
- return assignment;
- }
- private Assignment convertToPO(AssignmentUpdateDTO assignmentDTO) {
- Assignment assignment = new Assignment();
- BeanUtils.copyProperties(assignmentDTO, assignment);
- if (assignmentDTO.getAttachments() != null)
- assignment.setAttachments(ConvertUtil.listToString(assignmentDTO.getAttachments()));
- return assignment;
- }
- private AssignmentVO convertToVO(Assignment assignment) {
- AssignmentVO res = new AssignmentVO();
- BeanUtils.copyProperties(assignment, res);
- if (assignment.getAttachments() != null)
- res.setAttachments(ConvertUtil.stringToList(assignment.getAttachments(), String::valueOf));
- res.setStatus(calculateStatus(res.getStartTime(), res.getEndTime()));
- // 组装老师姓名
- res.setTeacherName(userMapper.selectNameById(assignment.getTeacherId()));
- return res;
- }
- private EngagementVO convertToVO(Engagement engagement) {
- EngagementVO res = ModelMapperUtil.map(engagement, EngagementVO.class);
- // 组装文件key
- // res.setFileKey(res.getAssignmentId() + "_" + res.getStudentId() + "_" + res.getVersion());
- // 组装学生姓名
- String studentName = userMapper.selectNameById(engagement.getStudentId());
- res.setStudentName(studentName);
- return res;
- }
- private void recordHistorySnapshot(Engagement engagement) {
- // 检查是否已存在相同版本的历史记录
- StudentAssignmentHistory existingHistory = studentAssignmentMapper.findHistoryByAssignmentIdAndStudentIdAndVersion(
- engagement.getAssignmentId(), engagement.getStudentId(), engagement.getVersion());
- if (existingHistory != null) {
- log.info("历史记录已存在,跳过插入 - assignmentId: {}, studentId: {}, version: {}",
- engagement.getAssignmentId(), engagement.getStudentId(), engagement.getVersion());
- return;
- }
- StudentAssignmentHistory history = new StudentAssignmentHistory();
- history.setAssignmentId(engagement.getAssignmentId());
- history.setStudentId(engagement.getStudentId());
- history.setVersion(engagement.getVersion());
- history.setStatus(engagement.getStatus());
- history.setQuillContent(engagement.getQuillContent());
- history.setTextContent(engagement.getTextContent());
- history.setHtmlContent(engagement.getHtmlContent());
- history.setSubmitTime(new Date());
- studentAssignmentMapper.insertHistory(history);
- log.info("历史记录插入成功 - assignmentId: {}, studentId: {}, version: {}",
- engagement.getAssignmentId(), engagement.getStudentId(), engagement.getVersion());
- }
- private AssignmentStatus calculateStatus(Date startTime, Date endTime) {
- Date now = new Date();
- if (now.before(startTime)) {
- return AssignmentStatus.NOT_STARTED;
- } else if (now.after(endTime)) {
- return AssignmentStatus.FINISHED;
- } else {
- return AssignmentStatus.PROCEEDING;
- }
- }
- @Override
- public List<StudentAssignmentStatusVO> getStudentsAssignmentStatus(Long classId, Long assignmentId) {
- // 1. 验证班级和作业存在性
- Assignment assignment = assignmentMapper.selectById(assignmentId);
- if (assignment == null) {
- throw new RuntimeException("作业不存在"); // 建议替换为项目自定义异常
- }
- // 2. 获取班级所有学生(从class_student表)
- List<StudentInfoVO> classStudents = classService.getStudentsByClassId(classId);
- if (classStudents.isEmpty()) {
- return Collections.emptyList();
- }
- // 3. 提取学号列表,查询对应的用户ID(users表)
- List<String> officialNumbers = classStudents.stream()
- .map(StudentInfoVO::getOfficialNumber)
- .collect(Collectors.toList());
- List<User> users = userMapper.selectUserIdByOfficialNumbers(officialNumbers);
- Map<String, Long> officialNumberToUserIdMap = users.stream()
- .collect(Collectors.toMap(
- User::getOfficialNumber,
- User::getId
- ));
- // 4. 查询这些学生的作业提交情况(student_assignment表)
- List<Long> studentIds = new ArrayList<>(officialNumberToUserIdMap.values());
- List<StudentAssignment> studentAssignments = studentAssignmentMapper.findByAssignmentIdAndStudentIds(assignmentId, studentIds);
- // 5. 构建学生ID到作业情况的映射
- Map<Long, StudentAssignment> studentIdToAssignmentMap = studentAssignments.stream()
- .collect(Collectors.toMap(
- StudentAssignment::getStudentId,
- Function.identity()
- ));
- // 6. 组装返回结果
- return classStudents.stream()
- .map(student -> {
- StudentAssignmentStatusVO vo = new StudentAssignmentStatusVO();
- vo.setOfficialNumber(student.getOfficialNumber());
- vo.setStuName(student.getStuName());
- // 设置学生ID
- Long studentId = officialNumberToUserIdMap.get(student.getOfficialNumber());
- vo.setStudentId(studentId);
- // 设置状态和成绩
- StudentAssignment studentAssignment = studentIdToAssignmentMap.get(studentId);
- if (studentAssignment == null) {
- // 未参与作业,按未提交处理
- vo.setStatus(AssignmentCompletionStatus.NOT_SUBMITTED);
- vo.setScore(0);
- } else {
- // 转换状态为枚举
- vo.setStatus(AssignmentCompletionStatus.fromValue(studentAssignment.getStatus()));
- // 处理成绩(BigDecimal转Integer,未批改为0)
- vo.setScore(studentAssignment.getScore() != null ?
- studentAssignment.getScore().intValue() : 0);
- }
- return vo;
- })
- .collect(Collectors.toList());
- }
- }
|