AssignmentServiceImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. package com.njuzr.eaibackend.service.impl;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.baomidou.mybatisplus.core.metadata.IPage;
  5. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  6. import com.njuzr.eaibackend.dto.AssignmentDTO;
  7. import com.njuzr.eaibackend.dto.AssignmentQueryDTO;
  8. import com.njuzr.eaibackend.dto.AssignmentUpdateDTO;
  9. import com.njuzr.eaibackend.dto.CorrectDTO;
  10. import com.njuzr.eaibackend.enums.AssignmentCompletionStatus;
  11. import com.njuzr.eaibackend.enums.AssignmentStatus;
  12. import com.njuzr.eaibackend.enums.Role;
  13. import com.njuzr.eaibackend.exception.MyException;
  14. import com.njuzr.eaibackend.mapper.*;
  15. import com.njuzr.eaibackend.po.*;
  16. import com.njuzr.eaibackend.service.AssignmentService;
  17. import com.njuzr.eaibackend.utils.*;
  18. import com.njuzr.eaibackend.vo.AssignmentVO;
  19. import com.njuzr.eaibackend.vo.EngagementDetailVO;
  20. import com.njuzr.eaibackend.vo.EngagementVO;
  21. import com.njuzr.eaibackend.vo.UserVO;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.springframework.beans.BeanUtils;
  24. import org.springframework.http.HttpStatus;
  25. import org.springframework.stereotype.Service;
  26. import org.springframework.transaction.annotation.Transactional;
  27. import java.time.LocalDateTime;
  28. import java.util.*;
  29. /**
  30. * @author: Leonezhurui
  31. * @Date: 2024/3/15 - 00:40
  32. * @Package: EAI-Backend
  33. */
  34. @Slf4j
  35. @Service
  36. public class AssignmentServiceImpl implements AssignmentService {
  37. private final AssignmentMapper assignmentMapper;
  38. private final CourseMapper courseMapper;
  39. private final StudentAssignmentMapper studentAssignmentMapper;
  40. private final UserMapper userMapper;
  41. private final OssUtil ossUtil;
  42. private final FileUtil fileUtil = new FileUtil();
  43. public AssignmentServiceImpl(AssignmentMapper assignmentMapper,
  44. CourseMapper courseMapper,
  45. StudentAssignmentMapper studentAssignmentMapper,
  46. UserMapper userMapper,
  47. OssUtil ossUtil,
  48. CourseServiceImpl courseServiceImpl,
  49. CourseStudentMapper courseStudentMapper) {
  50. this.assignmentMapper = assignmentMapper;
  51. this.courseMapper = courseMapper;
  52. this.studentAssignmentMapper = studentAssignmentMapper;
  53. this.userMapper = userMapper;
  54. this.ossUtil = ossUtil;
  55. }
  56. @Override
  57. public AssignmentVO createAssignment(MyUserDetails user, Long courseId, AssignmentDTO assignmentDTO) {
  58. Course course = courseMapper.selectById(courseId);
  59. if (course == null)
  60. throw MyException.create(HttpStatus.BAD_REQUEST, "课程不存在");
  61. if (user.getRole() != Role.ADMIN) {
  62. List<String> teacherIds = Collections.singletonList(Optional.ofNullable(course.getTeacherIds())
  63. .orElse(Collections.emptyList().toString()));
  64. String userIdStr = String.valueOf(user.getId());
  65. boolean hasTeacherId = teacherIds.contains(userIdStr);
  66. boolean pidMatches = Objects.equals(course.getTeacherPid(), user.getPid());
  67. if (!hasTeacherId && !pidMatches) {
  68. throw MyException.create(HttpStatus.BAD_REQUEST, "无权限创建");
  69. }
  70. }
  71. Assignment target = convertToPO(assignmentDTO);
  72. target.setCourseId(courseId);
  73. // target.setTeacherId(user.getId());
  74. // TODO:权宜之计
  75. target.setTeacherId(Long.valueOf(user.getPid()));
  76. target.setCreateTime(new Date());
  77. try {
  78. int code = assignmentMapper.insert(target);
  79. if (code == 0)
  80. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "创建作业失败");
  81. } catch (Exception e) {
  82. log.error(e.getMessage());
  83. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "创建作业失败");
  84. }
  85. return convertToVO(target);
  86. }
  87. @Override
  88. public AssignmentVO findAssignmentById(Long assignmentId) {
  89. QueryWrapper<Assignment> wrapper = new QueryWrapper<>();
  90. wrapper.eq("assignment_id", assignmentId);
  91. Assignment res = assignmentMapper.selectOne(wrapper);
  92. if (res == null)
  93. throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
  94. return convertToVO(res);
  95. }
  96. @Override
  97. public IPage<AssignmentVO> findAssignmentPage(Page<Assignment> page, AssignmentQueryDTO assignmentQueryDTO) {
  98. QueryWrapper<Assignment> wrapper = new QueryWrapper<>();
  99. if (assignmentQueryDTO.getAssignmentId() != null) { // assignmentId直接判断是否相等
  100. // TODO 检测assignmentId是否正确
  101. wrapper.eq("assignmentId", assignmentQueryDTO.getAssignmentId());
  102. }
  103. if (assignmentQueryDTO.getTeacherId() != null) { // teacherId直接匹配
  104. wrapper.eq("teacher_id", assignmentQueryDTO.getTeacherId());
  105. }
  106. if (assignmentQueryDTO.getCourseId() != null) { // teacherId直接匹配
  107. wrapper.eq("course_id", assignmentQueryDTO.getCourseId());
  108. }
  109. if (assignmentQueryDTO.getAssignmentName() != null) { // 模糊匹配作业名字
  110. wrapper.like("assignment_name", assignmentQueryDTO.getAssignmentName());
  111. }
  112. if (assignmentQueryDTO.getStatus() != null) {
  113. AssignmentStatus status = assignmentQueryDTO.getStatus();
  114. if (status == AssignmentStatus.NOT_STARTED) {
  115. wrapper.gt("start_time", LocalDateTime.now()); // 意思是start_time > now()
  116. } else if (status == AssignmentStatus.PROCEEDING) {
  117. wrapper.le("start_time", LocalDateTime.now())
  118. .ge("end_time", LocalDateTime.now());
  119. } else {
  120. wrapper.lt("end_time", LocalDateTime.now());
  121. }
  122. }
  123. IPage<Assignment> assignments = assignmentMapper.selectPage(page, wrapper);
  124. return PageMapperUtil.convert(assignments, this::convertToVO);
  125. }
  126. @Override
  127. public AssignmentVO updateAssignment(MyUserDetails user, Long assignmentId, AssignmentUpdateDTO assignmentUpdateDTO) {
  128. Assignment target = assignmentMapper.selectById(assignmentId);
  129. if (!Objects.equals(target.getTeacherId(), user.getId()))
  130. throw MyException.create(HttpStatus.BAD_REQUEST, "无权限更新");
  131. Assignment ope = convertToPO(assignmentUpdateDTO);
  132. ope.setAssignmentId(assignmentId);
  133. try {
  134. int code = assignmentMapper.updateById(ope);
  135. if (code == 0)
  136. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "服务器更新失败");
  137. } catch (Exception e) {
  138. log.error(e.getMessage());
  139. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "服务器更新失败");
  140. }
  141. return convertToVO(assignmentMapper.selectById(assignmentId));
  142. }
  143. /**
  144. * 教师删除作业
  145. */
  146. @Override
  147. @Transactional
  148. public void deleteById(Long teacherId, Long assignmentId) {
  149. Assignment target = assignmentMapper.selectById(assignmentId);
  150. if (!Objects.equals(target.getTeacherId(), teacherId))
  151. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "无权限删除");
  152. try {
  153. List<Engagement> engagements = studentAssignmentMapper.findEngagementByAssignmentId(assignmentId);
  154. for(Engagement engagement : engagements) {
  155. studentAssignmentMapper.delete(engagement.getStudentId(), assignmentId);
  156. }
  157. int code = assignmentMapper.deleteById(assignmentId);
  158. if (code == 0) {
  159. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "删除作业错误");
  160. }
  161. } catch (Exception e) {
  162. log.error(e.getMessage());
  163. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "删除作业错误");
  164. }
  165. }
  166. @Override
  167. public void engageAssignment(Long studentId, Long assignmentId) {
  168. // 1创建Engagement实体类,初始化基本信息
  169. Engagement engagement = new Engagement();
  170. engagement.setStudentId(studentId);
  171. engagement.setAssignmentId(assignmentId);
  172. engagement.setVersion(1); // 设置这是version
  173. engagement.setStatus(AssignmentCompletionStatus.NOT_SUBMITTED); // 已经进入到页面编辑,但是还没有提交
  174. // // 2通过FileUtil创建一个空的docx文件
  175. // InputStream inputStream = fileUtil.createEmptyDocx();
  176. //
  177. // String filePath = assignmentId + "_" + studentId + ".docx";
  178. // // 3通过OssUtil工具类上传空文件,注意给其命名为`assignmentId/studentId.docx`,并得到文件链接
  179. // String fileName = ossUtil.uploadEnduringFile(inputStream, filePath);
  180. // engagement.setFileUrl(fileName);
  181. try {
  182. int code = studentAssignmentMapper.insert(engagement);
  183. if (code == 0)
  184. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "参加作业失败");
  185. } catch (Exception e) {
  186. log.error(e.getMessage());
  187. // ossUtil.deleteFile(filePath);
  188. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "参加作业失败");
  189. }
  190. }
  191. /**
  192. * 根据两个外键,搜索学生参与作业的情况(需要在mysql中设置索引)
  193. *
  194. * @param studentId
  195. * @param assignmentId
  196. * @return
  197. */
  198. @Override
  199. public EngagementVO getEngagement(Long studentId, Long assignmentId) {
  200. Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
  201. if (engagement == null)
  202. throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
  203. return convertToVO(engagement);
  204. }
  205. @Override
  206. public IPage<EngagementVO> findEngagementPage(Page<Engagement> page, Long assignmentId) {
  207. IPage<Engagement> engagements = studentAssignmentMapper.findEngagementByAssignmentId(page, assignmentId);
  208. return PageMapperUtil.convert(engagements, this::convertToVO);
  209. }
  210. @Override
  211. public EngagementDetailVO getDetailEngagement(Long studentId, Long assignmentId) {
  212. // 1 获取用户详细信息
  213. User student = userMapper.selectById(studentId);
  214. if (student == null)
  215. throw MyException.create(HttpStatus.BAD_REQUEST, "学生不存在");
  216. // 2 获取作业详细信息
  217. Assignment assignment = assignmentMapper.selectById(assignmentId);
  218. if (assignment == null)
  219. throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
  220. // 3 获取作业参与详细信息
  221. Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
  222. if (engagement == null)
  223. throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
  224. EngagementDetailVO detailVO = ModelMapperUtil.map(engagement, EngagementDetailVO.class);
  225. detailVO.setUserVO(ModelMapperUtil.map(student, UserVO.class));
  226. detailVO.setAssignmentVO(convertToVO(assignment));
  227. // detailVO.setFileKey(assignmentId + "_" + studentId + "_" + engagement.getVersion());
  228. log.info("请求到详细信息:" + detailVO);
  229. return detailVO;
  230. }
  231. /**
  232. * 作业提交,更新文件版本和作业状态
  233. *
  234. * @param studentId
  235. * @param assignmentId
  236. */
  237. @Override
  238. public void engagementSubmit(Long studentId, Long assignmentId) {
  239. Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
  240. if (engagement == null)
  241. throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
  242. int originalVersion = engagement.getVersion();
  243. engagement.setVersion(originalVersion + 1);
  244. engagement.setStatus(AssignmentCompletionStatus.SUBMITTED);
  245. try {
  246. int code = studentAssignmentMapper.updateById(engagement);
  247. if (code == 0)
  248. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
  249. } catch (Exception e) {
  250. log.error(e.getMessage());
  251. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
  252. }
  253. }
  254. /**
  255. * 作业暂存,更新文件版本,不修改作业状态
  256. *
  257. * @param studentId
  258. * @param assignmentId
  259. */
  260. @Override
  261. public void engagementStage(Long studentId, Long assignmentId, JSONObject jsonObject) {
  262. Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
  263. if (engagement == null)
  264. throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
  265. int originalVersion = engagement.getVersion();
  266. String quillContent = jsonObject.getString("quillContent");
  267. String textContent = jsonObject.getString("textContent");
  268. String htmlContent = jsonObject.getString("htmlContent");
  269. engagement.setVersion(originalVersion + 1);
  270. engagement.setQuillContent(quillContent);
  271. engagement.setTextContent(textContent);
  272. engagement.setHtmlContent(htmlContent);
  273. try {
  274. int code = studentAssignmentMapper.updateById(engagement);
  275. if (code == 0)
  276. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
  277. } catch (Exception e) {
  278. log.error(e.getMessage());
  279. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "更新文件版本失败");
  280. }
  281. }
  282. @Override
  283. public void engagementCorrect(Long teacherId, Long studentId, Long assignmentId, CorrectDTO correctDTO) {
  284. Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
  285. if (engagement == null)
  286. throw MyException.create(HttpStatus.BAD_REQUEST, "参与作业情况不存在");
  287. Assignment assignment = assignmentMapper.selectById(assignmentId);
  288. if (assignment == null)
  289. throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
  290. if (!Objects.equals(assignment.getTeacherId(), teacherId))
  291. throw MyException.create(HttpStatus.BAD_REQUEST, "无权限批改");
  292. engagement.setStatus(AssignmentCompletionStatus.CORRECTED); // 第一步,修改状态,改为已批改
  293. engagement.setScore(correctDTO.getScore());
  294. engagement.setRemark(correctDTO.getRemark());
  295. try {
  296. int code = studentAssignmentMapper.updateById(engagement);
  297. if (code == 0)
  298. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "批改作业失败");
  299. } catch (Exception e) {
  300. log.error(e.getMessage());
  301. throw MyException.create(HttpStatus.INTERNAL_SERVER_ERROR, "批改作业失败");
  302. }
  303. }
  304. private Assignment convertToPO(AssignmentDTO assignmentDTO) {
  305. Assignment assignment = new Assignment();
  306. BeanUtils.copyProperties(assignmentDTO, assignment);
  307. if (assignmentDTO.getAttachments() != null)
  308. assignment.setAttachments(ConvertUtil.listToString(assignmentDTO.getAttachments()));
  309. return assignment;
  310. }
  311. private Assignment convertToPO(AssignmentUpdateDTO assignmentDTO) {
  312. Assignment assignment = new Assignment();
  313. BeanUtils.copyProperties(assignmentDTO, assignment);
  314. if (assignmentDTO.getAttachments() != null)
  315. assignment.setAttachments(ConvertUtil.listToString(assignmentDTO.getAttachments()));
  316. return assignment;
  317. }
  318. private AssignmentVO convertToVO(Assignment assignment) {
  319. AssignmentVO res = new AssignmentVO();
  320. BeanUtils.copyProperties(assignment, res);
  321. if (assignment.getAttachments() != null)
  322. res.setAttachments(ConvertUtil.stringToList(assignment.getAttachments(), String::valueOf));
  323. res.setStatus(calculateStatus(res.getStartTime(), res.getEndTime()));
  324. // 组装老师姓名
  325. res.setTeacherName(userMapper.selectNameById(assignment.getTeacherId()));
  326. return res;
  327. }
  328. private EngagementVO convertToVO(Engagement engagement) {
  329. EngagementVO res = ModelMapperUtil.map(engagement, EngagementVO.class);
  330. // 组装文件key
  331. // res.setFileKey(res.getAssignmentId() + "_" + res.getStudentId() + "_" + res.getVersion());
  332. // 组装学生姓名
  333. String studentName = userMapper.selectNameById(engagement.getStudentId());
  334. res.setStudentName(studentName);
  335. return res;
  336. }
  337. private AssignmentStatus calculateStatus(Date startTime, Date endTime) {
  338. Date now = new Date();
  339. if (now.before(startTime)) {
  340. return AssignmentStatus.NOT_STARTED;
  341. } else if (now.after(endTime)) {
  342. return AssignmentStatus.FINISHED;
  343. } else {
  344. return AssignmentStatus.PROCEEDING;
  345. }
  346. }
  347. }