Explorar o código

feat:完成批量下载学生作业功能

baiqi hai 1 ano
pai
achega
c8eb729690

+ 10 - 8
src/main/java/com/njuzr/eaibackend/controller/ExportController.java

@@ -1,18 +1,18 @@
 package com.njuzr.eaibackend.controller;
 
 import com.njuzr.eaibackend.service.ExportCompositionService;
+import com.njuzr.eaibackend.vo.UserVO;
 import freemarker.template.TemplateException;
+import org.apache.commons.lang3.tuple.Pair;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 @RestController
@@ -24,12 +24,14 @@ public class ExportController {
     @GetMapping("/composition/word")
     public ResponseEntity<byte[]> exportWord(@RequestParam Long assignmentId, @RequestParam Long studentId) throws TemplateException, IOException {
 
-        byte[] wordBytes = exportCompositionService.exportWord(1L,1L);
+        Pair<UserVO, byte[]> pair = exportCompositionService.exportWord(assignmentId, studentId);
+        UserVO student = pair.getLeft();
+        byte[] wordBytes = pair.getRight();
 
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
         headers.setContentDispositionFormData("attachment",
-                URLEncoder.encode("作业" + ".docx", "UTF-8"));
+                URLEncoder.encode(String.format("%s_%s.%s", student.getName(), student.getOfficialNumber(), "docx"), StandardCharsets.UTF_8));
 
         return ResponseEntity.ok()
                 .headers(headers)
@@ -37,9 +39,9 @@ public class ExportController {
     }
 
     @GetMapping("/composition/zip")
-    public ResponseEntity<byte[]> exportBatch(@RequestParam Long assignmentId, @RequestParam Long studentId) {
+    public ResponseEntity<byte[]> exportBatch(@RequestParam Long assignmentId, @RequestParam(required = false) List<Long> studentIds) {
 
-        byte[] zipBytes = exportCompositionService.exportBatchToZip(List.of(studentId, 222L), assignmentId);
+        byte[] zipBytes = exportCompositionService.exportBatchToZip(studentIds, assignmentId);
 
         return ResponseEntity.ok()
                 .header(HttpHeaders.CONTENT_DISPOSITION,

+ 3 - 1
src/main/java/com/njuzr/eaibackend/mapper/EngagementMapper.java

@@ -3,7 +3,9 @@ package com.njuzr.eaibackend.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.njuzr.eaibackend.po.Engagement;
 import org.apache.ibatis.annotations.Mapper;
-// TODO:(柏琪)
+
+import java.util.List;
+
 /**
  * @author 柏琪
  * @date 2024-07-27 13:57

+ 21 - 0
src/main/java/com/njuzr/eaibackend/mapper/serviceIpml/EngagementMapperServiceImpl.java

@@ -0,0 +1,21 @@
+package com.njuzr.eaibackend.mapper.serviceIpml;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.njuzr.eaibackend.mapper.EngagementMapper;
+import com.njuzr.eaibackend.po.Engagement;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class EngagementMapperServiceImpl extends ServiceImpl<EngagementMapper, Engagement> {
+
+    public List<Engagement> getEngagementByAssignmentId(Long assignmentId) {
+        return this.lambdaQuery()
+                .eq(Engagement::getAssignmentId, assignmentId)
+                .list();
+    }
+
+
+}

+ 38 - 20
src/main/java/com/njuzr/eaibackend/service/ExportCompositionService.java

@@ -3,6 +3,7 @@ package com.njuzr.eaibackend.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.njuzr.eaibackend.exception.MyException;
 import com.njuzr.eaibackend.mapper.EngagementMapper;
+import com.njuzr.eaibackend.mapper.serviceIpml.EngagementMapperServiceImpl;
 import com.njuzr.eaibackend.po.Engagement;
 import com.njuzr.eaibackend.utils.WordExporter;
 import com.njuzr.eaibackend.utils.ZipExport;
@@ -10,22 +11,14 @@ import com.njuzr.eaibackend.vo.AssignmentVO;
 import com.njuzr.eaibackend.vo.EngagementVO;
 import com.njuzr.eaibackend.vo.UserVO;
 import freemarker.template.Configuration;
-import freemarker.template.Template;
 import freemarker.template.TemplateException;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Element;
-import org.jsoup.nodes.Node;
-import org.jsoup.nodes.TextNode;
+import org.apache.commons.lang3.tuple.Pair;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
-import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
+import org.springframework.util.CollectionUtils;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -44,34 +37,59 @@ public class ExportCompositionService {
     private UserService userService;
     @Autowired
     private WordExporter wordExporter;
+    @Autowired
+    private EngagementMapperServiceImpl engagementMapperServiceImpl;
 
-    public byte[] exportWordReal(Long assignmentId, Long studentId) {
+    public Pair<UserVO, byte[]> exportWord(Long assignmentId, Long studentId) {
         AssignmentVO assignment = assignmentService.findAssignmentById(assignmentId);
         EngagementVO engagement = assignmentService.getEngagement(studentId, assignmentId);
         UserVO user = userService.searchUsers(new Page<>(1,1), studentId, null, null, null).getRecords().get(0);
 
+        Map<String, Object> model = buildWordInfoModel(assignment, user, engagement);
+
+        return Pair.of(user, wordExporter.exportCompositionWord(model));
+
+    }
+
+    private Map<String, Object> buildWordInfoModel(AssignmentVO assignment, UserVO user, EngagementVO engagement) {
         Map<String, Object> model = new HashMap<>();
         model.put("title", assignment.getAssignmentName());
         model.put("studentName", user.getName());
+        model.put("officialNumber", user.getOfficialNumber());
         model.put("assignmentName", assignment.getAssignmentName());
         model.put("date", new Date());
         model.put("content", processContent(engagement.getTextContent()));
+        return model;
+    }
 
-        return wordExporter.exportCompositionWord(model);
+    public byte[] exportBatchToZip(List<Long> studentIds, Long assignmentId) {
+        if(assignmentId == null){
+            throw MyException.create(HttpStatus.BAD_REQUEST, "assignmentId不能为空");
+        }
 
+        if (CollectionUtils.isEmpty(studentIds)) {
+            List<Engagement> engagements = engagementMapperServiceImpl.getEngagementByAssignmentId(assignmentId);
+            if (CollectionUtils.isEmpty(engagements)) {
+                return null;
+            }
+            studentIds = engagements.stream()
+                    .map(Engagement::getStudentId)
+                    .toList();
+        }
+        return exportBatchToZipByStudentIds(studentIds, assignmentId);
     }
 
-    public byte[] exportBatchToZip(List<Long> studentIds, Long assignmentId) {
+    private byte[] exportBatchToZipByStudentIds(List<Long> studentIds, Long assignmentId) {
         List<ZipExport.ZipItem> zipItems = studentIds.stream()
-                .map(id -> {
+                .map(studentId -> {
                     try {
-                        byte[] wordBytes = exportWord(assignmentId, id);
-                        String fileName = String.format("%s_%d.docx",
-                                "作业", id);
-                        log.info("导出成功 studentId={}", id);
+                        Pair<UserVO, byte[]> pair = exportWord(assignmentId, studentId);
+                        UserVO student = pair.getLeft();
+                        byte[] wordBytes = pair.getRight();
+                        String fileName = String.format("%s_%s.%s", student.getName(), student.getOfficialNumber(), "docx");
                         return new ZipExport.ZipItem(fileName, wordBytes);
                     } catch (Exception e) {
-                        log.error("导出失败 studentId={}", id, e);
+                        log.error("exportBatchToZip failed, studentId: {}, reason: {}", studentId, e.getMessage());
                         return null;
                     }
                 })
@@ -86,7 +104,7 @@ public class ExportCompositionService {
     }
 
 
-    public byte[] exportWord(Long assignmentId, Long studentId) throws IOException, TemplateException {
+    public byte[] exportWordTest(Long assignmentId, Long studentId) throws IOException, TemplateException {
 
         String assignmentName = "My Favorite Season";
         String content = "My favorite season is autumn. The weather is cool and comfortable, and the leaves turn golden, making the scenery beautiful. I enjoy walking in the park and listening to the sound of rustling leaves. Autumn is also a harvest season, with fruits like apples and pears ripe for picking.\n" +

+ 2 - 4
src/main/resources/templates/composition.ftl

@@ -1,10 +1,8 @@
 <!DOCTYPE html>
 <html>
 <body>
-<h1>${title}</h1>
-<p>学生: ${studentName}</p>
-<p>班级: ${assignmentName}</p>
-<p>日期: ${date?string('yyyy-MM-dd')}</p>
+<p>姓名: ${studentName}</p>
+<p>学号: ${officialNumber}</p>
 <div>
     ${content}
 </div>