ydmyzx преди 2 месеца
родител
ревизия
f17bcd58c9
променени са 29 файла, в които са добавени 1529 реда и са изтрити 203 реда
  1. 11 2
      yudao-module-system/yudao-module-system-biz/pom.xml
  2. 456 64
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java
  3. 152 81
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/StudentSelectSupervisorRecordController.java
  4. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/vo/StudentSelectSupervisorRecordPageReqVO.java
  5. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/vo/StudentSelectSupervisorRecordRespVO.java
  6. 24 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectionProject/studentSelectionProjectController.java
  7. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/supervisorSelectionSettingController.java
  8. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/vo/supervisorBookRespVO.java
  9. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/vo/supervisorSelectionSettingRespVO.java
  10. 68 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
  11. 16 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java
  12. 4 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java
  13. 4 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java
  14. 5 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java
  15. 100 15
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/studentSelectSupervisorRecord/studentSelectSupervisorRecordMapper.java
  16. 2 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/studentSelectionProject/studentSelectionProjectMapper.java
  17. 2 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/supervisorSelectionSetting/supervisorSelectionSettingMapper.java
  18. 70 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java
  19. 22 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/studentSelectSupervisorRecord/studentSelectSupervisorRecordService.java
  20. 50 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/studentSelectSupervisorRecord/studentSelectSupervisorRecordServiceImpl.java
  21. 8 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/supervisorSelectionSetting/supervisorSelectionSettingService.java
  22. 8 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/supervisorSelectionSetting/supervisorSelectionSettingServiceImpl.java
  23. 12 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
  24. 42 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
  25. 251 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/PdfUtils.java
  26. 31 0
      yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/studentSelectSupervisorRecord/studentSelectSupervisorRecordMapper.xml
  27. 18 0
      yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/supervisorSelectionSetting/supervisorSelectionSettingMapper.xml
  28. 145 2
      yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/user/AdminUserMapper.xml
  29. 23 23
      yudao-server/src/main/resources/application-local.yaml

+ 11 - 2
yudao-module-system/yudao-module-system-biz/pom.xml

@@ -152,8 +152,17 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-protection</artifactId>
         </dependency>
-
-
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.5.13</version>
+        </dependency>
+        <!-- PDF中文支持 -->
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>2.0.28</version>
+        </dependency>
     </dependencies>
 
 </project>

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

@@ -18,9 +18,18 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.ExcelWriter;
 import com.alibaba.excel.write.metadata.WriteSheet;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.pdf.PdfWriter;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.xwpf.usermodel.*;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
@@ -28,14 +37,22 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.io.*;
 import java.math.BigInteger;
+import java.nio.file.Files;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.util.*;
+import java.util.List;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -66,7 +83,7 @@ public class MailTemplateController {
     @Operation(summary = "定时发送邮件给导师")
     public void sendMailToTeacherScheduled() {
         try {
-            sendWordMailToTeacher();
+            sendPDFMailToTeacher();
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -205,7 +222,6 @@ public class MailTemplateController {
                             .append("<br/>");
                 }
 
-
                 if (!errorList.isEmpty()) {
                     templateParams.put("errType","未打卡同学清单");
                     templateParams.put("errList",errorListBuilder);
@@ -244,7 +260,7 @@ public class MailTemplateController {
                 attachments.put(fileName, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
                 // 发送邮件,包含附件
                 if (teacher.getEmail() != null) {
-                    mailSendService.sendSingleMailToMemberWithAttachments(teacher.getEmail(), null, "attendance-list-word", templateParams, attachments);
+                    mailSendService.sendSingleMailToMemberWithAttachments("1473464808@qq.com", null, "attendance-list-word", templateParams, attachments);
                 }
                 // 每次推送后等待0.1s
                 try {
@@ -255,7 +271,255 @@ public class MailTemplateController {
             }
         }
     }
+    @PostMapping("/sendPDFToTeacher")
+    @Operation(summary = "发送PDF给导师")
+    public void sendPDFMailToTeacher() throws IOException {
+        // 获取导师
+        Set<Long> collegeIdList = permissionService.getUserListByRoleId(113L);
+        List<AdminUserDO> TeacherList = adminUserService.getUserList(collegeIdList);
+
+        StudentAttendancePageReqVO pageReqVO = new StudentAttendancePageReqVO();
+        Map<String, Object> templateParams = new HashMap<>(); // 模板参数设置
+
+        // 获取前一天
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+
+        if (TeacherList != null && !TeacherList.isEmpty()) {
+            for (AdminUserDO teacher : TeacherList) {
+                if (!(teacher.getDeptId() == null || teacher.getDeptId() == 0)) {
+                    pageReqVO.setDeptId(teacher.getDeptId());
+                }
+                if (!(teacher.getDeptId() == null || teacher.getDeptId() == 0)) {
+                    pageReqVO.setDeptId(teacher.getDeptId());
+                }
+                pageReqVO.setDate(yesterday);
+                List<StudentAttendanceSupervisorTemplateVO> normalList = BeanUtils.toBean(
+                        studentAttendanceService.getStudentAttendanceListForTeacher(pageReqVO.setSupervisorId(teacher.getId())),
+                        StudentAttendanceSupervisorTemplateVO.class
+                );
+                List<StudentAttendanceSupervisorTemplateVO> errorList = BeanUtils.toBean(
+                        studentAttendanceService.getStudentAttendanceErrorListForTeacher(pageReqVO.setSupervisorId(teacher.getId())),
+                        StudentAttendanceSupervisorTemplateVO.class
+                );
+                if (normalList.isEmpty() && errorList.isEmpty()) {
+                    if(!adminUserService.isSupervisorNullHasStudent(teacher.getId())){
+                        continue;
+                    }
+                }
+                templateParams.put("teacherName", teacher.getNickname());
+                templateParams.put("date",yesterday.toString());
+
+
+                StringBuilder normalListBuilder = new StringBuilder();
+                for (StudentAttendanceSupervisorTemplateVO attendance : normalList) {
+                    normalListBuilder
+                            .append(" 学生姓名: ").append(attendance.getStudentName())
+                            .append(" 学生学号: ").append(attendance.getUserNumber() != null ? attendance.getUserNumber() : "无")
+                            .append(" 打卡时间: ").append(attendance.getClockInTime() != null ? attendance.getClockInTime() : "未打卡")
+                            .append("<br/>");
+                }
+
+                StringBuilder errorListBuilder = new StringBuilder();
+                for (StudentAttendanceSupervisorTemplateVO attendance : errorList) {
+                    errorListBuilder
+                            .append(" 学生姓名: ").append(attendance.getStudentName())
+                            .append(" 学生学号: ").append(attendance.getUserNumber() != null ? attendance.getUserNumber() : "无")
+                            .append(" 打卡时间: ").append(attendance.getClockInTime() != null ? attendance.getClockInTime() : "未打卡")
+                            .append("<br/>");
+                }
+                Map<String, InputStream> attachments = new HashMap<>();
+
+                try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+                     PDDocument document = new PDDocument()) {
+
+                    PDPage page = new PDPage();
+                    document.addPage(page);
+                    // 提前创建 5 个流并存储在列表中
+                    List<PDPageContentStream> contentStreams = new ArrayList<>();
+                    contentStreams.add(new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true));
+                    for (int i = 0; i < 1; i++) {
+                        PDPage newPage = new PDPage();
+                        document.addPage(newPage);
+                        contentStreams.add(new PDPageContentStream(document, newPage, PDPageContentStream.AppendMode.APPEND, true, true));
+                    }
+
+                    PDFont font = PDType0Font.load(document, getClass().getResourceAsStream("/font/STXIHEI.TTF"));
+                // 使用第一个流写标题
+                    PDPageContentStream contentStream = contentStreams.get(0);
+                    // 页面宽度与高度
+                    float pageWidth = page.getMediaBox().getWidth();
+                    float pageHeight = page.getMediaBox().getHeight();
+
+                    // 设置初始 Y 坐标,页面顶部保留边距
+                    float margin = 50;
+                    float yPosition = pageHeight - margin;
+
+                    // 1. 添加标题
+                    String title = "测绘地理信息学院研究生考勤情况日报告";
+                    float titleWidth = font.getStringWidth(title) / 1000 * 16; // 字体宽度 * 字号
+                    float titleX = (pageWidth - titleWidth) / 2; // 居中显示
+                    contentStream.beginText();
+                    contentStream.setFont(font, 16);
+                    contentStream.newLineAtOffset(titleX, yPosition);
+                    contentStream.showText(title);
+                    contentStream.endText();
+                    yPosition -= 100; // 下移一行
+
+
+                    // 2. 添加老师称呼
+                    String teacherGreeting = "尊敬的" + teacher.getNickname() + "导师:";
+                    contentStream.beginText();
+                    contentStream.setFont(font, 14);
+                    contentStream.newLineAtOffset(50, yPosition); // 左对齐,X 偏移量 100
+                    contentStream.showText(teacherGreeting);
+                    contentStream.endText();
+                    yPosition -= 50; // 下移一行
+
+                    // 3. 添加日期信息段落
+                    String dateInfoText = "您所指导的研究生 " + yesterday.getYear() + " 年 " + yesterday.getMonthValue() + " 月 " + yesterday.getDayOfMonth() + " 日 考勤情况如下:";
+                    contentStream.beginText();
+                    contentStream.setFont(font, 14);
+                    contentStream.newLineAtOffset(50, yPosition); // 左对齐,X 偏移量 60
+                    contentStream.showText(dateInfoText);
+                    contentStream.endText();
+                    yPosition -= 30; // 下移一行
+
+                    String errlistName = "打卡异常同学清单";
+
+                    // 计算标题宽度以居中显示
+                    float errlistNameWidth = font.getStringWidth(errlistName) / 1000 * 16;
+                    float errlistNameX = (pageWidth - errlistNameWidth) / 2;
+
+
+                    contentStream.beginText();
+                    contentStream.setFont(font, 16); // 设置字体大小为 16
+                    contentStream.newLineAtOffset(errlistNameX, yPosition);
+                    contentStream.showText(errlistName);
+                    contentStream.endText();
+                    yPosition -= 30; // 下移高度
+
+                    if (!errorList.isEmpty()) {
+                        templateParams.put("errType","未打卡同学清单");
+                        templateParams.put("errList",errorListBuilder);
+                        yPosition = generatePDFWithTableUsingStreamPool(contentStreams, document, page, errorList, yPosition, font, false);
+                    } else {
+                        templateParams.put("errType","未打卡同学清单!");
+                        templateParams.put("errList","无");
+                        writeText(contentStream, "无", 100, yPosition, font);
+                        yPosition -= 30; // 下移高度
+                    }
+                    System.out.println(teacher.getNickname() + "我没进来"+ currentStreamIndex + contentStreams.size());
+
+                    if (yPosition < margin + 40) {
+                        currentStreamIndex++;
+                        // 如果流池已经用尽,则动态创建新的流
+                        if (currentStreamIndex >= contentStreams.size()) {
+                            System.out.println(teacher.getNickname() + "我进来了"+ currentStreamIndex + contentStreams.size());
+                            PDPage newPage = new PDPage();
+                            document.addPage(newPage);
+                            PDPageContentStream newStream = new PDPageContentStream(document, newPage, PDPageContentStream.AppendMode.APPEND, true, true);
+                            contentStreams.add(newStream);
+                        }
+                        // 切换到下一个流
+                        contentStream = contentStreams.get(currentStreamIndex);
+                        yPosition = pageHeight - margin;
+                    }
+
+                    contentStream = contentStreams.get(currentStreamIndex);
+
+                    String listName = "正常打卡同学清单";
+
+                    // 计算标题宽度以居中显示
+                    float listNameWidth = font.getStringWidth(listName) / 1000 * 16;
+                    float listNameX = (pageWidth - listNameWidth) / 2;
+
+
+                    contentStream.beginText();
+                    contentStream.setFont(font, 16); // 设置字体大小为 16
+                    contentStream.newLineAtOffset(listNameX, yPosition);
+                    contentStream.showText(listName);
+                    contentStream.endText();
+
+                    yPosition -= 20; // 下移高度
+
+                    // 添加正常打卡学生列表
+                    if (!normalList.isEmpty()) {
+                        templateParams.put("normaltype","正常打卡同学清单");
+                        templateParams.put("normalList",normalListBuilder);
+                        yPosition = generatePDFWithTableUsingStreamPool(contentStreams, document, page, normalList, yPosition, font, true);
+                    } else {
+                        templateParams.put("normaltype","正常打卡同学清单");
+                        templateParams.put("normalList","无");
+                        writeText(contentStream, "无", 100, yPosition, font);
+                        yPosition -= 30; // 下移高度
+                    }
+
+
+                    // 添加结尾
+                    String footer = "测绘地理信息学院研究生管理委员会";
+
+                    if (yPosition < margin + 40) {
+                        currentStreamIndex++;
+                        // 如果流池已经用尽,则动态创建新的流
+                        if (currentStreamIndex >= contentStreams.size()) {
+                            PDPage newPage = new PDPage();
+                            document.addPage(newPage);
+                            PDPageContentStream newStream = new PDPageContentStream(document, newPage, PDPageContentStream.AppendMode.APPEND, true, true);
+                            contentStreams.add(newStream);
+                        }
+                        // 切换到下一个流
+                        contentStream = contentStreams.get(currentStreamIndex);
+                        yPosition = pageHeight - margin;
+                    }
+                    contentStream = contentStreams.get(currentStreamIndex);
+                    // 写结尾
+                    writeText(contentStream, footer, 350, yPosition, font);
+
+                    // 关闭所有流
+                    for (PDPageContentStream stream : contentStreams) {
+                        if (stream != null) {
+                            stream.close();
+                        }
+                    }
+
+                    // 保存文档到输出流
+                    document.save(byteArrayOutputStream);
+                    // 保存文档到输出流
+                    String fileName = String.format("%s考勤信息.pdf", (teacher.getDeptId() == null || teacher.getDeptId() == 0 ? "" : teacher.getDeptName()) + yesterday);
+                    attachments.put(fileName, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    throw new RuntimeException("生成 PDF 时发生错误", e);
+                }
+                // 发送邮件,包含附件
+                if (teacher.getEmail() != null) {
+                    mailSendService.sendSingleMailToMemberWithAttachments(teacher.getEmail(), null, "attendance-list-word", templateParams, attachments);
+                    currentStreamIndex = 0;
+                }
+                // 每次推送后等待0.1秒
+                try {
+                    Thread.sleep(100);  // 0.1s
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
 
+    private void writeText(PDPageContentStream contentStream, String text, float x, float y, PDFont font) throws IOException {
+        if (contentStream == null) {
+            throw new IllegalStateException("ContentStream is null!");
+        }
+        if (font == null) {
+            throw new IllegalStateException("Font is null!");
+        }
+
+        contentStream.beginText();
+        contentStream.setFont(font, 12); // 默认字体大小
+        contentStream.newLineAtOffset(x, y);
+        contentStream.showText(text);
+        contentStream.endText();
+    }
     @PostMapping("/sendExcelToCollege")
     @Operation(summary = "发送Excel给学院")
     public void sendExcelMailToCollege() throws IOException {
@@ -683,6 +947,7 @@ public class MailTemplateController {
         paragraph.setSpacingAfter(spacingAfter);
     }
 
+
     // 方法: 创建表格并填充数据
     private void createAttendanceTable(XWPFDocument document, List<StudentAttendanceSupervisorTemplateVO> dataList, boolean isNormalList) {
         XWPFTable table = document.createTable();
@@ -730,77 +995,204 @@ public class MailTemplateController {
         }
     }
 
-
-    /**
-     * 生成用于展示的考勤报告文字内容
-     *
-     * @param teacher    导师信息
-     * @param normalList 正常打卡学生列表
-     * @param errorList  未打卡学生列表
-     * @param date       报告日期
-     * @return 生成的文字内容
-     */
-    public String generateAttendanceReportText(AdminUserDO teacher,
-                                               List<StudentAttendanceSupervisorTemplateVO> normalList,
-                                               List<StudentAttendanceSupervisorTemplateVO> errorList,
-                                               LocalDate date) {
-        StringBuilder report = new StringBuilder();
-
-        // 标题
-        report.append("测绘地理信息学院研究生考勤情况日报告").append("\n\n");
-
-        // 问候语
-        report.append("尊敬的").append(teacher.getNickname()).append("老师:").append("\n\n");
-
-        // 时间信息
-        report.append("         您所指导的研究生 ")
-                .append(date.getYear()).append(" 年 ")
-                .append(date.getMonthValue()).append(" 月 ")
-                .append(date.getDayOfMonth()).append(" 日考勤情况如下:").append("\n\n");
-
-        // 未打卡学生清单
-        if (errorList != null && !errorList.isEmpty()) {
-            report.append("未打卡同学清单").append("\n");
-            report.append(generateAttendanceTable(errorList, false)).append("\n");
-            report.append("特此通知,请您及时检查学生在校情况。").append("\n\n");
-            report.append("测绘地理信息学院研究生管理委员会").append("\n");
-            report.append(date.toString()).append("\n\n");
-        } else {
-            report.append("您所指导的所有研究生今日已全部打卡!").append("\n\n");
-            report.append("测绘地理信息学院研究生管理委员会").append("\n");
-            report.append(date.toString()).append("\n\n");
+    private int currentStreamIndex = 0; // 用于记录当前使用的流索引
+    private float generatePDFWithTableUsingStreamPool(List<PDPageContentStream> contentStreams, PDDocument document, PDPage page,
+                                                      List<StudentAttendanceSupervisorTemplateVO> dataList,
+                                                      float yPosition, PDFont font, boolean isNormal) throws IOException {
+        float margin = 50;
+        float tableWidth = page.getMediaBox().getWidth() - 2 * margin; // 表格总宽度
+        float rowHeight = 20; // 每行高度
+        float yStartNewPage = page.getMediaBox().getHeight() - 50; // 新页面顶部位置
+        float cellMargin = 5; // 单元格内边距
+
+        float[] colWidths = {40, 100, 100, 100, 200}; // 列宽
+        String[] headers = {
+                "序号", "学生姓名", "学生学号", "实验室房号", isNormal ? "打卡时间" : "备注"
+        };
+
+        // 当前使用的流
+        PDPageContentStream contentStream = contentStreams.get(currentStreamIndex);
+
+        // 绘制表头
+        for (int i = 0; i < headers.length; i++) {
+            float cellX = margin + getColumnStartX(i, colWidths);
+            drawCell(contentStream, cellX, yPosition, colWidths[i], rowHeight, headers[i], font, true);
         }
+        yPosition -= rowHeight; // 下移一行
+
+
+        // 绘制表格内容
+        int index = 1;
+        for (StudentAttendanceSupervisorTemplateVO data : dataList) {
+            System.out.println( "生成表格中!!"+ currentStreamIndex + contentStreams.size());
+
+            if (yPosition < margin + rowHeight) {
+                currentStreamIndex++;
+                 // 如果流池已经用尽,则动态创建新的流
+                if (currentStreamIndex >= contentStreams.size()) {
+                    PDPage newPage = new PDPage();
+                    document.addPage(newPage);
+                    PDPageContentStream newStream = new PDPageContentStream(document, newPage, PDPageContentStream.AppendMode.APPEND, true, true);
+                    contentStreams.add(newStream);
+                }
+                 // 切换到下一个流
+                contentStream = contentStreams.get(currentStreamIndex);
+                yPosition = yStartNewPage;
+
+                for (int i = 0; i < headers.length; i++) {
+                    float cellX = margin + getColumnStartX(i, colWidths);
+                    drawCell(contentStream, cellX, yPosition, colWidths[i], rowHeight, headers[i], font, true);
+                }
+
+                yPosition -= rowHeight; // 下移一行
+            }
+
+            String[] rowData = {
+                    String.valueOf(index),
+                    data.getStudentName(),
+                    data.getUserNumber() != null ? data.getUserNumber() : "无",
+                    data.getDeptName() != null ? data.getDeptName() : "无",
+                    isNormal
+                            ? (data.getClockInTime() != null ? data.getClockInTime().toString() : "无")
+                            : (data.getRemark() != null ? data.getRemark() : "无")
+            };
+
+            for (int i = 0; i < rowData.length; i++) {
+                float cellX = margin + getColumnStartX(i, colWidths);
+                drawCell(contentStream, cellX, yPosition, colWidths[i], rowHeight, rowData[i], font, false);
+            }
 
-        // 正常打卡学生清单
-        report.append("正常打卡同学清单").append("\n");
-        report.append(generateAttendanceTable(normalList, true));
+            yPosition -= rowHeight; // 下移一行
+            index++;
+        }
+        yPosition -= 30; // 下移一行
+        return yPosition;
+    }
 
-        return report.toString();
+    private float getColumnStartX(int columnIndex, float[] colWidths) {
+        float x = 0;
+        for (int i = 0; i < columnIndex; i++) {
+            x += colWidths[i];
+        }
+        return x;
     }
+    private void drawCell(PDPageContentStream contentStream, float x, float y, float width, float height,
+                          String text, PDFont font, boolean isHeader) throws IOException {
 
-    /**
-     * 生成考勤表格内容
-     *
-     * @param dataList     学生考勤数据列表
-     * @param isNormalList 是否为正常打卡名单
-     * @return 表格文字内容
-     */
-    private String generateAttendanceTable(List<StudentAttendanceSupervisorTemplateVO> dataList, boolean isNormalList) {
-        StringBuilder table = new StringBuilder();
+        if (contentStream == null) {
+            throw new IllegalStateException("contentStream is null in drawCell method.");
+        }
 
-        // 表头
-        table.append(String.format("%-5s%-10s%-15s%-15s%-15s%n", "序号", "学生姓名", "学生学号", "所在实验室房号", isNormalList ? "打卡时间" : "备注"));
+        if (font == null) {
+            throw new IllegalStateException("font is null in drawCell method.");
+        }
 
-        // 填充数据
-        int sequenceNumber = 1;
-        for (StudentAttendanceSupervisorTemplateVO vo : dataList) {
-            table.append(String.format("%-5d%-10s%-15s%-15s%-15s%n",
-                    sequenceNumber++, vo.getStudentName(), vo.getUserNumber(), vo.getDeptName(),
-                    isNormalList ? vo.getClockInTime() : vo.getRemark()));
+        // 绘制单元格边框
+        contentStream.addRect(x, y - height/2, width, height);
+        contentStream.stroke();
+
+        // 设置字体(原有字体)
+        contentStream.setFont(font, 12); // 保持字体大小为 12
+
+        // 绘制文本
+        float textX = x + 5; // 左侧留 5 单元格内边距
+        float textY = y - height / 2 + 5; // 高度中心对齐,并略微向下调整
+
+        contentStream.beginText();
+        contentStream.newLineAtOffset(textX, textY);
+
+        // 如果是表头,设置加粗效果(PDType0Font 不支持加粗,需通过更换字体实现)
+        if (isHeader) {
+            contentStream.setFont(font, 14); // 加大字体模拟加粗
+        }
+
+        // 检查文字宽度,进行动态换行处理
+        float textWidth = getStringWidth(font, 12, text); // 计算文字宽度
+        if (textWidth > width - 10) { // 如果文字宽度超出单元格宽度
+            String[] words = text.split(" "); // 按空格拆分单词
+            StringBuilder line = new StringBuilder();
+            for (String word : words) {
+                if (getStringWidth(font, 12, line + word) > width - 10) {
+                    // 当前行文字超出宽度,写入并换行
+                    contentStream.showText(line.toString());
+                    contentStream.newLineAtOffset(0, -12); // 换行(12 是字体高度)
+                    line = new StringBuilder();
+                }
+                line.append(word).append(" ");
+            }
+            // 写入剩余文字
+            if (line.length() != 0) {
+                contentStream.showText(line.toString().trim());
+            }
+        } else {
+            contentStream.showText(text); // 正常绘制文字
         }
 
-        return table.toString();
+        contentStream.endText();
+    }
+
 
+    // 获取文字宽度的工具方法
+    private float getStringWidth(PDFont font, float fontSize, String text) throws IOException {
+        return font.getStringWidth(text) / 1000 * fontSize;
     }
 
+    @GetMapping("/generatePdf")
+    public void generatePdf() {
+        PDDocument document = new PDDocument();
+// 创建 ByteArrayOutputStream 用来存储 PDF 文件数据
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+        PDPage page = new PDPage();
+        document.addPage(page);
+
+        try {
+
+            PDFont font = PDType0Font.load(document, getClass().getResourceAsStream("/font/STXIHEI.TTF"));
+            // 创建第一页
+            PDPage page1 = new PDPage();
+            document.addPage(page1);
+
+            // 添加内容到第一页
+            try (PDPageContentStream contentStream1 = new PDPageContentStream(document, page1)) {
+                contentStream1.beginText();
+                contentStream1.setFont(font, 12);
+                contentStream1.newLineAtOffset(25, 750);
+                contentStream1.showText("This is the first page.");
+                contentStream1.endText();
+            }
+
+            // 创建第二页
+            PDPage page2 = new PDPage();
+            document.addPage(page2);
+
+            // 添加内容到第二页
+            try (PDPageContentStream contentStream2 = new PDPageContentStream(document, page2)) {
+                contentStream2.beginText();
+                contentStream2.setFont(font, 12);
+                contentStream2.newLineAtOffset(25, 750);
+                contentStream2.showText("This is the second page.");
+                contentStream2.endText();
+            }
+            Map<String, Object> templateParams = new HashMap<>();//模板参数设置
+            // 附件
+            Map<String, InputStream> attachments = new HashMap<>();
+            // 创建附件
+
+            document.save(byteArrayOutputStream);
+            document.close();
+
+            attachments.put( "_" + "123.pdf", new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
+            mailSendService.sendSingleMailToMemberWithAttachments("1473464808@qq.com", null, "attendance-list-excel", templateParams, attachments);
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                document.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
 }

+ 152 - 81
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/StudentSelectSupervisorRecordController.java

@@ -62,43 +62,43 @@ public class StudentSelectSupervisorRecordController {
     private studentSelectionProjectService studentSelectionProjectService;
 
 //    @Scheduled(cron = "0 00 00 * * ?") // 每天0:00检测
-    @Scheduled(cron = "0 0 * * * ?") // 每1小时执行
-    @Idempotent(timeout = 10)
-    public void checkIsSelection() {
-        LocalDateTime nowTime =LocalDateTime.now();
-        studentSelectionProjectSaveReqVO project
-                = BeanUtils.toBean(
-                        studentSelectionProjectService.getStudentSelectionProjectByYear(nowTime.getYear())
-                ,studentSelectionProjectSaveReqVO.class);
-        LocalDateTime endTime = project.getSupervisorConfirmDeadline();
-        if (nowTime.isAfter(endTime)){
-            checkSelection();
-        }
-    }
-    //在项目结束的时候生成编辑记录,学院直接设置
-    @GetMapping("/ceshi")
-    @Operation(summary = "测试生成编辑记录")
-    public void checkSelection() {
-        //获取今年的选择记录
-        LocalDate date =LocalDate.now();
-        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
-
-        if (project==null){
-            return;
-        }
-        //没有选择成功导师的学生
-        List<AdminUserDO> studentList =adminUserService.getStudentAndSupervisorNull(project.getStudentGrade());
-        //更新所有待处理的记录=>撤回
-        studentSelectSupervisorRecordService.updatePendingSelectType(project.getId());
-        //创建其他的记录
-        StudentSelectSupervisorRecordSaveReqVO createReqVO =new StudentSelectSupervisorRecordSaveReqVO();
-        for (AdminUserDO student :studentList){
-            createReqVO.setProjectId(project.getId());
-            createReqVO.setStudentId(student.getId());
-            createReqVO.setSelectType(4);//编辑状态
-            studentSelectSupervisorRecordService.createStudentSelectSupervisorRecord(createReqVO);
-        }
-    }
+//    @Scheduled(cron = "0 0 * * * ?") // 每1小时执行
+//    @Idempotent(timeout = 10)
+//    public void checkIsSelection() {
+//        LocalDateTime nowTime =LocalDateTime.now();
+//        studentSelectionProjectSaveReqVO project
+//                = BeanUtils.toBean(
+//                        studentSelectionProjectService.getStudentSelectionProjectByYear(nowTime.getYear())
+//                ,studentSelectionProjectSaveReqVO.class);
+//        LocalDateTime endTime = project.getSupervisorConfirmDeadline();
+//        if (nowTime.isAfter(endTime)){
+//            checkSelection();
+//        }
+//    }
+//    //在项目结束的时候生成编辑记录,学院直接设置
+//    @GetMapping("/ceshi")
+//    @Operation(summary = "测试生成编辑记录")
+//    public void checkSelection() {
+//        //获取今年的选择记录
+//        LocalDate date =LocalDate.now();
+//        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+//
+//        if (project==null){
+//            return;
+//        }
+//        //没有选择成功导师的学生
+//        List<AdminUserDO> studentList =adminUserService.getStudentAndSupervisorNull(project.getStudentGrade());
+//        //更新所有待处理的记录=>撤回
+//        studentSelectSupervisorRecordService.updatePendingSelectType(project.getId());
+//        //创建其他的记录
+//        StudentSelectSupervisorRecordSaveReqVO createReqVO =new StudentSelectSupervisorRecordSaveReqVO();
+//        for (AdminUserDO student :studentList){
+//            createReqVO.setProjectId(project.getId());
+//            createReqVO.setStudentId(student.getId());
+//            createReqVO.setSelectType(4);//编辑状态
+//            studentSelectSupervisorRecordService.createStudentSelectSupervisorRecord(createReqVO);
+//        }
+//    }
 
 
     @PostMapping("/create")
@@ -149,15 +149,68 @@ public class StudentSelectSupervisorRecordController {
         return success("请求提交成功");
     }
 
-    //    学院志愿编辑,
+    //
+    @PostMapping("/collegeCreate")
+    @Operation(summary = "学院创建师生互选记录")
+    @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:collegeCreate')")
+    public CommonResult<String> collegeCreateRecord(@Valid @RequestBody StudentSelectSupervisorRecordSaveReqVO createReqVO) {
+
+        AdminUserDO student  =adminUserService.getUser(createReqVO.getStudentId());
+
+        LocalDateTime dateTime =LocalDateTime.now();
+        Integer nextYear =dateTime.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(dateTime.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
+        if (project==null) {
+            return error(1,"今年还没有创建互选项目");
+        }
+
+            Integer occupiedAcademicSlots = adminUserService.countStudentListBySupervisorId(project.getStudentGrade(),createReqVO.getSupervisorId(), 1);//占用学硕
+            Integer occupiedProfessionalSlots = adminUserService.countStudentListBySupervisorId(project.getStudentGrade(),createReqVO.getSupervisorId(), 2);//占用专硕
+            supervisorSelectionSettingDO supervisorSelectionSetting = supervisorSelectionSettingService.getSettingBySupervisorIdAndProjectId(createReqVO.getSupervisorId(), createReqVO.getProjectId());
+
+            if (supervisorSelectionSetting == null || (supervisorSelectionSetting.getAcademicSlots() == null && supervisorSelectionSetting.getProfessionalSlots() == null)) {
+                return error(1, "该导师无名额");
+            }
+            if (student.getMasterType() == 1) {
+                if (supervisorSelectionSetting.getAcademicSlots() != null && supervisorSelectionSetting.getAcademicSlots().equals(occupiedAcademicSlots)) {
+                    return error(1, "学硕名额已经满了");
+                }
+            } else if (student.getMasterType() == 2) {
+                if (supervisorSelectionSetting.getProfessionalSlots() != null && supervisorSelectionSetting.getProfessionalSlots().equals(occupiedProfessionalSlots)) {
+                    return error(1, "专硕名额已经满了");
+                }
+            }
+
+            studentSelectSupervisorRecordDO record1 = studentSelectSupervisorRecordService.getRecordByStudentIdAndSupervisorId(project.getId(),student.getId(), null, 2);//同意
+            studentSelectSupervisorRecordDO record2 = studentSelectSupervisorRecordService.getRecordByStudentIdAndSupervisorId(project.getId(),student.getId(), null, 1);//待处理
+            if (record1 != null) {
+                return error(1, "请求已通过了");
+            } else if (record2 != null) {
+                return error(1, "还有请求在待处理中");
+            }
+
+            createReqVO.setSelectType(2);//同意
+
+            studentSelectSupervisorRecordService.createStudentSelectSupervisorRecord(createReqVO);
+        return success("请求提交成功");
+    }
+
+
+    // 学院志愿编辑,
     @PutMapping("/update")
     @Operation(summary = "更新师生互选记录")
     @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:update')")
     public CommonResult<String> updateStudentSelectSupervisorRecord(@Valid @RequestBody StudentSelectSupervisorRecordSaveReqVO updateReqVO) {
-
+        if (updateReqVO.getId()==null){
+            return error(1,"没有传互选记录id");
+        }
         studentSelectSupervisorRecordDO record =studentSelectSupervisorRecordService.getStudentSelectSupervisorRecord(updateReqVO.getId());
         //
         studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProject(record.getProjectId()), studentSelectionProjectSaveReqVO.class);
+        
         AdminUserDO user =adminUserService.getUser(record.getStudentId());
         Integer  occupiedAcademicSlots =adminUserService.countStudentListBySupervisorId(project.getStudentGrade(),updateReqVO.getSupervisorId(),1);//占用学硕
         Integer  occupiedProfessionalSlots =adminUserService.countStudentListBySupervisorId(project.getStudentGrade(),updateReqVO.getSupervisorId(),2);//占用专硕
@@ -176,40 +229,38 @@ public class StudentSelectSupervisorRecordController {
                 return error(1, "该老师专硕名额已经满了");
             }
         }
-
-        UserSaveReqVO saveReqVO =new UserSaveReqVO();
-        saveReqVO.setId(record.getStudentId());
-        System.out.println(updateReqVO.getSupervisorId());
-        if (updateReqVO.getSupervisorId()!=null) {
-            AdminUserDO supervisor = adminUserService.getUser(updateReqVO.getSupervisorId());
-            if (supervisor != null) {
-                if (supervisor.getUserType().equals("3")) {
-                    saveReqVO.setSupervisorId(updateReqVO.getSupervisorId());
-                } else if (supervisor.getUserType().equals("5")) {
-                    saveReqVO.setExternalSupervisorId(updateReqVO.getSupervisorId());
+            //更新志愿
+            UserSaveReqVO saveReqVO = new UserSaveReqVO();
+            saveReqVO.setId(record.getStudentId());
+            System.out.println(updateReqVO.getSupervisorId());
+            if (updateReqVO.getSupervisorId() != null) {
+                AdminUserDO supervisor = adminUserService.getUser(updateReqVO.getSupervisorId());
+                if (supervisor != null) {
+                    if (supervisor.getUserType().equals("3")) {
+                        saveReqVO.setSupervisorId(updateReqVO.getSupervisorId());
+                    } else if (supervisor.getUserType().equals("5")) {
+                        saveReqVO.setExternalSupervisorId(updateReqVO.getSupervisorId());
 //                //校外导师的合作导师
-                    if (supervisor.getSupervisorId() != null && supervisor.getSupervisorId() != 0) {
-                        saveReqVO.setSupervisorId(supervisor.getSupervisorId());
+                        if (supervisor.getSupervisorId() != null && supervisor.getSupervisorId() != 0) {
+                            saveReqVO.setSupervisorId(supervisor.getSupervisorId());
+                        }
                     }
                 }
             }
-        }
 
-        if(record.getSelectType()==4){//编辑状态
-            updateReqVO.setSelectType(2);//同意
-        }else if (record.getSelectType()==2){//同意了的
-            //初始化记录里面的签名
-            updateReqVO.setStudentSignature("");//学生签名
-            updateReqVO.setStudentSignDate(null);//TODO 这个审批时间
-            updateReqVO.setSupervisorSignature("");
-            updateReqVO.setStudentSignDate(null);
-            updateReqVO.setSupervisorSignDate(null);
-        }else if (record.getSelectType()==1){
-            updateReqVO.setStudentSignature("");//学生签名
-            updateReqVO.setStudentSignDate(null);
-        }
-        adminUserService.updateUser(saveReqVO);
-        studentSelectSupervisorRecordService.updateStudentSelectSupervisorRecord(updateReqVO);
+          if (record.getSelectType() == 2) {//同意了的
+                //初始化记录里面的签名 TODO
+                record.setSupervisorApproveTime(null);//审批时间
+                record.setStudentSignature(null);//学生签名
+                record.setStudentSignDate(null);////学生签名日期
+                record.setSupervisorSignature(null);//导师签名
+                record.setSupervisorSignDate(null);//导师签名日期
+            } else if (record.getSelectType() == 1) {//待处理的
+                record.setStudentSignature(null);//学生签名
+                record.setStudentSignDate(null);
+            }
+            adminUserService.updateUser(saveReqVO);
+            studentSelectSupervisorRecordService.updateRecordNull(BeanUtils.toBean(record, StudentSelectSupervisorRecordSaveReqVO.class));
         return success("志愿修改成功");
     }
 
@@ -236,16 +287,9 @@ public class StudentSelectSupervisorRecordController {
     @Operation(summary = "获得师生互选记录分页")
     @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:query')")
     public CommonResult<PageResult<StudentSelectSupervisorRecordRespVO>> getStudentSelectSupervisorRecordPage(@Valid StudentSelectSupervisorRecordPageReqVO pageReqVO) {
-//        LocalDateTime dateTime = LocalDateTime.now();
-//        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(dateTime.getYear()), studentSelectionProjectSaveReqVO.class);
-//        Long loginId = SecurityFrameworkUtils.getLoginUserId();
-//        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginId);
-//        if ((roleIds.contains(112L) || roleIds.contains(113L)) && project.getSupervisorConfirmDeadline().isBefore(dateTime)) {
-//            return error(1, "该项目已过截至日期");
-//        }else {
-            PageResult<studentSelectSupervisorRecordDO> pageResult = studentSelectSupervisorRecordService.getStudentSelectSupervisorRecordPage(pageReqVO);
-            return success(BeanUtils.toBean(pageResult, StudentSelectSupervisorRecordRespVO.class));
-//        }
+        PageResult<studentSelectSupervisorRecordDO> pageResult = studentSelectSupervisorRecordService.getStudentSelectSupervisorRecordPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, StudentSelectSupervisorRecordRespVO.class));
+//
     }
 
     @GetMapping("/export-excel")
@@ -389,8 +433,12 @@ public class StudentSelectSupervisorRecordController {
     @Operation(summary = "互选表打印数据列表")
     @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:getSelectionList')")
     public CommonResult<List<PrintBookVO>> getSelectionBookList() {
-        LocalDate date = LocalDate.now();
-        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()), studentSelectionProjectSaveReqVO.class);
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
         if (project == null) {
             return error(1, "项目不存在");
         }
@@ -420,7 +468,11 @@ public class StudentSelectSupervisorRecordController {
         Set<Long> roleIds =permissionService.getUserRoleIdListByUserId(loginId);
 
         LocalDate date =LocalDate.now();
-        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
         if (project==null){
             return error(1,"请检查今年是否创建了项目");
         }
@@ -484,4 +536,23 @@ public class StudentSelectSupervisorRecordController {
         Long loginId =SecurityFrameworkUtils.getLoginUserId();
         return success(studentSelectSupervisorRecordService.getSupervisorSignatureById(loginId));
     }
+
+
+    @GetMapping("/pendingApprovalPage")
+    @Operation(summary = "获得待审批记录分页")
+    @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:pendingApprovalPage')")
+    public CommonResult<PageResult<StudentSelectSupervisorRecordRespVO>> getPendingApprovalRecordPage(@Valid StudentSelectSupervisorRecordPageReqVO pageReqVO) {
+        PageResult<studentSelectSupervisorRecordDO> pageResult = studentSelectSupervisorRecordService.getPendingApprovalRecordPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, StudentSelectSupervisorRecordRespVO.class));
+    }
+
+    @GetMapping("/approvedRecordPage")
+    @Operation(summary = "获得已审批记录分页")
+    @PreAuthorize("@ss.hasPermission('system:student-select-supervisor-record:approvedRecordPage')")
+    public CommonResult<PageResult<StudentSelectSupervisorRecordRespVO>> getApprovedRecordPage(@Valid StudentSelectSupervisorRecordPageReqVO pageReqVO) {
+        PageResult<studentSelectSupervisorRecordDO> pageResult = studentSelectSupervisorRecordService.getApprovedRecordPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, StudentSelectSupervisorRecordRespVO.class));
+    }
+
+
 }

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/vo/StudentSelectSupervisorRecordPageReqVO.java

@@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 public class StudentSelectSupervisorRecordPageReqVO extends PageParam {
 
     @Schema(description = "项目id", example = "20003")
-    private Integer projectId;
+    private Long projectId;
 
     @Schema(description = "学生id", example = "14632")
     private Long studentId;

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectSupervisorRecord/vo/StudentSelectSupervisorRecordRespVO.java

@@ -19,7 +19,7 @@ public class StudentSelectSupervisorRecordRespVO {
 
     @Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED, example = "20003")
     @ExcelProperty("项目id")
-    private Integer projectId;
+    private Long projectId;
 
     @Schema(description = "学生id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14632")
     @ExcelProperty("学生id")

+ 24 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/studentSelectionProject/studentSelectionProjectController.java

@@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.studentSelectionProject;
 
 import cn.iocoder.yudao.module.system.controller.admin.supervisorSelectionSetting.vo.supervisorSelectionSettingPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.supervisorSelectionSetting.vo.supervisorSelectionSettingSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.studentSelectSupervisorRecord.studentSelectSupervisorRecordDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.supervisorSelectionSetting.supervisorSelectionSettingDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
+import cn.iocoder.yudao.module.system.service.studentSelectSupervisorRecord.studentSelectSupervisorRecordService;
 import cn.iocoder.yudao.module.system.service.supervisorSelectionSetting.supervisorSelectionSettingService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import org.apache.ibatis.annotations.Param;
@@ -48,7 +50,7 @@ import cn.iocoder.yudao.module.system.service.studentSelectionProject.studentSel
 public class studentSelectionProjectController {
     // TODO 1.删除项目时,应该同时删除对应的关联信息
     //  2. 新增接口 ,学院 :(1) 查看所有未提交、未通过、(注意提交但是撤回的状态)的学生 (2) 查看所有已通过的学生 (3) 招生详情只展示同意的
-    //   老师: (1) 新增菜单, 待审批接口 (2)已审批
+    //   老师: (1) 新增菜单, 待审批接口 (2)已审批 //ok
     //   学生:  (1)  操作提示 ,还有请求在待处理中 改为 已存在申请 , (2)申请表样式
     //  3.合并菜单
     //  4. 项目创建表单 名称和描述  年份默认
@@ -59,6 +61,8 @@ public class studentSelectionProjectController {
     private supervisorSelectionSettingService supervisorSelectionSettingService;
     @Resource
     private AdminUserService adminUserService;
+    @Resource
+    private studentSelectSupervisorRecordService studentSelectSupervisorRecordService;
 
     @PostMapping("/create")
     @Operation(summary = "创建师生互选项目")
@@ -82,8 +86,12 @@ public class studentSelectionProjectController {
         if (createReqVO.getStudentStartTime().isAfter(createReqVO.getSupervisorConfirmDeadline())){
             return error(1,"时间设置错误");
         }
-        LocalDate date = LocalDate.now();
-        studentSelectionProjectDO project = studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear());
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
         if (project!=null){
             return error(1,"今年已经创建过项目了");
         }else {
@@ -205,10 +213,20 @@ public class studentSelectionProjectController {
     @Parameter(name = "id", description = "编号", required = true)
     @PreAuthorize("@ss.hasPermission('system:student-selection-project:delete')")
     public CommonResult<Boolean> deleteStudentSelectionProject(@RequestParam("id") Long id) {
+        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProject(id), studentSelectionProjectSaveReqVO.class);
+        List<Long> supervisorIds =project.getSupervisorIds();
+        //删除项目下的导师设置
+        supervisorSelectionSettingService.deleteSettingsBySupervisorIds(id,supervisorIds);
+        //删除项目下的互选记录
+        studentSelectSupervisorRecordService.deleteRecordsByProjectId(id);
+        //初始化选中的学生的导师id
+        adminUserService.updateStudentSupervisorId(project.getStudentGrade());
+        //删除项目;
         studentSelectionProjectService.deleteStudentSelectionProject(id);
         return success(true);
     }
 
+
     @GetMapping("/get")
     @Operation(summary = "获得师生互选项目")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
@@ -276,6 +294,9 @@ public class studentSelectionProjectController {
     public CommonResult<List<AdminUserDO>> getProjectSupervisors(@RequestParam("projectId") Long projectId) {
         // 获取项目数据并转换成相应的 VO
         studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProject(projectId), studentSelectionProjectSaveReqVO.class);
+        if (project==null){
+            return error(1,"不存在该项目");
+        }
         List<Long> supervisorIds = project.getSupervisorIds();
         Set<Long> newSupervisorIds = new HashSet<>(supervisorIds);
         List<AdminUserDO> supervisors = adminUserService.getUserList(newSupervisorIds);

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/supervisorSelectionSettingController.java

@@ -132,7 +132,7 @@ public class supervisorSelectionSettingController {
     }
 
     @GetMapping("/getSupervisorInfo")
-    @Operation(summary = "导师这个项目的信息")
+    @Operation(summary = "导师这个项目的设置信息")
     public CommonResult<supervisorSelectionSettingDO> getSupervisorInfo(@RequestParam("supervisorId") Integer supervisorId,@RequestParam("projectId") Long projectId) {
         return success(supervisorSelectionSettingService.getSettingBySupervisorIdAndProjectId(Long.valueOf(supervisorId),projectId));
     }

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/vo/supervisorBookRespVO.java

@@ -12,7 +12,7 @@ import java.time.LocalDate;
 public class supervisorBookRespVO {
 
     @Schema(description = "项目")
-    private Integer projectId;
+    private Long projectId;
 
     @Schema(description = "导师Id")
     private String supervisorId;

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/supervisorSelectionSetting/vo/supervisorSelectionSettingRespVO.java

@@ -19,7 +19,7 @@ public class supervisorSelectionSettingRespVO {
 
     @Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @ExcelProperty("项目id")
-    private Integer projectId;
+    private Long projectId;
 
     @Schema(description = "导师id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @ExcelProperty("导师id")

+ 68 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java

@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.studentSelectionProject.vo.studentPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.studentSelectionProject.vo.studentSelectionProjectSaveReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
 
@@ -334,7 +335,7 @@ public class UserController {
                 if (!(user.getExternalSupervisorId() == null || user.getExternalSupervisorId() == 0)) {
                     AdminUserDO externalSupervisor = userService.getUser(user.getExternalSupervisorId());
                     if (externalSupervisor != null) {
-                        user.setWorkSupervisor(externalSupervisor.getNickname());
+                        user.setExternalSupervisor(externalSupervisor.getNickname());//校外导师名字
                     }
                 }
             }
@@ -352,6 +353,19 @@ public class UserController {
                 }
             }
         }
+//      //查询用户的选择状态()
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
+        if (project!=null) {
+            if ((user.getGrade() != null && !user.getGrade().isEmpty()) && user.getGrade().equals(project.getStudentGrade())) {
+                user.setSelectStatus(userService.getUserSelectStatus(id, project.getId()));
+            }
+        }
+
         // 拼接数据
         DeptDO dept = deptService.getDept(user.getDeptId());
         return success(UserConvert.INSTANCE.convert(user, dept));
@@ -607,7 +621,11 @@ public class UserController {
         AdminUserDO loginUser =userService.getUser(loginId);
         Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginId);
 
-        studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
         if (project==null){
             return error(1,"请检查今年是否创建了项目");
         }
@@ -638,8 +656,14 @@ public class UserController {
         PopDo PD =userService.getPopData();
         if (popData.getIsStudent() != null || popData.getIsSupervisor() != null) {
             userService.updatePop(popData);
+
             LocalDate date =LocalDate.now();
-            studentSelectionProjectSaveReqVO project = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+            Integer nextYear =date.getYear()+1 ;
+            studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+            studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+            studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+            project =project1==null?project2:project1;
+
             if (project==null){
                 return error(1,"请检查今年是否创建了项目");
             }
@@ -680,4 +704,45 @@ public class UserController {
         return success( userService.getPopData());
     }
 
+
+    @GetMapping("/getPassedStudentsPage")
+    @Operation(summary = "获取今年项目学生通过分页")
+    @PreAuthorize("@ss.hasPermission('system:user:getPassedStudentsPage')")
+    public CommonResult<PageResult<AdminUserDO>> getPassedStudentsPage(@Valid UserPageReqVO pageReqVO) {
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
+        if (project==null) {
+            return error(1,"今年还没有创建互选项目");
+        }
+        pageReqVO.setGrade(project.getStudentGrade());
+        pageReqVO.setUserType("1");
+
+        PageResult<AdminUserDO>  result = userService.getPassedStudentsPage(pageReqVO);
+        return success(result);
+    }
+
+    @GetMapping("/getUnPassedStudentsPage")
+    @Operation(summary = "获取今年互选项目学生未通过分页")//未提交和待处理
+    @PreAuthorize("@ss.hasPermission('system:user:getUnPassedStudentsPage')")
+    public CommonResult<PageResult<AdminUserDO>> getUnPassedStudentsPage(@Valid UserPageReqVO reqVO) {
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
+        if (project==null) {
+            return error(1,"今年还没有创建互选项目");
+        }
+
+        reqVO.setGrade(project.getStudentGrade());
+        reqVO.setUserType("1");
+        PageResult<AdminUserDO>  result = userService.getUnPassedStudentsPage(reqVO);
+        return success(result);
+    }
+
 }

+ 16 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java

@@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.system.controller.admin.user;
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
+import cn.iocoder.yudao.module.system.controller.admin.studentSelectionProject.vo.studentSelectionProjectSaveReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
@@ -78,9 +80,22 @@ public class UserProfileController {
             if (supervisorUser!=null) {
                 String supervisor = supervisorUser.getNickname();
                 user.setSupervisor(supervisor);
-                System.out.println("学生基本信息" + user);
             }
         }
+
+        //获取互选项目用户的选择状态()
+        LocalDate date =LocalDate.now();
+        Integer nextYear =date.getYear()+1 ;
+        studentSelectionProjectSaveReqVO project =new studentSelectionProjectSaveReqVO();
+        studentSelectionProjectSaveReqVO project1 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(nextYear),studentSelectionProjectSaveReqVO.class);
+        studentSelectionProjectSaveReqVO project2 = BeanUtils.toBean(studentSelectionProjectService.getStudentSelectionProjectByYear(date.getYear()),studentSelectionProjectSaveReqVO.class);
+        project =project1==null?project2:project1;
+        if (project!=null) {
+            if ((user.getGrade() != null && !user.getGrade().isEmpty()) && user.getGrade().equals(project.getStudentGrade())) {
+                user.setSelectStatus(userService.getUserSelectStatus(user.getId(), project.getId()));
+            }
+        }
+
         // 获得用户角色
         List<RoleDO> userRoles = roleService.getRoleListFromCache(permissionService.getUserRoleIdListByUserId(user.getId()));
         // 获得部门信息

+ 4 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java

@@ -115,4 +115,8 @@ public class UserProfileRespVO {
     @Schema(description = "工作地点")
     private String workPlace;
 
+    //选择状态
+    @Schema(description = "选择状态")
+    private Integer selectStatus;
+
 }

+ 4 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java

@@ -138,4 +138,8 @@ public class UserRespVO{
     @Schema(description = "合作导师名称")
     private String workSupervisor;
 
+    //选择状态
+    @Schema(description = "选择状态")
+    private Integer selectStatus;
+
 }

+ 5 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java

@@ -188,8 +188,12 @@ public class AdminUserDO extends TenantBaseDO {
 
     @TableField(exist = false)
     private String deptName;
-    
 
+    //选择状态
+    @TableField(exist = false)
+    private Integer selectStatus;
 
+    @TableField(exist = false)
+    private Long recordId;
 
 }

+ 100 - 15
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/studentSelectSupervisorRecord/studentSelectSupervisorRecordMapper.java

@@ -22,6 +22,10 @@ import org.apache.ibatis.annotations.Update;
 @Mapper
 public interface studentSelectSupervisorRecordMapper extends BaseMapperX<studentSelectSupervisorRecordDO> {
 
+    // 部分能传null
+    void updateRecordNull(@Param("recordDO") studentSelectSupervisorRecordDO recordDO);
+
+    //招生详情和导师的项目详情
     default PageResult<studentSelectSupervisorRecordDO> selectPage(StudentSelectSupervisorRecordPageReqVO reqVO, Set<Long>roleIds, AdminUserDO loginUser) {
 
         MPJLambdaWrapperX<studentSelectSupervisorRecordDO> queryWrapperX =new MPJLambdaWrapperX<>();
@@ -46,17 +50,21 @@ public interface studentSelectSupervisorRecordMapper extends BaseMapperX<student
                 .eqIfExists(studentSelectSupervisorRecordDO::getStudentSignature, reqVO.getStudentSignature())
                 .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorSignature, reqVO.getSupervisorSignature())
                 .eqIfExists(studentSelectSupervisorRecordDO::getExternalSupervisorId, reqVO.getExternalSupervisorId())
-                .orderByDesc(studentSelectSupervisorRecordDO::getId);
+                .orderByDesc(studentSelectSupervisorRecordDO::getCreateTime);
 
-        if (roleIds.contains(113L)){
+        if (roleIds.contains(113L)){//导师看自己的待处理,同意,退回
             queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSupervisorId,loginUser.getId())
                     .inIfPresent(studentSelectSupervisorRecordDO::getSelectType,1,2,3)
                     .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
                     .last("ORDER BY FIELD(select_type, 1,2,3)");
-        }else if (roleIds.contains(114L)){//学院看所有的编辑、待处理、退回记录
-            queryWrapperX.inIfPresent(studentSelectSupervisorRecordDO::getSelectType,0,1,2,3,4)
-                    .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
-                    .last("ORDER BY FIELD(select_type, 4, 1, 3, 2,0)");
+        }else if (roleIds.contains(114L)){
+            if ( reqVO.getSupervisorId()!=null&&reqVO.getSupervisorId()!=0) {//招生详情学院看对应导师的同意的
+                queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSelectType, 2);
+            }else {//互选记录看所有
+                queryWrapperX.inIfPresent(studentSelectSupervisorRecordDO::getSelectType,0,1,2,3)
+                        .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
+                        .last("ORDER BY FIELD(select_type,2,1,3,0)");
+            }
         }else if (roleIds.contains(112L)){//学生看自己的
             queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getStudentId,loginUser.getId());
         }
@@ -84,23 +92,96 @@ public interface studentSelectSupervisorRecordMapper extends BaseMapperX<student
                 .eqIfExists(studentSelectSupervisorRecordDO::getStudentSignature, reqVO.getStudentSignature())
                 .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorSignature, reqVO.getSupervisorSignature())
                 .eqIfExists(studentSelectSupervisorRecordDO::getExternalSupervisorId, reqVO.getExternalSupervisorId())
-                .orderByDesc(studentSelectSupervisorRecordDO::getId);
-        if (roleIds.contains(113L)){
+                .orderByDesc(studentSelectSupervisorRecordDO::getCreateTime);
+        if (roleIds.contains(113L)){//导师看自己的待处理,同意,退回
             queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSupervisorId,loginUser.getId())
-                            .inIfPresent(studentSelectSupervisorRecordDO::getSelectType,1,2,3)
-                            .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
-                            .last("ORDER BY FIELD(select_type, 1,2,3)");
-        }else if (roleIds.contains(114L)){//学院看所有的编辑、待处理、退回记录
-            queryWrapperX.inIfPresent(studentSelectSupervisorRecordDO::getSelectType,0,1,2,3,4)
+                    .inIfPresent(studentSelectSupervisorRecordDO::getSelectType,1,2,3)
                     .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
-                            .last("ORDER BY FIELD(select_type, 4, 1, 3, 2)");
-
+                    .last("ORDER BY FIELD(select_type, 1,2,3)");
+        }else if (roleIds.contains(114L)){//
+            if ( reqVO.getSupervisorId()!=null&&reqVO.getSupervisorId()!=0) {//招生详情
+                queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSelectType, 2);
+            }else {//互选记录看所有
+                queryWrapperX.inIfPresent(studentSelectSupervisorRecordDO::getSelectType,0,1,2,3)
+                        .orderBy(true, true, studentSelectSupervisorRecordDO::getSelectType)
+                        .last("ORDER BY FIELD(select_type,2,1,3,0)");
+            }
         }else if (roleIds.contains(112L)){//学生看自己的
             queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getStudentId,loginUser.getId());
         }
         return selectList(queryWrapperX);
     }
 
+    //导师待审批
+    default PageResult<studentSelectSupervisorRecordDO> getPendingApprovalRecordPage(StudentSelectSupervisorRecordPageReqVO reqVO, Set<Long>roleIds, AdminUserDO loginUser) {
+
+        MPJLambdaWrapperX<studentSelectSupervisorRecordDO> queryWrapperX =new MPJLambdaWrapperX<>();
+
+        queryWrapperX
+                .betweenIfPresent(studentSelectSupervisorRecordDO::getSupervisorApproveTime, reqVO.getSupervisorApproveTime())
+                .selectAll(studentSelectSupervisorRecordDO.class)
+                .leftJoin(AdminUserDO.class,AdminUserDO::getId,studentSelectSupervisorRecordDO::getStudentId)//关联学生信息
+                .leftJoin(studentSelectionProjectDO.class,studentSelectionProjectDO::getId,studentSelectSupervisorRecordDO::getProjectId)//关联项目
+                .selectAs(AdminUserDO::getNickname,studentSelectSupervisorRecordDO::getStudentName)//学生姓名
+                .selectAs(AdminUserDO::getGrade,studentSelectSupervisorRecordDO::getStudentGrade)//学生年级
+                .selectAs(AdminUserDO::getMasterType,studentSelectSupervisorRecordDO::getMasterType)//硕士类型
+                .selectAs(AdminUserDO::getMajor,studentSelectSupervisorRecordDO::getMajor)//专业
+                .selectAs(AdminUserDO::getIntroduction,studentSelectSupervisorRecordDO::getIntroduction)//简历
+                .selectAs(studentSelectionProjectDO::getProjectName,studentSelectSupervisorRecordDO::getProjectName)//项目名称
+                .likeIfExists(AdminUserDO::getNickname,reqVO.getStudentName())//学生姓名
+                .eqIfExists(AdminUserDO::getGrade,reqVO.getStudentGrade())//学生年级
+                .eqIfExists(studentSelectSupervisorRecordDO::getProjectId, reqVO.getProjectId())
+                .eqIfExists(studentSelectSupervisorRecordDO::getStudentId, reqVO.getStudentId())
+                .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorId, reqVO.getSupervisorId())//学院看招生情况会传导师id
+                .eqIfExists(studentSelectSupervisorRecordDO::getSelectType, reqVO.getSelectType())
+                .eqIfExists(studentSelectSupervisorRecordDO::getStudentSignature, reqVO.getStudentSignature())
+                .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorSignature, reqVO.getSupervisorSignature())
+                .eqIfExists(studentSelectSupervisorRecordDO::getExternalSupervisorId, reqVO.getExternalSupervisorId())
+                .orderByDesc(studentSelectSupervisorRecordDO::getCreateTime);
+
+        if (roleIds.contains(113L)){//导师看自己的待处理
+            queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSupervisorId,loginUser.getId())
+                    .eqIfPresent(studentSelectSupervisorRecordDO::getSelectType,1);
+        }
+        return selectPage(reqVO,queryWrapperX);
+    }
+
+    //导师已审批
+    default PageResult<studentSelectSupervisorRecordDO> getApprovedRecordPage(StudentSelectSupervisorRecordPageReqVO reqVO, Set<Long>roleIds, AdminUserDO loginUser) {
+
+        MPJLambdaWrapperX<studentSelectSupervisorRecordDO> queryWrapperX =new MPJLambdaWrapperX<>();
+
+        queryWrapperX
+                .betweenIfPresent(studentSelectSupervisorRecordDO::getSupervisorApproveTime, reqVO.getSupervisorApproveTime())
+                .selectAll(studentSelectSupervisorRecordDO.class)
+                .leftJoin(AdminUserDO.class,AdminUserDO::getId,studentSelectSupervisorRecordDO::getStudentId)//关联学生信息
+                .leftJoin(studentSelectionProjectDO.class,studentSelectionProjectDO::getId,studentSelectSupervisorRecordDO::getProjectId)//关联项目
+                .selectAs(AdminUserDO::getNickname,studentSelectSupervisorRecordDO::getStudentName)//学生姓名
+                .selectAs(AdminUserDO::getGrade,studentSelectSupervisorRecordDO::getStudentGrade)//学生年级
+                .selectAs(AdminUserDO::getMasterType,studentSelectSupervisorRecordDO::getMasterType)//硕士类型
+                .selectAs(AdminUserDO::getMajor,studentSelectSupervisorRecordDO::getMajor)//专业
+                .selectAs(AdminUserDO::getIntroduction,studentSelectSupervisorRecordDO::getIntroduction)//简历
+                .selectAs(studentSelectionProjectDO::getProjectName,studentSelectSupervisorRecordDO::getProjectName)//项目名称
+                .likeIfExists(AdminUserDO::getNickname,reqVO.getStudentName())//学生姓名
+                .eqIfExists(AdminUserDO::getGrade,reqVO.getStudentGrade())//学生年级
+                .eqIfExists(studentSelectSupervisorRecordDO::getProjectId, reqVO.getProjectId())
+                .eqIfExists(studentSelectSupervisorRecordDO::getStudentId, reqVO.getStudentId())
+                .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorId, reqVO.getSupervisorId())//学院看招生情况会传导师id
+                .eqIfExists(studentSelectSupervisorRecordDO::getSelectType, reqVO.getSelectType())
+                .eqIfExists(studentSelectSupervisorRecordDO::getStudentSignature, reqVO.getStudentSignature())
+                .eqIfExists(studentSelectSupervisorRecordDO::getSupervisorSignature, reqVO.getSupervisorSignature())
+                .eqIfExists(studentSelectSupervisorRecordDO::getExternalSupervisorId, reqVO.getExternalSupervisorId())
+                .orderByDesc(studentSelectSupervisorRecordDO::getCreateTime);
+
+        if (roleIds.contains(113L)){//导师看自己的同意和退回
+            queryWrapperX.eqIfPresent(studentSelectSupervisorRecordDO::getSupervisorId,loginUser.getId())
+                    .inIfPresent(studentSelectSupervisorRecordDO::getSelectType,2,3);
+        }
+        return selectPage(reqVO,queryWrapperX);
+    }
+
+
+
     //只能查一直只有一条记录的,同意/未处理
     studentSelectSupervisorRecordDO getRecordByStudentIdAndSupervisorId(
             @Param("projectId") Long projectId,
@@ -120,4 +201,8 @@ public interface studentSelectSupervisorRecordMapper extends BaseMapperX<student
     @Select("SELECT supervisor_signature FROM student_select_supervisor_record WHERE supervisor_id=#{supervisorId} AND select_type =2 AND supervisor_signature IS NOT NULL AND supervisor_signature != '' AND deleted =0 ORDER BY supervisor_sign_date DESC LIMIT 1")
     String getSupervisorSignatureById(@Param("supervisorId") Long supervisorId);
 
+    @Update("UPDATE student_select_supervisor_record SET deleted = 1 WHERE project_id = #{projectId} AND deleted = 0")
+    void deleteRecordsByProjectId(@Param("projectId") Long projectId);
+
+
 }

+ 2 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/studentSelectionProject/studentSelectionProjectMapper.java

@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.system.dal.mysql.studentSelectionProject;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
+import cn.iocoder.yudao.module.system.dal.dataobject.studentSelectSupervisorRecord.studentSelectSupervisorRecordDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.studentSelectionProject.studentSelectionProjectDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import org.apache.ibatis.annotations.Mapper;
@@ -39,7 +41,6 @@ public interface studentSelectionProjectMapper extends BaseMapperX<studentSelect
         }else if (roleIds.contains(114L)){//学院
 
         }
-
         return selectPage(reqVO,queryWrapperX);
     }
     @Select("SELECT * FROM supervisor_student_selection_project WHERE YEAR(create_time) = #{year} AND deleted =0")

+ 2 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/supervisorSelectionSetting/supervisorSelectionSettingMapper.java

@@ -49,6 +49,8 @@ public interface supervisorSelectionSettingMapper extends BaseMapperX<supervisor
 //    @Select("SELECT * FROM supervisor_selection_setting WHERE supervisor_id = #{supervisorId} AND project_id = #{projectId} AND deleted =0")
 //    supervisorSelectionSettingDO getSettingBySupervisorIdAndProjectId(@Param("supervisorId") Long supervisorId,@Param("projectId") Integer projectId);
 
+     void deleteSettingsBySupervisorIds(@Param("projectId")Long projectId,@Param("supervisorIds") List<Long> supervisorIds);
+
 
 
 }

+ 70 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java

@@ -5,9 +5,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.module.system.controller.admin.studentSelectionProject.vo.studentPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.studentSelectSupervisorRecord.studentSelectSupervisorRecordDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.PopDo;
 import cn.iocoder.yudao.module.system.dal.dataobject.userAchievement.UserAchievementDO;
@@ -21,6 +24,7 @@ import org.apache.ibatis.annotations.*;
 
 import javax.annotation.Resource;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Mapper
 public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
@@ -267,7 +271,6 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
                 .likeIfPresent(AdminUserDO::getEmail,reqVO.getEmail())
                 .likeIfPresent(AdminUserDO::getNickname, reqVO.getNickname())//昵称查询
                 .likeIfPresent(AdminUserDO::getUserNumber,reqVO.getUserNumber())//学号查询
-                .likeIfPresent(AdminUserDO::getWorkPlace,reqVO.getWorkPlace())
                 .likeIfPresent(AdminUserDO::getWorkPlace,reqVO.getWorkPlace())//工作地点
                 .likeIfPresent(AdminUserDO::getMajor, reqVO.getMajor())//专业
                 .eqIfPresent(AdminUserDO::getMasterType, reqVO.getMasterType())//专硕
@@ -369,6 +372,72 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
     @Update("UPDATE system_users SET introduction = #{introduction} WHERE id = #{id}")
     void updateUserIntroduction(@Param("id") Long id, @Param("introduction") String introduction);
 
+    //找当年级下导师值为空的在校生
     @Select("SELECT * FROM system_users WHERE (supervisor_id = 0 OR supervisor_id IS NULL) AND grade = #{grade} AND user_type = '1' AND deleted = 0")
     List<AdminUserDO> getStudentAndSupervisorNull(@Param("grade") String grade);
+
+    //初始化当年级下的校生的导师id
+    @Update("UPDATE system_users " +
+            "SET supervisor_id = NULL, external_supervisor_id = NULL " +
+            "WHERE supervisor_id IS NOT NULL AND supervisor_id != 0 " +
+            "AND grade = #{grade} " +
+            "AND user_type = '1' " +//在校生
+            "AND deleted = 0")
+    void updateStudentSupervisorId(@Param("grade") String grade);
+
+    //已通过学生
+    default PageResult<AdminUserDO> getPassedStudentsPage(UserPageReqVO pageReqVO) {
+
+        MPJLambdaWrapperX<AdminUserDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
+
+        // 使用 select 语句返回计算出来的 selectStatus 字段
+        mpjLambdaWrapperX
+                .select("t.*, CASE " +
+                        "    WHEN COALESCE(MAX(t1.select_type), 0) = 2 THEN 2" +
+                        "    WHEN COALESCE(MAX(t1.select_type), 0) = 1 THEN 1 " + // 带处理
+                        "    ELSE 0 " + // 未提交
+                        "END AS selectStatus")  // 将 selectStatus 返回
+                .leftJoin("student_select_supervisor_record t1 on t1.student_id = t.id and t1.deleted = 0")
+                .eqIfExists(AdminUserDO::getUserType, 1)
+                .eqIfExists(AdminUserDO::getGrade, pageReqVO.getGrade())
+                .likeIfExists(AdminUserDO::getMobile, pageReqVO.getMobile())
+                .likeIfExists(AdminUserDO::getStatus, pageReqVO.getStatus())
+                .eqIfExists(AdminUserDO::getSupervisorId, pageReqVO.getSupervisorId()) // 导师查询
+                .likeIfExists(AdminUserDO::getEmail, pageReqVO.getEmail())
+                .likeIfExists(AdminUserDO::getNickname, pageReqVO.getNickname()) // 昵称查询
+                .likeIfExists(AdminUserDO::getUserNumber, pageReqVO.getUserNumber()) // 学号查询
+                .likeIfExists(AdminUserDO::getMajor, pageReqVO.getMajor()) // 专业
+                .eqIfExists(AdminUserDO::getMasterType, pageReqVO.getMasterType()) // 专硕
+                .orderByDesc(AdminUserDO::getId);
+
+        // 查询数据
+        PageResult<AdminUserDO> result = selectPage(pageReqVO, mpjLambdaWrapperX);
+
+        List<AdminUserDO> filteredList = result.getList().stream()
+                .filter(user -> user.getSelectStatus() == 2)  // 只保留 selectStatus 1
+                .collect(Collectors.toList());
+
+        // 重新设置过滤后的结果
+        result.setList(filteredList);
+        result.setTotal((long) filteredList.size());
+        return result;
+    }
+
+    //待处理和已提交
+
+    //未通过学生
+     List<AdminUserDO> getIsPassedStudentsPage( @Param("reqVO") UserPageReqVO reqVO,@Param("offset") Integer offset ,@Param("isPassed") Integer isPassed);
+     Long  getIsPassedStudentsPageCount( @Param("reqVO") UserPageReqVO reqVO,@Param("isPassed") Integer isPassed);
+
+
+     //获取用户选择状态
+    @Select("SELECT COALESCE(MAX(CASE " +
+            "WHEN r.select_type = 2 THEN 2 " +
+            "WHEN r.select_type = 1 THEN 1 " +
+            "ELSE 0 " +
+            "END), 0) " +
+            "FROM system_users u " +
+            "LEFT JOIN student_select_supervisor_record r ON r.student_id = u.id " +
+            "WHERE u.id = #{id} AND r.project_id =#{projectId} AND r.deleted = 0 AND u.deleted = 0")
+    Integer getUserSelectStatus(@Param("id") Long id, @Param("projectId") Long projectId);
 }

+ 22 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/studentSelectSupervisorRecord/studentSelectSupervisorRecordService.java

@@ -29,6 +29,17 @@ public interface studentSelectSupervisorRecordService {
      */
     void updateStudentSelectSupervisorRecord(@Valid StudentSelectSupervisorRecordSaveReqVO updateReqVO);
 
+    /**
+     *能传null
+     *学生签名
+     * 导师签名
+     * 导师审批时间
+     * 学生签字日期
+     * 导师签字日期
+     *
+     */
+    void updateRecordNull( @Valid StudentSelectSupervisorRecordSaveReqVO updateReqVO);
+
     /**
      * 删除师生互选记录
      *
@@ -53,6 +64,15 @@ public interface studentSelectSupervisorRecordService {
     PageResult<studentSelectSupervisorRecordDO> getStudentSelectSupervisorRecordPage(StudentSelectSupervisorRecordPageReqVO pageReqVO);
 
     List<studentSelectSupervisorRecordDO> getStudentSelectSupervisorRecordList(StudentSelectSupervisorRecordPageReqVO pageReqVO);
+    /**
+     * 获得导师待审批分页
+     */
+    PageResult<studentSelectSupervisorRecordDO> getPendingApprovalRecordPage(StudentSelectSupervisorRecordPageReqVO pageReqVO);
+    /**
+     * 获得导师已审批分页
+     */
+    PageResult<studentSelectSupervisorRecordDO> getApprovedRecordPage(StudentSelectSupervisorRecordPageReqVO pageReqVO);
+
 
     studentSelectSupervisorRecordDO getRecordByStudentIdAndSupervisorId( Long projectId,Long studentId ,Long supervisorId,Integer selectType);
 
@@ -65,6 +85,8 @@ public interface studentSelectSupervisorRecordService {
 
     String getSupervisorSignatureById(Long supervisorId);
 
+    void deleteRecordsByProjectId(Long projectId);
+
 
 
 }

+ 50 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/studentSelectSupervisorRecord/studentSelectSupervisorRecordServiceImpl.java

@@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.system.service.permission.PermissionService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.validation.Valid;
+
 import org.springframework.validation.annotation.Validated;
 
 import java.util.*;
@@ -53,6 +55,15 @@ public class studentSelectSupervisorRecordServiceImpl implements studentSelectSu
         studentSelectSupervisorRecordDO updateObj = BeanUtils.toBean(updateReqVO, studentSelectSupervisorRecordDO.class);
         studentSelectSupervisorRecordMapper.updateById(updateObj);
     }
+//    能传null
+    @Override
+    public void updateRecordNull(@Valid StudentSelectSupervisorRecordSaveReqVO updateReqVO){
+        // 校验存在
+        validateStudentSelectSupervisorRecordExists(updateReqVO.getId());
+        // 更新
+        studentSelectSupervisorRecordDO recordDO = BeanUtils.toBean(updateReqVO, studentSelectSupervisorRecordDO.class);
+        studentSelectSupervisorRecordMapper.updateRecordNull(recordDO);
+    }
 
     @Override
     public void deleteStudentSelectSupervisorRecord(Long id) {
@@ -105,6 +116,40 @@ public class studentSelectSupervisorRecordServiceImpl implements studentSelectSu
         return result;
     }
 
+    @Override
+    public PageResult<studentSelectSupervisorRecordDO> getPendingApprovalRecordPage(StudentSelectSupervisorRecordPageReqVO pageReqVO) {
+        Long loginId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserDO loginUser = adminUserService.getUser(loginId);
+        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginId);
+        PageResult<studentSelectSupervisorRecordDO> result =studentSelectSupervisorRecordMapper.getPendingApprovalRecordPage(pageReqVO,roleIds,loginUser);
+        result.getList().forEach(re->{
+            AdminUserDO supervisor =adminUserService.getUser(re.getSupervisorId());
+            if (supervisor!=null) {
+                re.setSupervisor(supervisor.getNickname());
+                re.setSupervisorType(supervisor.getUserType());
+            }
+        });
+        return result;
+    }
+
+
+    @Override
+    public PageResult<studentSelectSupervisorRecordDO> getApprovedRecordPage(StudentSelectSupervisorRecordPageReqVO pageReqVO) {
+        Long loginId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserDO loginUser = adminUserService.getUser(loginId);
+        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginId);
+        PageResult<studentSelectSupervisorRecordDO> result =studentSelectSupervisorRecordMapper.getApprovedRecordPage(pageReqVO,roleIds,loginUser);
+        result.getList().forEach(re->{
+            AdminUserDO supervisor =adminUserService.getUser(re.getSupervisorId());
+            if (supervisor!=null) {
+                re.setSupervisor(supervisor.getNickname());
+                re.setSupervisorType(supervisor.getUserType());
+            }
+        });
+        return result;
+    }
+
+
     @Override
     public studentSelectSupervisorRecordDO getRecordByStudentIdAndSupervisorId(Long projectId,Long studentId , Long supervisorId, Integer selectType){
         return studentSelectSupervisorRecordMapper.getRecordByStudentIdAndSupervisorId(projectId,studentId,supervisorId,selectType);
@@ -130,4 +175,9 @@ public class studentSelectSupervisorRecordServiceImpl implements studentSelectSu
         return studentSelectSupervisorRecordMapper.getSupervisorSignatureById(supervisorId);
     }
 
+    @Override
+    public void deleteRecordsByProjectId(Long projectId){
+        studentSelectSupervisorRecordMapper.deleteRecordsByProjectId(projectId);
+    }
+
 }

+ 8 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/supervisorSelectionSetting/supervisorSelectionSettingService.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.supervisorSelectionSettin
 import cn.iocoder.yudao.module.system.dal.dataobject.supervisorSelectionSetting.supervisorSelectionSettingDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 导师学硕专硕名额设置 Service 接口
@@ -54,5 +55,11 @@ public interface supervisorSelectionSettingService {
 
     supervisorSelectionSettingDO getSettingBySupervisorIdAndProjectId(Long supervisorId,Long projectId);
 
-
+    /**
+     * 删除项目下所有导师的名额设置
+     *
+     * @param projectId 项目id
+     * @param supervisorIds 导师ids
+     */
+    void deleteSettingsBySupervisorIds(Long projectId, List<Long> supervisorIds);
 }

+ 8 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/supervisorSelectionSetting/supervisorSelectionSettingServiceImpl.java

@@ -113,4 +113,12 @@ public class supervisorSelectionSettingServiceImpl implements supervisorSelectio
         return supervisorSelectionSettingMapper.getSettingBySupervisorIdAndProjectId(supervisorId,projectId);
     }
 
+    //删除项目下所有导师的名额设置
+    @Override
+    public  void deleteSettingsBySupervisorIds(Long projectId, List<Long> supervisorIds){
+        if (supervisorIds == null || supervisorIds.isEmpty()) {
+            return;
+        }
+         supervisorSelectionSettingMapper.deleteSettingsBySupervisorIds(projectId,supervisorIds);
+    }
 }

+ 12 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java

@@ -256,6 +256,18 @@ public interface AdminUserService {
     List<AdminUserDO> getStudentAndSupervisorNull(String grade);
 
     Boolean isSupervisorNullHasStudent(Long teacherId);
+
+    //初始化当年级下的校生的导师id
+    void updateStudentSupervisorId(String grade);
+
+    //通过的用户分页
+    PageResult<AdminUserDO> getPassedStudentsPage(UserPageReqVO pageReqVO);
+
+    //未通过的用户分页
+    PageResult<AdminUserDO> getUnPassedStudentsPage(UserPageReqVO reqVO);
+
+    //获取user的选择状态
+    Integer getUserSelectStatus(Long id ,Long projectId);
 }
 
 

+ 42 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java

@@ -42,6 +42,7 @@ import com.mzt.logapi.service.impl.DiffParseFunction;
 import com.mzt.logapi.starter.annotation.LogRecord;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
@@ -1209,5 +1210,46 @@ public class AdminUserServiceImpl implements AdminUserService {
         return !list.isEmpty();
     }
 
+    //初始化当年级下的校生的导师id
+    @Override
+    public void updateStudentSupervisorId(String grade){
+        userMapper.updateStudentSupervisorId(grade);
+    }
+
+    @Override
+    public PageResult<AdminUserDO> getPassedStudentsPage(UserPageReqVO reqVO){
+        int offset;
+        if (reqVO.getPageSize() == -1) {
+            offset =-1;  //
+        } else {
+            offset = (reqVO.getPageNo() - 1) * reqVO.getPageSize();
+        }
+        List<AdminUserDO> result =userMapper.getIsPassedStudentsPage(reqVO,offset,1);
+        Long size = userMapper.getIsPassedStudentsPageCount(reqVO,1);
+
+        return new PageResult<>(result,size);
+    }
+
+    @Override
+    public PageResult<AdminUserDO> getUnPassedStudentsPage(UserPageReqVO reqVO){
+        int offset;
+        if (reqVO.getPageSize() == -1) {
+            offset =-1;  //
+        } else {
+            offset = (reqVO.getPageNo() - 1) * reqVO.getPageSize();
+        }
+        List<AdminUserDO> result =userMapper.getIsPassedStudentsPage(reqVO,offset,0);
+        Long size = userMapper.getIsPassedStudentsPageCount(reqVO,0);
+
+        return new PageResult<>(result,size);
+    }
+
+
+
+    //获取学生项目的选择状态
+    @Override
+    public Integer getUserSelectStatus(Long id ,Long projectId){
+        return userMapper.getUserSelectStatus(id,projectId);
+    }
 }
 

+ 251 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/PdfUtils.java

@@ -0,0 +1,251 @@
+package cn.iocoder.yudao.module.system.util;
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @version V1.0
+ * @Description:生成PDF文件
+ * @Author: Mr.LJie
+ * @Date: 2021/11/30 14:17
+ */
+public class PdfUtils {
+    /**
+     * 固定高
+     */
+    public static float fixedHeight = 27f;
+    /**
+     * 跨行
+     */
+    public static int rowSpan = 0;
+    /**
+     * 跨列
+     */
+    public static int colSpan = 0;
+    /**
+     * 左边距
+     */
+    public static float marginLeft = 20;
+    /**
+     * 右边距
+     */
+    public static float marginRight = 20;
+    /**
+     * 上边距
+     */
+    public static float marginTop = 20;
+    /**
+     * 下边距
+     */
+    public static float marginBottom = 20;
+
+    /***
+     * @Description :创建A4纵向文件
+     * @param
+     * @return com.itextpdf.text.Document
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:25
+     */
+    public static Document createPortraitDocument() {
+        //生成pdf
+        Document document = new Document();
+        // 页面大小
+        Rectangle rectangle = new Rectangle(PageSize.A4);
+        // 页面背景颜色
+        rectangle.setBackgroundColor(BaseColor.WHITE);
+        document.setPageSize(rectangle);
+        // 页边距 左,右,上,下
+        document.setMargins(marginLeft, marginRight, marginTop, marginBottom);
+        return document;
+    }
+
+    /***
+     * @Description :创建A4横向文件
+     * @param
+     * @return com.itextpdf.text.Document
+     * @Author Mr.Jie
+     * @Date 2021/11/30 15:42
+     */
+    public static Document createTransverseDocument() {
+        //生成pdf
+        Document document = new Document();
+        // 页面大小
+        Rectangle rectangle = new Rectangle(new RectangleReadOnly(842F, 595F));
+        // 页面背景颜色
+        rectangle.setBackgroundColor(BaseColor.WHITE);
+        document.setPageSize(rectangle);
+        // 页边距 左,右,上,下
+        document.setMargins(marginLeft, marginRight, marginTop, marginBottom);
+
+        return document;
+    }
+
+    /**
+     * @param text 段落内容
+     * @param font 字体设置
+     * @return com.itextpdf.text.Paragraph
+     * @Description :创建段落内容
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:59
+     */
+    public static Paragraph createParagraph(String text, Font font) {
+        Paragraph elements = new Paragraph(text, font);
+        elements.setSpacingBefore(5);
+        elements.setSpacingAfter(5);
+        return elements;
+    }
+
+
+    /***
+     * @Description :创建字体样式
+     * @param fontNumber    字号
+     * @param fontSize      字体大小
+     * @param fontColor     字体颜色
+     * @return com.itextpdf.text.Font
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:57
+     */
+    public static Font createFont(int fontNumber, int fontSize, BaseColor fontColor) {
+        //中文字体 ----不然中文会乱码
+        BaseFont bf = null;
+        try {
+            bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+
+            return new Font(bf, fontNumber, fontSize, fontColor);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return new Font(bf, Font.DEFAULTSIZE, Font.NORMAL, BaseColor.BLACK);
+    }
+
+    /***
+     * @Description :隐藏表格边框线
+     * @param cell  单元格
+     * @return void
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:57
+     */
+    public static void disableBorderSide(PdfPCell cell) {
+        if (cell != null) {
+            cell.disableBorderSide(1);
+            cell.disableBorderSide(2);
+            cell.disableBorderSide(4);
+            cell.disableBorderSide(8);
+        }
+    }
+
+
+    /***
+     * @Description :创建居中得单元格
+     * @param
+     * @return com.itextpdf.text.pdf.PdfPCell
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:57
+     */
+    public static PdfPCell createCenterPdfPCell() {
+        PdfPCell cell = new PdfPCell();
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+        cell.setFixedHeight(fixedHeight);
+        return cell;
+    }
+
+    /***
+     * @Description :创建指定文字得单元格
+     * @param text      文字内容
+     * @param rowSpan   跨行合并单元格
+     * @param colSpan   跨列合并单元格
+     * @param font      字体
+     * @return com.itextpdf.text.pdf.PdfPCell
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:50
+     */
+    public static PdfPCell createCenterPdfPCell(String text, int rowSpan, int colSpan, Font font) {
+        PdfPCell cell = new PdfPCell(new Paragraph(text, font));
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
+        cell.setFixedHeight(fixedHeight);
+        cell.setRowspan(rowSpan);
+        cell.setColspan(colSpan);
+        return cell;
+    }
+
+    /***
+     * @Description :表格列数
+     * @param len
+     * @return com.itextpdf.text.pdf.PdfPTable
+     * @Author Mr.Jie
+     * @Date 2021/11/30 14:52
+     */
+    public static PdfPTable createPdfPTable(int len) {
+        PdfPTable pdfPTable = new PdfPTable(len);
+        //宽度100%填充
+        pdfPTable.setWidthPercentage(100);
+        return pdfPTable;
+    }
+
+    /***
+     * @Description :创建表头
+     * @param document
+     * @param headers
+     * @param font
+     * @return void
+     * @Author Mr.Jie
+     * @Date 2021/11/30 15:27
+     */
+    public static void createHeader(Document document, PdfPTable table, String[] headers, Font font) throws DocumentException {
+        for (int i = 0; i < headers.length; i++) {
+            //默认不跨行、跨列
+            PdfPCell cell = PdfUtils.createCenterPdfPCell(headers[i], rowSpan, rowSpan, font);
+            //居中显示
+            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+            table.addCell(cell);
+        }
+        document.add(table);
+    }
+
+    /***
+     * @Description :数据处理
+     * @param document
+     * @param table
+     * @param list
+     * @param font
+     * @return void
+     * @Author Mr.Jie
+     * @Date 2021/11/30 15:32
+     */
+    public static void dataProcessing(Document document, PdfPTable table, List<Map<String, Object>> list, Font font, int columns) throws DocumentException {
+        float totalTableHeight = 0;
+        float pageHeight = PageSize.A4.getHeight();
+        float bottomMargin = document.bottomMargin();
+        float topMargin = document.topMargin();
+        for (Map<String, Object> map : list) {
+            // 累加表格高度
+            totalTableHeight += fixedHeight;
+            for (Map.Entry<String, Object> entry : map.entrySet()) {
+                Object value = entry.getValue();
+                //默认不跨行、跨列
+                PdfPCell cell = PdfUtils.createCenterPdfPCell(value.toString(), rowSpan, rowSpan, font);
+                // 将单元格添加到表格
+                table.addCell(cell);
+            }
+            // 添加行信息
+            document.add(table);
+            // 检查是否超出一页容量
+            if (totalTableHeight > (pageHeight - bottomMargin - topMargin)) {
+                // 如果超出后重置
+                totalTableHeight = 0;
+                // 开始新的一页
+                document.newPage();
+                // 创建表格
+                table = createPdfPTable(columns);
+            }
+        }
+    }
+}

+ 31 - 0
yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/studentSelectSupervisorRecord/studentSelectSupervisorRecordMapper.xml

@@ -107,6 +107,37 @@
 
     </select>
 
+    <update id="updateRecordNull" parameterType="studentSelectSupervisorRecordDO">
+        UPDATE student_select_supervisor_record
+        <set>
+            <if test="recordDO.projectId != null">
+                project_id = #{recordDO.projectId},
+            </if>
+            <if test="recordDO.studentId != null">
+                student_id = #{recordDO.studentId},
+            </if>
+            <if test="recordDO.supervisorId != null">
+                supervisor_id = #{recordDO.supervisorId},
+            </if>
+            <if test="recordDO.externalSupervisorId != null">
+                external_supervisor_id = #{recordDO.externalSupervisorId},
+            </if>
+            <if test="recordDO.selectType != null">
+                select_type = #{recordDO.selectType},
+            </if>
+--             TODO 能传null
+            student_signature = #{recordDO.studentSignature},
+
+            supervisor_approve_time = #{recordDO.supervisorApproveTime},
+
+            supervisor_signature = #{recordDO.supervisorSignature},
+
+            student_sign_date = #{recordDO.studentSignDate},
+
+            supervisor_sign_date = #{recordDO.supervisorSignDate},
 
+        </set>
+        WHERE id = #{recordDO.id}
+    </update>
 
 </mapper>

+ 18 - 0
yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/supervisorSelectionSetting/supervisorSelectionSettingMapper.xml

@@ -31,4 +31,22 @@
             </if>
         </where>
     </select>
+
+    <update id="deleteSettingsBySupervisorIds" >
+        UPDATE supervisor_selection_setting
+        SET deleted = 1
+        WHERE 1=1
+            <if test="projectId != null">
+                AND project_id = #{projectId}
+            </if>
+            <if test="supervisorIds != null and supervisorIds.size() > 0">
+                AND supervisor_id IN
+                <foreach collection="supervisorIds" item="supervisorId" open="(" close=")" separator=",">
+                    #{supervisorId}
+                </foreach>
+            </if>
+        AND deleted = 0
+    </update>
+
+
 </mapper>

+ 145 - 2
yudao-module-system/yudao-module-system-biz/src/main/resources/Mapper/user/AdminUserMapper.xml

@@ -216,7 +216,6 @@
         ) AS subquery;
     </select>
 
-
     <select id="selectList1" resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO">
         SELECT
         a.*,
@@ -422,9 +421,153 @@
         a.id
     </select>
 
-    <select id="selectIsPop" resultType="Long">
 
+
+
+    <select id="getIsPassedStudentsPage" resultType="cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO">
+        SELECT
+        a.*,r.id,
+        CASE
+        WHEN COALESCE(MAX(r.select_type), 0) = 2 THEN 2
+        WHEN COALESCE(MAX(r.select_type), 0) = 1 THEN 1
+        ELSE 0
+        END AS selectStatus,
+
+        -- 计算 selectStatus 为 1 或 2 的记录 id
+        CASE
+        WHEN COALESCE(MAX(r.select_type), null) IN (1, 2) THEN r.id
+        ELSE NULL
+        END AS recordId,
+
+        COALESCE(system_dept.name, "测绘学院") AS deptName,
+        supervisor_user.nickname AS supervisor,
+        supervisor_user.mobile AS supervisorMobile
+        FROM
+        system_users a
+        LEFT JOIN
+        student_select_supervisor_record r ON r.student_id = a.id AND r.deleted = 0
+        LEFT JOIN
+        system_users supervisor_user ON supervisor_user.id = a.supervisor_id AND supervisor_user.deleted = 0
+        LEFT JOIN
+        system_dept system_dept ON system_dept.id = a.dept_id
+        WHERE
+        1=1
+        <if test="reqVO.username != null and reqVO.username != ''">
+            AND a.username LIKE CONCAT('%', #{reqVO.username}, '%')
+        </if>
+        <if test="reqVO.email != null and reqVO.email != ''">
+            AND a.email LIKE CONCAT('%', #{reqVO.email}, '%')
+        </if>
+        <if test="reqVO.mobile != null and reqVO.mobile != ''">
+            AND a.mobile LIKE CONCAT('%', #{reqVO.mobile}, '%')
+        </if>
+        <if test="reqVO.userNumber != null and reqVO.userNumber != ''">
+            AND a.user_number LIKE CONCAT('%', #{reqVO.userNumber}, '%')
+        </if>
+        <if test="reqVO.nickname != null and reqVO.nickname != ''">
+            AND a.nickname LIKE CONCAT('%', #{reqVO.nickname}, '%')
+        </if>
+        <if test="reqVO.userType != null">
+            AND a.user_type = #{reqVO.userType}
+        </if>
+        <if test="reqVO.grade != '' and reqVO.grade != null ">
+            AND a.grade = #{reqVO.grade}
+        </if>
+        <if test="reqVO.supervisorId != null and reqVO.supervisorId != '' ">
+            AND a.supervisor_id = #{reqVO.supervisorId}
+        </if>
+        <if test="reqVO.major != null  and reqVO.major != '' ">
+            AND a.major = #{reqVO.major}
+        </if>
+        <if test="reqVO.masterType != null and reqVO.masterType != '' ">
+            AND a.masterType = #{reqVO.masterType}
+        </if>
+        <if test="reqVO.status != null and reqVO.status != '' ">
+            AND a.status = #{reqVO.status}
+        </if>
+        AND a.deleted = 0
+        GROUP BY
+        a.id
+
+        <!-- 合并 HAVING 子句 -->
+        HAVING
+        CASE
+        WHEN COALESCE(MAX(r.select_type), 0) = 2 THEN 2
+        WHEN COALESCE(MAX(r.select_type), 0) = 1 THEN 1
+        ELSE 0
+        END
+        <choose>
+            <when test="isPassed == 0">IN (0, 1)</when>
+            <when test="isPassed == 1">= 2</when>
+        </choose>
+
+        ORDER BY
+        a.id DESC
+
+        <if test="offset != -1">
+            LIMIT #{offset}, #{reqVO.pageSize}
+        </if>
+    </select>
+
+    <select id="getIsPassedStudentsPageCount" resultType="Long">
+        SELECT COUNT(*) AS total_count
+        FROM (
+        SELECT a.id
+        FROM system_users a
+        LEFT JOIN student_select_supervisor_record r ON r.student_id = a.id AND r.deleted = 0
+        LEFT JOIN system_users supervisor_user ON supervisor_user.id = a.supervisor_id AND supervisor_user.deleted = 0
+        LEFT JOIN system_dept system_dept ON system_dept.id = a.dept_id
+        WHERE 1 = 1
+        <if test="reqVO.username != null and reqVO.username != ''">
+            AND a.username LIKE CONCAT('%', #{reqVO.username}, '%')
+        </if>
+        <if test="reqVO.email != null and reqVO.email != ''">
+            AND a.email LIKE CONCAT('%', #{reqVO.email}, '%')
+        </if>
+        <if test="reqVO.mobile != null and reqVO.mobile != ''">
+            AND a.mobile LIKE CONCAT('%', #{reqVO.mobile}, '%')
+        </if>
+        <if test="reqVO.userNumber != null and reqVO.userNumber != ''">
+            AND a.user_number LIKE CONCAT('%', #{reqVO.userNumber}, '%')
+        </if>
+        <if test="reqVO.nickname != null and reqVO.nickname != ''">
+            AND a.nickname LIKE CONCAT('%', #{reqVO.nickname}, '%')
+        </if>
+        <if test="reqVO.userType != null">
+            AND a.user_type = #{reqVO.userType}
+        </if>
+        <if test="reqVO.grade != '' and reqVO.grade != null ">
+            AND a.grade = #{reqVO.grade}
+        </if>
+        <if test="reqVO.supervisorId != null and reqVO.supervisorId != '' ">
+            AND a.supervisor_id = #{reqVO.supervisorId}
+        </if>
+        <if test="reqVO.major != null  and reqVO.major != '' ">
+            AND a.major = #{reqVO.major}
+        </if>
+        <if test="reqVO.masterType != null and reqVO.masterType != '' ">
+            AND a.masterType = #{reqVO.masterType}
+        </if>
+        <if test="reqVO.status != null and reqVO.status != '' ">
+            AND a.status = #{reqVO.status}
+        </if>
+        AND a.deleted = 0
+        GROUP BY a.id
+
+        <!-- 合并 HAVING 条件 -->
+        HAVING
+        CASE
+        WHEN COALESCE(MAX(r.select_type), 0) = 2 THEN 2
+        WHEN COALESCE(MAX(r.select_type), 0) = 1 THEN 1
+        ELSE 0
+        END
+        <choose>
+            <when test="isPassed == 0">IN (0, 1)</when>
+            <when test="isPassed == 1">= 2</when>
+        </choose>
+        ) AS subquery;
     </select>
 
 
+
 </mapper>

+ 23 - 23
yudao-server/src/main/resources/application-local.yaml

@@ -46,8 +46,8 @@ spring:
       primary: master
       datasource:
         master:
-          url: jdbc:mysql://172.16.59.50:3306/graduate?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
-#          url: jdbc:mysql://127.0.0.1:3306/graduate?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
+#          url: jdbc:mysql://172.16.59.50:3306/graduate?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
+          url: jdbc:mysql://127.0.0.1:3306/graduate?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
           #          url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
           #          url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
           #          url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
@@ -71,8 +71,8 @@ spring:
 
   # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
   redis:
-    host: 172.16.59.50  # 地址
-#    host: 127.0.0.1  # 地址
+#    host: 172.16.59.50  # 地址
+    host: 127.0.0.1  # 地址
     port: 6379 # 端口
     database: 2 # 数据库索引
     password: 123456 # 密码,建议生产环境开启
@@ -159,26 +159,26 @@ logging:
   file:
     name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
   level:
-    root: OFF
+#    root: OFF
     # 配置自己写的 MyBatis Mapper 打印日志
-#    cn.iocoder.yudao.module.bpm.dal.mysql: debug
-#    cn.iocoder.yudao.module.infra.dal.mysql: debug
-#    cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印
-#    cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info
-#    cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info
-#    cn.iocoder.yudao.module.pay.dal.mysql: debug
-#    cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info
-#    cn.iocoder.yudao.module.system.dal.mysql: debug
-#    cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
-#    cn.iocoder.yudao.module.tool.dal.mysql: debug
-#    cn.iocoder.yudao.module.member.dal.mysql: debug
-#    cn.iocoder.yudao.module.trade.dal.mysql: debug
-#    cn.iocoder.yudao.module.promotion.dal.mysql: debug
-#    cn.iocoder.yudao.module.statistics.dal.mysql: debug
-#    cn.iocoder.yudao.module.crm.dal.mysql: debug
-#    cn.iocoder.yudao.module.erp.dal.mysql: debug
-#    cn.iocoder.yudao.module.ai.dal.mysql: debug
-#    org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR
+    cn.iocoder.yudao.module.bpm.dal.mysql: debug
+    cn.iocoder.yudao.module.infra.dal.mysql: debug
+    cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印
+    cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info
+    cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info
+    cn.iocoder.yudao.module.pay.dal.mysql: debug
+    cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info
+    cn.iocoder.yudao.module.system.dal.mysql: debug
+    cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
+    cn.iocoder.yudao.module.tool.dal.mysql: debug
+    cn.iocoder.yudao.module.member.dal.mysql: debug
+    cn.iocoder.yudao.module.trade.dal.mysql: debug
+    cn.iocoder.yudao.module.promotion.dal.mysql: debug
+    cn.iocoder.yudao.module.statistics.dal.mysql: debug
+    cn.iocoder.yudao.module.crm.dal.mysql: debug
+    cn.iocoder.yudao.module.erp.dal.mysql: debug
+    cn.iocoder.yudao.module.ai.dal.mysql: debug
+    org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR
     # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
 
 debug: false