package com.njuzr.eaibackend.controller; import com.njuzr.eaibackend.mapper.UserMapper; import com.njuzr.eaibackend.po.User; import com.njuzr.eaibackend.service.ExportCompositionService; import com.njuzr.eaibackend.service.ExportBehaviorOverviewService; import com.njuzr.eaibackend.service.UserService; import com.njuzr.eaibackend.service.AssignmentService; import com.njuzr.eaibackend.service.ClassService; import com.njuzr.eaibackend.vo.UserVO; import com.njuzr.eaibackend.vo.AssignmentVO; import freemarker.template.TemplateException; import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ContentDisposition; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; @RestController @RequestMapping("/api/export") public class ExportController { @Autowired private ExportCompositionService exportCompositionService; @Autowired private ExportBehaviorOverviewService exportBehaviorOverviewService; @Autowired private UserService userService; @Autowired private UserMapper userMapper; @Autowired private AssignmentService assignmentService; @Autowired private ClassService classService; @GetMapping("/composition/word") public ResponseEntity exportWord(@RequestParam Long assignmentId, @RequestParam Long studentId) throws TemplateException, IOException { Pair 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(String.format("%s_%s.%s", student.getName(), student.getOfficialNumber(), "docx"), StandardCharsets.UTF_8)); return ResponseEntity.ok() .headers(headers) .body(wordBytes); } @GetMapping("/composition/zip") public ResponseEntity exportBatch(@RequestParam Long assignmentId, @RequestParam(required = false) List studentIds) { byte[] zipBytes = exportCompositionService.exportBatchToZip(studentIds, assignmentId); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=compositions.zip") .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(zipBytes); } @GetMapping("/behaviorOverview/excel") public ResponseEntity exportBehaviorOverviewExcel(@RequestParam Long assignmentId, @RequestParam Long studentId) { byte[] bytes = exportBehaviorOverviewService.exportBehaviorOverviewExcel(assignmentId, studentId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 查询学生信息 String name = null; String officialNumber = null; try { User user = userMapper.selectById(studentId); if (user != null) { name = user.getName(); officialNumber = user.getOfficialNumber(); } } catch (Exception ignored) { } // 查询作业名称 String assignmentName = null; try { AssignmentVO vo = assignmentService.findAssignmentById(assignmentId); assignmentName = vo != null ? vo.getAssignmentName() : null; } catch (Exception ignored) { } String fileName; if (name == null || name.isEmpty() || officialNumber == null) { fileName = String.format("行为数据记录_%d_%d.xlsx", studentId, assignmentId); } else if (assignmentName == null || assignmentName.isEmpty()) { fileName = String.format("行为数据记录_%s_%s.xlsx", officialNumber, name); } else { fileName = String.format("行为数据记录_%s_%s_%s.xlsx", officialNumber, name, assignmentName); } headers.setContentDisposition(ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build()); return ResponseEntity.ok() .headers(headers) .body(bytes); } @GetMapping("/behaviorOverview/excel/assignment") public ResponseEntity exportAssignmentBehaviorOverviewExcel(@RequestParam Long assignmentId) { byte[] bytes = exportBehaviorOverviewService.exportAssignmentBehaviorOverviewExcel(assignmentId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String assignmentName = null; try { AssignmentVO vo = assignmentService.findAssignmentById(assignmentId); assignmentName = vo != null ? vo.getAssignmentName() : null; } catch (Exception ignored) { } String fileName = assignmentName == null || assignmentName.isEmpty() ? String.format("行为数据记录_%d.xlsx", assignmentId) : String.format("行为数据记录_%d_%s.xlsx", assignmentId, assignmentName); headers.setContentDisposition(ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build()); return ResponseEntity.ok() .headers(headers) .body(bytes); } @GetMapping("/pauseStatistics/excel/assignment") public ResponseEntity exportAssignmentPauseStatisticsExcel( @RequestParam Long assignmentId, @RequestParam(defaultValue = "2000") Integer threshold) { byte[] bytes = exportBehaviorOverviewService.exportAssignmentPauseStatisticsExcel(assignmentId, threshold); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String assignmentName = null; try { AssignmentVO vo = assignmentService.findAssignmentById(assignmentId); assignmentName = vo != null ? vo.getAssignmentName() : null; } catch (Exception ignored) { } String fileName = assignmentName == null || assignmentName.isEmpty() ? String.format("pause_statistics_assignment_%d_threshold_%d.xlsx", assignmentId, threshold) : String.format("pause_statistics_assignment_%d_%s_threshold_%d.xlsx", assignmentId, assignmentName, threshold); headers.setContentDisposition(ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build()); return ResponseEntity.ok() .headers(headers) .body(bytes); } @GetMapping("/behaviorOverview/excel/class") public ResponseEntity exportClassBehaviorOverviewExcel(@RequestParam Long classId) { byte[] bytes = exportBehaviorOverviewService.exportClassBehaviorOverviewExcel(classId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String className = null; try { com.njuzr.eaibackend.po.Class cls = classService.getClassById(classId); className = cls != null ? cls.getClassName() : null; } catch (Exception ignored) { } String fileName = className == null || className.isEmpty() ? String.format("行为数据记录_%d.xlsx", classId) : String.format("行为数据记录_%d_%s.xlsx", classId, className); headers.setContentDisposition(ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build()); return ResponseEntity.ok() .headers(headers) .body(bytes); } @GetMapping("/class/download") public ResponseEntity downloadClassAssignments(@RequestParam Long classId) { byte[] zipBytes = exportCompositionService.downloadClassAssignments(classId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String className = null; try { com.njuzr.eaibackend.po.Class cls = classService.getClassById(classId); className = cls != null ? cls.getClassName() : null; } catch (Exception ignored) { } String fileName = className == null || className.isEmpty() ? String.format("class_%d_%s.zip", classId, new java.text.SimpleDateFormat("yyyyMMdd").format(new Date())) : String.format("%s_%s.zip", className, new java.text.SimpleDateFormat("yyyyMMdd").format(new Date())); ContentDisposition contentDisposition = ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build(); headers.setContentDisposition(contentDisposition); return ResponseEntity.ok() .headers(headers) .body(zipBytes); } @GetMapping("/assignment/download") public ResponseEntity downloadAssignmentSubmissions(@RequestParam Long assignmentId) { byte[] zipBytes = exportCompositionService.downloadAssignmentSubmissions(assignmentId); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String assignmentName = null; try { AssignmentVO vo = assignmentService.findAssignmentById(assignmentId); assignmentName = vo != null ? vo.getAssignmentName() : null; } catch (Exception ignored) { } String fileName = assignmentName == null || assignmentName.isEmpty() ? String.format("assignment_%d_%s.zip", assignmentId, new java.text.SimpleDateFormat("yyyyMMdd").format(new Date())) : String.format("%s_%s.zip", assignmentName, new java.text.SimpleDateFormat("yyyyMMdd").format(new Date())); ContentDisposition contentDisposition = ContentDisposition.builder("attachment") .filename(fileName, StandardCharsets.UTF_8) .build(); headers.setContentDisposition(contentDisposition); return ResponseEntity.ok() .headers(headers) .body(zipBytes); } }