Sfoglia il codice sorgente

1.4邮件输出word

Crazy 5 giorni fa
parent
commit
12cc3ae66a

+ 155 - 139
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java

@@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.xwpf.usermodel.*;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -65,7 +66,7 @@ public class MailTemplateController {
     @Operation(summary = "定时发送邮件给导师")
     public void sendMailToTeacherScheduled() {
         try {
-            sendExcelMailToTeacher();
+            sendWordMailToTeacher();
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -137,9 +138,9 @@ public class MailTemplateController {
                 sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
     }
 
-    @PostMapping("/sendExcelToTeacher")
-    @Operation(summary = "发送Excel给导师")
-    public void sendExcelMailToTeacher() throws IOException {
+    @PostMapping("/sendWordToTeacher")
+    @Operation(summary = "发送Word给导师")
+    public void sendWordMailToTeacher() throws IOException {
         // 获取导师
         Set<Long> collegeIdList =  permissionService.getUserListByRoleId(113L);
         List<AdminUserDO> TeacherList = adminUserService.getUserList(collegeIdList);
@@ -168,30 +169,50 @@ public class MailTemplateController {
 //                        studentAttendanceService.getStudentAttendanceExcusedListForTeacher(pageReqVO.setSupervisorId(getLoginUserId())),
 //                        StudentAttendanceSupervisorTemplateVO.class
 //                );
-                // 创建 ByteArrayOutputStream 用来存储 Excel 文件数据
-                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 
-                // 写入 Excel 文件
-                try (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream, StudentAttendanceSupervisorTemplateVO.class).build()) {
-                    WriteSheet writeSheetNormal = EasyExcel.writerSheet("正常打卡信息").build();
-                    WriteSheet writeSheetError = EasyExcel.writerSheet("未打卡信息").build();
-//                    WriteSheet writeSheetExcused = EasyExcel.writerSheet("请假信息").build();
-                    excelWriter.write(errorList, writeSheetError);
-                    // 将各个 List 数据写入不同的 Sheet 中
-                    excelWriter.write(normalList, writeSheetNormal);
 
-//                    excelWriter.write(excusedList, writeSheetExcused);
-                }
+                // 创建 ByteArrayOutputStream 用来存储 Word 文件数据
+                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+                   // 创建 Word 文档
+                XWPFDocument document = new XWPFDocument();
 
-                // 创建附件 Map
-                Map<String, InputStream> attachments = new HashMap<>();
-                // 使用 ByteArrayInputStream 来创建附件
-                attachments.put(teacher.getDeptName() + "_"  + yesterday + "_" + "工作间考勤信息.xlsx", new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
+                createParagraphWithRun(document, "测绘地理信息学院研究生考勤情况日报告", 16,  ParagraphAlignment.CENTER, 100,0);
+
+                createParagraphWithRun(document, "尊敬的"+teacher.getNickname()+"导师(家长):", 14,  ParagraphAlignment.LEFT, 100, UnderlinePatterns.SINGLE);
+
+                String dateInfoText = "         您所指导的研究生 " + yesterday.getYear() + " 年 " + yesterday.getMonthValue() + " 月 " + yesterday.getDayOfMonth() + " 日 考勤情况如下:";
+                createParagraphWithRun(document, dateInfoText, 14,  ParagraphAlignment.LEFT, 60,0);
+
+                // 未打卡同学清单标题
+                createParagraphWithRun(document, "未打卡同学清单", 14,  ParagraphAlignment.CENTER, 50,0);
+                // 未打卡同学数据填写
+                createAttendanceTable(document, errorList, false);
+
+
+                createParagraphWithRun(document, "特此通知,请您及时检查学生在校情况。", 14,  ParagraphAlignment.LEFT, 1000,0);
+
+                createParagraphWithRun(document, "测绘地理信息学院研究生管理委员会", 14,  ParagraphAlignment.RIGHT, 100,1000);
 
+                // 正常打卡同学清单标题
+                createParagraphWithRun(document, "正常打卡同学清单", 14,  ParagraphAlignment.CENTER, 0,0);
+                // 正常打卡同学数据填写
+                createAttendanceTable(document, normalList, true);
+
+                document.write(byteArrayOutputStream);
+
+                Map<String, InputStream> attachments = new HashMap<>();
+                String fileName = String.format("%s考勤信息.docx", (teacher.getDeptId()==null||teacher.getDeptId()==0?"":teacher.getDeptName())+yesterday);
+                attachments.put(fileName, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
                 // 发送邮件,包含附件
                 if (teacher.getEmail() != null) {
                     mailSendService.sendSingleMailToMemberWithAttachments(teacher.getEmail(), null, "attendance-list-excel", templateParams, attachments);
                 }
+                // 每次推送后等待0.1s
+                try {
+                    Thread.sleep(100);  // 0.1s
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
             }
         }
     }
@@ -441,9 +462,9 @@ public class MailTemplateController {
         }
     }
 
-    @PostMapping("/ceshiSendExcelToTeacher")
-    @Operation(summary = "测试发送Excel给老师")
-    public void ceshiSendExcelMail(@RequestParam("email") String email) throws IOException {
+    @PostMapping("/ceshiSendWordToTeacher")
+    @Operation(summary = "测试发送Word给老师")
+    public void ceshiSendWordMail(@RequestParam("email") String email) throws IOException {
 
         // 获取导师
         Set<Long> collegeIdList = permissionService.getUserListByRoleId(113L);
@@ -454,26 +475,21 @@ public class MailTemplateController {
 
         LocalDate yesterday = LocalDate.now().minusDays(1);
         if (TeacherList != null && !TeacherList.isEmpty()) {
-//            for (AdminUserDO teacher : TeacherList) {
-
+            for (AdminUserDO teacher : TeacherList) {
                 pageReqVO.setDate(yesterday);
-//                if (!(teacher.getDeptId() == null || teacher.getDeptId() == 0)) {
-//                    pageReqVO.setDeptId(teacher.getDeptId());
-//                }
+                if (!(teacher.getDeptId() == null || teacher.getDeptId() == 0)) {
+                    pageReqVO.setDeptId(teacher.getDeptId());
+                }
 
-//                List<StudentAttendanceSupervisorTemplateVO> normalList = BeanUtils.toBean(
-//                        studentAttendanceService.getStudentAttendanceListForTeacher(pageReqVO),
-//                        StudentAttendanceSupervisorTemplateVO.class
-//                );
+                List<StudentAttendanceSupervisorTemplateVO> normalList = BeanUtils.toBean(
+                        studentAttendanceService.getStudentAttendanceListForTeacher(pageReqVO.setSupervisorId(teacher.getId())),
+                        StudentAttendanceSupervisorTemplateVO.class
+                );
 
-                List<StudentAttendanceSupervisorTemplateVO> errorList = studentAttendanceService.getStudentAttendanceErrorListForTeacher(pageReqVO.setSupervisorId(590L))
-                        .stream()
-                        .map(studentAttendance -> {
-                            StudentAttendanceSupervisorTemplateVO vo = BeanUtils.toBean(studentAttendance, StudentAttendanceSupervisorTemplateVO.class);
-                            vo.setClockInTime("未打卡");
-                            return vo;
-                        })
-                        .collect(Collectors.toList());
+                List<StudentAttendanceSupervisorTemplateVO> errorList = BeanUtils.toBean(
+                        studentAttendanceService.getStudentAttendanceErrorListForTeacher(pageReqVO.setSupervisorId(teacher.getId())),
+                        StudentAttendanceSupervisorTemplateVO.class
+                );
 
 //                List<StudentAttendanceSupervisorTemplateVO> excusedList = studentAttendanceService.getStudentAttendanceExcusedListForTeacher(pageReqVO)
 //                        .stream()
@@ -485,111 +501,40 @@ public class MailTemplateController {
 //                        .collect(Collectors.toList());
 
                 // 创建 ByteArrayOutputStream 用来存储 Word 文件数据
-                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-
+            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 // 创建 Word 文档
-                XWPFDocument document = new XWPFDocument();
+            XWPFDocument document = new XWPFDocument();
 
-                XWPFParagraph title = document.createParagraph();
-                XWPFRun titleRun = title.createRun();
-                titleRun.setText("测绘地理信息学院研究生考勤情况日报告");
-                titleRun.setBold(true);
-                titleRun.setFontSize(16);
-                title.setAlignment(ParagraphAlignment.CENTER); // 设置标题居中
-                title.setSpacingAfter(100);
-
-
-                XWPFParagraph teacherInfo = document.createParagraph();
-                XWPFRun teacherInfoRun = teacherInfo.createRun();
-//                teacherInfoRun.setText("尊敬的" + teacher.getNickname() + "导师(家长):");
-                teacherInfoRun.setText("尊敬的" + "何宏昌" + "导师(家长):");
-                teacherInfoRun.setFontSize(14);
-                teacherInfoRun.setBold(true);
-                teacherInfo.setAlignment(ParagraphAlignment.LEFT);
-                teacherInfoRun.setUnderline(UnderlinePatterns.SINGLE);
-                teacherInfo.setSpacingAfter(100);
-
-                XWPFParagraph dateInfo = document.createParagraph();
-                XWPFRun dateInfoRun = dateInfo.createRun();
-                dateInfoRun.setText("         您所指导的研究生 " + yesterday.getYear() + "  年  " + yesterday.getMonthValue() + "  月  " + yesterday.getDayOfMonth() + " 日 考勤情况如下:");
-                dateInfoRun.setFontSize(14);
-                dateInfoRun.setBold(true);
-                dateInfo.setAlignment(ParagraphAlignment.LEFT);
-                dateInfo.setSpacingAfter(60);
-
-                XWPFParagraph listTitle = document.createParagraph();
-                XWPFRun listTitleRun = listTitle.createRun();
-                listTitleRun.setText("未打卡同学清单");
-                listTitleRun.setBold(true);
-                listTitleRun.setFontSize(14);
-                listTitle.setAlignment(ParagraphAlignment.CENTER);
-                listTitle.setSpacingAfter(50);
-
-                XWPFTable tableError = document.createTable();
-                //设置表格样式
-//                tableError.getCTTbl().getTblPr().set
-
-                tableError.setWidth(XWPFTable.DEFAULT_PERCENTAGE_WIDTH);
-
-                XWPFTableRow headerRowError = tableError.getRow(0);
-                headerRowError.getCell(0).setText("序号");
-                headerRowError.addNewTableCell().setText("学生姓名");
-                headerRowError.addNewTableCell().setText("学生学号");
-                headerRowError.addNewTableCell().setText("所在实验室房号");
-                headerRowError.addNewTableCell().setText("备注");
-
-                // 设置表头字体大小和加粗
-                for (XWPFTableCell cell : headerRowError.getTableCells()) {
-                    XWPFRun run = cell.addParagraph().createRun();
-                    run.setText(cell.getText());
-                    run.setFontSize(14); // 设置字体大小为14
-                    run.setBold(true); // 设置字体加粗
-                }
+            createParagraphWithRun(document, "测绘地理信息学院研究生考勤情况日报告", 16,  ParagraphAlignment.CENTER, 100,0);
 
-                int sequenceNumber = 1; // 序号初始化
-                for (StudentAttendanceSupervisorTemplateVO vo : errorList) {
-
-                    XWPFTableRow row = tableError.createRow();
-                    // 填充数据
-                    row.getCell(0).setText(String.valueOf(sequenceNumber++));
-                    row.getCell(1).setText(vo.getStudentName());
-                    row.getCell(2).setText(vo.getUserNumber());
-                    row.getCell(3).setText(vo.getDeptName());
-                    row.getCell(4).setText(vo.getRemark()); //
-
-                    // 设置内容字体大小
-                    for (XWPFTableCell cell : row.getTableCells()) {
-                        XWPFRun run = cell.addParagraph().createRun();
-                        run.setText(cell.getText());
-                        run.setFontSize(12); // 设置字体大小为12
-                    }
-                }
+            createParagraphWithRun(document, "尊敬的"+teacher.getNickname()+"导师(家长):", 14,  ParagraphAlignment.LEFT, 100, UnderlinePatterns.SINGLE);
 
-                XWPFParagraph notice = document.createParagraph();
-                XWPFRun noticeRun = notice.createRun();
-                noticeRun.setText("特此通知,请您及时检查学生在校情况。");
-                noticeRun.setFontSize(14);
-                noticeRun.setBold(true);
-                notice.setAlignment(ParagraphAlignment.LEFT);
-                notice.setSpacingBefore(100);
-
-                XWPFParagraph committee = document.createParagraph();
-                XWPFRun committeeRun = committee.createRun();
-                committeeRun.setText("测绘地理信息学院研究生管理委员会");
-                committeeRun.setFontSize(14);
-                committeeRun.setBold(true);
-                committee.setAlignment(ParagraphAlignment.RIGHT);
-                committee.setSpacingBefore(1000);
+            String dateInfoText = "         您所指导的研究生 " + yesterday.getYear() + " 年 " + yesterday.getMonthValue() + " 月 " + yesterday.getDayOfMonth() + " 日 考勤情况如下:";
+            createParagraphWithRun(document, dateInfoText, 14,  ParagraphAlignment.LEFT, 60,0);
 
-                document.write(byteArrayOutputStream);
+            createParagraphWithRun(document, "未打卡同学清单", 14,  ParagraphAlignment.CENTER, 50,0);
 
-                Map<String, InputStream> attachments = new HashMap<>();
-//                String fileName = String.format("%s考勤信息.docx", (teacher.getDeptId()==null||teacher.getDeptId()==0?"":teacher.getDeptName())+yesterday);
-                    String fileName = String.format("%s考勤信息.docx", yesterday);
-                attachments.put(fileName, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
+            createAttendanceTable(document, errorList, false);
 
+
+            createParagraphWithRun(document, "特此通知,请您及时检查学生在校情况。", 14,  ParagraphAlignment.LEFT, 1000,0);
+
+            createParagraphWithRun(document, "测绘地理信息学院研究生管理委员会", 14,  ParagraphAlignment.RIGHT, 100,1000);
+
+            // 正常打卡同学清单标题
+            createParagraphWithRun(document, "正常打卡同学清单", 14,  ParagraphAlignment.CENTER, 0,0);
+            // 正常打卡同学数据填写
+            createAttendanceTable(document, normalList, true);
+
+            document.write(byteArrayOutputStream);
+
+            // 创建附件并将文件保存
+            Map<String, InputStream> attachments = new HashMap<>();
+//            String fileName = String.format("%s考勤信息.docx", (teacher.getDeptId()==null||teacher.getDeptId()==0?"":teacher.getDeptName())+yesterday);
+            String fileName = String.format("%s考勤信息.docx", yesterday);
+            attachments.put(fileName, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
                 // 发送邮件
-//                if (teacher.getEmail() != null) {
+                if (teacher.getEmail() != null) {
                     mailSendService.sendSingleMailToMemberWithAttachments(email, null, "attendance-list-excel", templateParams, attachments);
                 }
                 // 每次推送后等待1s
@@ -598,8 +543,8 @@ public class MailTemplateController {
                 } catch (InterruptedException e) {
                     throw new RuntimeException(e);
                 }
-//            }
-//        }
+            }
+        }
     }
 
     @PostMapping("/ceshiExcelToCollege")
@@ -676,4 +621,75 @@ public class MailTemplateController {
     }
 
 
+    // 方法: 创建带有文本的段落
+    private void createParagraphWithRun(XWPFDocument document, String text, int fontSize,  ParagraphAlignment alignment, int spacingAfter,int spacingBefore) {
+        XWPFParagraph paragraph = document.createParagraph();
+        XWPFRun run = paragraph.createRun();
+        run.setText(text);
+        run.setFontSize(fontSize);
+        run.setBold(true);
+        paragraph.setAlignment(alignment);
+        paragraph.setSpacingAfter(spacingAfter);
+        paragraph.setSpacingBefore(spacingBefore);
+    }
+
+    // 方法: 创建带有文本和下划线的段落
+    private void createParagraphWithRun(XWPFDocument document, String text, int fontSize,  ParagraphAlignment alignment, int spacingAfter, UnderlinePatterns underlinePattern) {
+        XWPFParagraph paragraph = document.createParagraph();
+        XWPFRun run = paragraph.createRun();
+        run.setText(text);
+        run.setFontSize(fontSize);
+        run.setBold(true);
+        run.setUnderline(underlinePattern);
+        paragraph.setAlignment(alignment);
+        paragraph.setSpacingAfter(spacingAfter);
+    }
+
+    // 方法: 创建表格并填充数据
+    private void createAttendanceTable(XWPFDocument document, List<StudentAttendanceSupervisorTemplateVO> dataList, boolean isNormalList) {
+        XWPFTable table = document.createTable();
+        table.setWidth(XWPFTable.DEFAULT_PERCENTAGE_WIDTH);
+
+        // 设置表头
+        XWPFTableRow headerRow = table.getRow(0);
+        headerRow.getCell(0).setText("序号");
+        headerRow.addNewTableCell().setText("学生姓名");
+        headerRow.addNewTableCell().setText("学生学号");
+        headerRow.addNewTableCell().setText("所在实验室房号");
+        String extraColumn = isNormalList ? "打卡时间" : "备注";
+        headerRow.addNewTableCell().setText(extraColumn);
+
+        // 设置表头样式
+        for (XWPFTableCell cell : headerRow.getTableCells()) {
+            XWPFParagraph paragraph = cell.getParagraphs().get(0);
+            XWPFRun run = paragraph.createRun();
+            run.setText(cell.getText());
+            run.setFontSize(12);
+            run.setBold(true);
+            run.setFontFamily("宋体");
+            paragraph.setAlignment(ParagraphAlignment.CENTER);
+        }
+
+        // 填充数据
+        int sequenceNumber = 1;
+        for (StudentAttendanceSupervisorTemplateVO vo : dataList) {
+            XWPFTableRow row = table.createRow();
+            row.getCell(0).setText(String.valueOf(sequenceNumber++));
+            row.getCell(1).setText(vo.getStudentName());
+            row.getCell(2).setText(vo.getUserNumber());
+            row.getCell(3).setText(vo.getDeptName());
+            row.getCell(4).setText(isNormalList ? vo.getClockInTime() : vo.getRemark());
+
+            // 设置数据行样式
+            for (XWPFTableCell cell : row.getTableCells()) {
+                XWPFParagraph paragraph = cell.getParagraphs().get(0);
+                XWPFRun run = paragraph.createRun();
+                run.setText(cell.getText());
+                run.setFontSize(12);
+                run.setFontFamily("宋体");
+                paragraph.setAlignment(ParagraphAlignment.CENTER);
+            }
+        }
+    }
+
 }

+ 26 - 11
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/StudentAttendanceSupervisorTemplateVO.java

@@ -5,36 +5,51 @@ import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
 @Schema(description = "管理后台 - 邮件学生考勤信息模版的Response VO")
 @Data
 public class StudentAttendanceSupervisorTemplateVO {
 
 
     @Schema(description = "学生名字")
-//    @ColumnWidth(20)
-//    @ExcelProperty(value = "学生名字")
+    @ColumnWidth(20)
+    @ExcelProperty(value = "学生名字")
     private String studentName;
 
     @Schema(description = "学生学号")
-//    @ColumnWidth(20)
-//    @ExcelProperty(value = "学生学号")
+    @ColumnWidth(20)
+    @ExcelProperty(value = "学生学号")
     private String userNumber;
 
     @Schema(description = "工作间名称")
-//    @ColumnWidth(20)
-//    @ExcelProperty(value = "工作间名称")
+    @ColumnWidth(20)
+    @ExcelProperty(value = "工作间名称")
     private String deptName;
 
     @Schema(description = "日期")
-//    @ColumnWidth(20)
-//    @ExcelProperty(value = "日期")
+    @ColumnWidth(20)
+    @ExcelProperty(value = "日期")
     private String date;
 
     @Schema(description = "打卡时间")
-//    @ColumnWidth(20)
-//    @ExcelProperty(value = "打卡时间")
-    private String clockInTime;
+    @ColumnWidth(20)
+    @ExcelProperty(value = "打卡时间")
+    private LocalDateTime clockInTime;
 
     @Schema(description = "备注")
+    @ColumnWidth(20)
+    @ExcelProperty(value = "打卡时间")
     private String remark;
+
+    // Getter 方法,直接返回格式化后的字符串
+    public String getClockInTime() {
+        if (clockInTime != null) {
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            return clockInTime.format(formatter);
+        }
+        return null;  // 如果 clockInTime 为空,返回 null 或者可以返回空字符串 ""
+    }
+
 }