Browse Source

Merge branch 'pre'

大数据与最优化研究所 4 months ago
parent
commit
07cb2cc809
100 changed files with 3343 additions and 460 deletions
  1. 12 0
      src/main/java/com/xjrsoft/common/annotation/FiledWidth.java
  2. 31 0
      src/main/java/com/xjrsoft/common/constant/GlobalConstant.java
  3. 6 1
      src/main/java/com/xjrsoft/common/enums/EvaluateTypeEnum.java
  4. 2 0
      src/main/java/com/xjrsoft/common/enums/RoleEnum.java
  5. 16 0
      src/main/java/com/xjrsoft/common/mybatis/SqlRunnerAdapter.java
  6. 6 0
      src/main/java/com/xjrsoft/common/utils/LocalDateTimeUtil.java
  7. 114 70
      src/main/java/com/xjrsoft/common/utils/UploadUtil.java
  8. 4 4
      src/main/java/com/xjrsoft/common/utils/WeChatUtil.java
  9. 1 1
      src/main/java/com/xjrsoft/common/xss/XssHttpServletRequestWrapper.java
  10. 1 1
      src/main/java/com/xjrsoft/config/CommonPropertiesConfig.java
  11. 154 0
      src/main/java/com/xjrsoft/config/FileCheckRuleConfig.java
  12. 12 5
      src/main/java/com/xjrsoft/config/JacksonConfig.java
  13. 8 3
      src/main/java/com/xjrsoft/module/assessment/entity/AssessmentTemplatePlan.java
  14. 5 0
      src/main/java/com/xjrsoft/module/assessment/service/impl/AssessmentTemplatePlanServiceImpl.java
  15. 16 0
      src/main/java/com/xjrsoft/module/attendance/controller/AttendanceRuleCategoryController.java
  16. 107 23
      src/main/java/com/xjrsoft/module/attendance/controller/StatisticsController.java
  17. 1 0
      src/main/java/com/xjrsoft/module/attendance/controller/TeacherStatisticsController.java
  18. 3 0
      src/main/java/com/xjrsoft/module/attendance/dto/AddAttendanceRuleCategoryDto.java
  19. 3 0
      src/main/java/com/xjrsoft/module/attendance/dto/AttendanceRuleCategoryPageDto.java
  20. 3 0
      src/main/java/com/xjrsoft/module/attendance/dto/AttendanceStatisticDto.java
  21. 3 0
      src/main/java/com/xjrsoft/module/attendance/dto/TeacherDetailsDto.java
  22. 3 0
      src/main/java/com/xjrsoft/module/attendance/entity/AttendanceRuleCategory.java
  23. 3 0
      src/main/java/com/xjrsoft/module/attendance/entity/AttendanceStatistics.java
  24. 4 0
      src/main/java/com/xjrsoft/module/attendance/mapper/TeacherAttendanceRecordMapper.java
  25. 5 0
      src/main/java/com/xjrsoft/module/attendance/service/ITeacherAttendanceRecordService.java
  26. 15 0
      src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceRuleCategoryServiceImpl.java
  27. 53 36
      src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceStatisticsServiceImpl.java
  28. 5 0
      src/main/java/com/xjrsoft/module/attendance/service/impl/TeacherAttendanceRecordServiceImpl.java
  29. 3 0
      src/main/java/com/xjrsoft/module/attendance/vo/AttendanceRuleCategoryPageVo.java
  30. 3 0
      src/main/java/com/xjrsoft/module/attendance/vo/AttendanceRuleCategoryVo.java
  31. 3 0
      src/main/java/com/xjrsoft/module/attendance/vo/AttendanceStatisticsPageVo.java
  32. 3 0
      src/main/java/com/xjrsoft/module/attendance/vo/TeacherStatisticsVo.java
  33. 94 0
      src/main/java/com/xjrsoft/module/banding/entity/BandingTaskClassStudentSure.java
  34. 4 0
      src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassMapper.java
  35. 7 0
      src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassStudentMapper.java
  36. 26 0
      src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassStudentSureMapper.java
  37. 5 0
      src/main/java/com/xjrsoft/module/banding/service/IBandingTaskClassStudentService.java
  38. 34 6
      src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskClassServiceImpl.java
  39. 239 117
      src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskClassStudentServiceImpl.java
  40. 49 6
      src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskServiceImpl.java
  41. 12 0
      src/main/java/com/xjrsoft/module/banding/vo/BandingTaskClassSureListVo.java
  42. 31 0
      src/main/java/com/xjrsoft/module/banding/vo/SyncStudentDataListVo.java
  43. 27 0
      src/main/java/com/xjrsoft/module/base/controller/BaseClassController.java
  44. 11 0
      src/main/java/com/xjrsoft/module/base/controller/BaseClassCourseController.java
  45. 42 27
      src/main/java/com/xjrsoft/module/base/controller/BaseClassDynamicsController.java
  46. 100 0
      src/main/java/com/xjrsoft/module/base/controller/BaseClassTeacherChangeController.java
  47. 46 3
      src/main/java/com/xjrsoft/module/base/controller/BaseCourseSubjectController.java
  48. 3 0
      src/main/java/com/xjrsoft/module/base/dto/AddBaseClassPageDto.java
  49. 37 0
      src/main/java/com/xjrsoft/module/base/dto/AddBaseClassTeacherChangeDto.java
  50. 10 0
      src/main/java/com/xjrsoft/module/base/dto/BaseClassDynamicsPageDto.java
  51. 27 0
      src/main/java/com/xjrsoft/module/base/dto/BaseClassDynamicsRelationPageDto.java
  52. 46 0
      src/main/java/com/xjrsoft/module/base/dto/BaseClassTeacherChangePageDto.java
  53. 32 0
      src/main/java/com/xjrsoft/module/base/dto/UpdateBaseClassTeacherChangeDto.java
  54. 5 0
      src/main/java/com/xjrsoft/module/base/entity/BaseClass.java
  55. 53 0
      src/main/java/com/xjrsoft/module/base/entity/BaseClassDynamicsRelation.java
  56. 0 1
      src/main/java/com/xjrsoft/module/base/entity/BaseClassMerge.java
  57. 93 0
      src/main/java/com/xjrsoft/module/base/entity/BaseClassTeacherChange.java
  58. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseClassroom.java
  59. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseGrade.java
  60. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseLabel.java
  61. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseMajorSet.java
  62. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseOfficeBuild.java
  63. 6 0
      src/main/java/com/xjrsoft/module/base/entity/BaseSemester.java
  64. 0 2
      src/main/java/com/xjrsoft/module/base/entity/CourseSubjectDetail.java
  65. 17 0
      src/main/java/com/xjrsoft/module/base/mapper/BaseClassDynamicsRelationMapper.java
  66. 21 0
      src/main/java/com/xjrsoft/module/base/mapper/BaseClassTeacherChangeMapper.java
  67. 5 0
      src/main/java/com/xjrsoft/module/base/service/IBaseClassDynamicsService.java
  68. 20 0
      src/main/java/com/xjrsoft/module/base/service/IBaseClassTeacherChangeService.java
  69. 9 1
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassCourseServiceImpl.java
  70. 155 0
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassDynamicsServiceImpl.java
  71. 52 2
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassMergeServiceImpl.java
  72. 31 0
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassServiceImpl.java
  73. 26 0
      src/main/java/com/xjrsoft/module/base/service/impl/BaseClassTeacherChangeServiceImpl.java
  74. 8 1
      src/main/java/com/xjrsoft/module/base/service/impl/BaseCourseSubjectServiceImpl.java
  75. 2 2
      src/main/java/com/xjrsoft/module/base/service/impl/BaseSemesterServiceImpl.java
  76. 27 0
      src/main/java/com/xjrsoft/module/base/vo/BaseClassDynamicsRelationPageVo.java
  77. 3 0
      src/main/java/com/xjrsoft/module/base/vo/BaseClassPageVo.java
  78. 42 0
      src/main/java/com/xjrsoft/module/base/vo/BaseClassTeacherChangePageVo.java
  79. 38 0
      src/main/java/com/xjrsoft/module/base/vo/BaseClassTeacherChangeVo.java
  80. 3 0
      src/main/java/com/xjrsoft/module/base/vo/BaseClassVo.java
  81. 101 43
      src/main/java/com/xjrsoft/module/base/vo/BaseCourseSubjectPageVo.java
  82. 4 0
      src/main/java/com/xjrsoft/module/courseTable/service/ICourseTableService.java
  83. 35 0
      src/main/java/com/xjrsoft/module/courseTable/service/impl/CourseTableServiceImpl.java
  84. 110 7
      src/main/java/com/xjrsoft/module/databoard/controller/DataboardController.java
  85. 143 6
      src/main/java/com/xjrsoft/module/databoard/controller/DatadetailController.java
  86. 37 0
      src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailClassVo.java
  87. 28 0
      src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailCompanyVo.java
  88. 34 0
      src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailEvaluateVo.java
  89. 43 0
      src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailVo.java
  90. 37 0
      src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsVo.java
  91. 4 0
      src/main/java/com/xjrsoft/module/evaluate/dto/EvaluateObjectListDto.java
  92. 181 7
      src/main/java/com/xjrsoft/module/evaluate/service/impl/EvaluateObjectServiceImpl.java
  93. 3 0
      src/main/java/com/xjrsoft/module/evaluate/vo/EvaluateObjectListVo.java
  94. 1 1
      src/main/java/com/xjrsoft/module/form/controller/FormExecuteController.java
  95. 23 0
      src/main/java/com/xjrsoft/module/form/entity/QueryCondition.java
  96. 29 0
      src/main/java/com/xjrsoft/module/form/mapper/CustomFormDataMapper.java
  97. 345 84
      src/main/java/com/xjrsoft/module/form/service/impl/FormExecuteServiceImpl.java
  98. 37 0
      src/main/java/com/xjrsoft/module/form/utils/FormDataSqlProvider.java
  99. 7 0
      src/main/java/com/xjrsoft/module/form/utils/FormDataTransUtil.java
  100. 5 0
      src/main/java/com/xjrsoft/module/generator/entity/ListConfig.java

+ 12 - 0
src/main/java/com/xjrsoft/common/annotation/FiledWidth.java

@@ -0,0 +1,12 @@
+package com.xjrsoft.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FiledWidth {
+    int value() default 0; // 默认为必填
+}

+ 31 - 0
src/main/java/com/xjrsoft/common/constant/GlobalConstant.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @Author: tzx
@@ -519,4 +520,34 @@ public interface GlobalConstant {
      * oauth2 缓存key
      */
     String OAUTH2  = "oauth2:";
+
+    // 允许的文件扩展名与MIME类型映射
+    public static final Map<String, String> ALLOWED_FILE_TYPES = Map.ofEntries(
+            // 图片类型
+            Map.entry("jpg", "image/jpeg"),
+            Map.entry("jpeg", "image/jpeg"),
+            Map.entry("png", "image/png"),
+            Map.entry("gif", "image/gif"),
+            Map.entry("webp", "image/webp"),
+
+            // 文档类型
+            Map.entry("pdf", "application/pdf"),
+            Map.entry("doc", "application/msword"),
+            Map.entry("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
+            Map.entry("xls", "application/vnd.ms-excel"),
+            Map.entry("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
+
+            // 音频类型
+            Map.entry("mp3", "audio/mpeg"),
+            Map.entry("wav", "audio/wav"),
+            Map.entry("ogg", "audio/ogg"),
+            Map.entry("aac", "audio/aac"),
+
+            // 视频类型
+            Map.entry("mp4", "video/mp4"),
+            Map.entry("mov", "video/quicktime"),
+            Map.entry("avi", "video/x-msvideo"),
+            Map.entry("webm", "video/webm")
+    );
+
 }

+ 6 - 1
src/main/java/com/xjrsoft/common/enums/EvaluateTypeEnum.java

@@ -20,7 +20,12 @@ public enum EvaluateTypeEnum {
 
     TEACHER_EVALUATE_CLASS("tea_evaluate_class", "任课教师对班级评价"),
 
-    TEACHER_EVALUATE("teacher_evaluate", "任课教师对班级评价");
+    TEACHER_EVALUATE("teacher_evaluate", "任课教师对班级评价"),
+    STU_SELF_EVALUATE("stu_self_evaluate", "学生自评"),
+
+    CLASS_STU_EVALUATE("class_stu_evaluate", "班级学生交叉互评"),
+
+    TEA_EVALUATE_STU("tea_evaluate_stu", "教师评价班级学生");
 
     final String code;
     final String value;

+ 2 - 0
src/main/java/com/xjrsoft/common/enums/RoleEnum.java

@@ -23,6 +23,8 @@ public enum RoleEnum {
     PARENT(4L, "家长"),
     VISITOR(5L, "访客"),
 
+    BOOKADMIN(1747874695055732738L, "教材管理员"),
+
     CLASSTE(1745630294430511106L, "班主任");
 
     final Long code;

+ 16 - 0
src/main/java/com/xjrsoft/common/mybatis/SqlRunnerAdapter.java

@@ -258,12 +258,22 @@ public class SqlRunnerAdapter implements ISqlRunner, Closeable {
     }
 
     private ImmutablePair<String, List<String>> dynamicInsertBuild(String tableName, Entity params) {
+        // 校验表名是否合法
+        if (!isValidIdentifier(tableName)) {
+            throw new IllegalArgumentException("Invalid table name");
+        }
+
         SQL sql = new SQL().INSERT_INTO(tableName);
         List<String> args = new ArrayList<>();
         int i = 0;
 
         // 循环字段列表并赋值
         for (String key : params.keySet()) {
+            // 校验列名是否合法
+            if (!isValidIdentifier(key)) {
+                continue; // 或者抛出异常
+            }
+
             Object value = params.get(key);
             if (value == null) {
                 continue;
@@ -278,6 +288,12 @@ public class SqlRunnerAdapter implements ISqlRunner, Closeable {
         return new ImmutablePair<>(sql.toString(), args);
     }
 
+    // 校验标识符是否合法的方法
+    private boolean isValidIdentifier(String identifier) {
+        // 使用正则表达式校验,只允许字母、数字和下划线
+        return identifier != null && identifier.matches("^[a-zA-Z0-9_]+$");
+    }
+
     @Transactional
     public Boolean dynamicUpdate(String tableName, Entity params, Entity where) {
         SQL sql = new SQL().UPDATE(tableName);

+ 6 - 0
src/main/java/com/xjrsoft/common/utils/LocalDateTimeUtil.java

@@ -12,6 +12,7 @@ import java.time.LocalTime;
 import java.time.Year;
 import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 
 public final class LocalDateTimeUtil {
     private LocalDateTimeUtil(){}
@@ -147,4 +148,9 @@ public final class LocalDateTimeUtil {
         // 检查目标日期是否在开始日期和结束日期之间(包含边界)
         return !targetDateTime.isBefore(startDateTime) && !targetDateTime.isAfter(endDateTime);
     }
+
+
+    public static long getMinutes(LocalDateTime startDateTime, LocalDateTime endDateTime){
+        return ChronoUnit.MINUTES.between(startDateTime, endDateTime);
+    }
 }

+ 114 - 70
src/main/java/com/xjrsoft/common/utils/UploadUtil.java

@@ -1,70 +1,114 @@
-package com.xjrsoft.common.utils;
-
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.xjrsoft.common.factory.OssFactory;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.ResponseBody;
-import org.apache.commons.collections.CollectionUtils;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-public class UploadUtil {
-
-    //单文件上传
-    public static String  uploadFile(MultipartFile file) throws Exception {
-        if (file.isEmpty()) {
-            throw new RuntimeException("上传文件不能为空");
-        }
-        //上传文件
-        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(StringPool.DOT));
-        return Objects.requireNonNull(OssFactory.build()).uploadSuffix(file.getBytes(), suffix);
-    }
-
-    //多文件上传
-    public  static List<String> uploadFiles(List<MultipartFile> files) throws Exception {
-        if (CollectionUtils.isNotEmpty(files)) {
-            throw new RuntimeException("上传文件不能为空");
-        }
-        List<String> urls = new ArrayList<>();
-        //上传文件
-        for (MultipartFile file : files) {
-            urls.add(uploadFile(file));
-        }
-        return urls;
-    }
-
-    public static InputStream download(String path) {
-        try {
-            OkHttpClient client = new OkHttpClient();
-            Request req = new Request.Builder().url(path).build();
-            InputStream inputStream = null;
-                okhttp3.Response resp = client.newCall(req).execute();
-                if (resp.isSuccessful()) {
-                    ResponseBody body = resp.body();
-                    inputStream = body.byteStream();
-                }
-            return inputStream;
-        } catch (Exception e){
-            throw new RuntimeException("获取文件失败,请检查配置信息", e);
-        }
-    }
-
-    public static boolean delete(String path) {
-     return Objects.requireNonNull(OssFactory.build()).delete(path);
-    }
-
-
-    public static String  uploadFileByte(String fileName, byte[] file) throws Exception {
-        if (file.length == 0) {
-            throw new RuntimeException("上传文件不能为空");
-        }
-        //上传文件
-        String suffix = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf(StringPool.DOT));
-        return Objects.requireNonNull(OssFactory.build()).uploadSuffix(file, suffix);
-    }
-}
+package com.xjrsoft.common.utils;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.xjrsoft.common.constant.GlobalConstant;
+import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.factory.OssFactory;
+import com.xjrsoft.config.FileCheckRuleConfig;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.ResponseBody;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class UploadUtil {
+
+    //单文件上传
+    public static String  uploadFile(MultipartFile file) throws Exception {
+        if (file.isEmpty()) {
+            throw new RuntimeException("上传文件不能为空");
+        }
+        //上传文件
+        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(StringPool.DOT));
+        return Objects.requireNonNull(OssFactory.build()).uploadSuffix(file.getBytes(), suffix);
+    }
+
+    //多文件上传
+    public  static List<String> uploadFiles(List<MultipartFile> files) throws Exception {
+        if (CollectionUtils.isNotEmpty(files)) {
+            throw new RuntimeException("上传文件不能为空");
+        }
+        List<String> urls = new ArrayList<>();
+        //上传文件
+        for (MultipartFile file : files) {
+            urls.add(uploadFile(file));
+        }
+        return urls;
+    }
+
+    public static InputStream download(String path) {
+        try {
+            OkHttpClient client = new OkHttpClient();
+            Request req = new Request.Builder().url(path).build();
+            InputStream inputStream = null;
+                okhttp3.Response resp = client.newCall(req).execute();
+                if (resp.isSuccessful()) {
+                    ResponseBody body = resp.body();
+                    inputStream = body.byteStream();
+                }
+            return inputStream;
+        } catch (Exception e){
+            throw new RuntimeException("获取文件失败,请检查配置信息", e);
+        }
+    }
+
+    public static boolean delete(String path) {
+     return Objects.requireNonNull(OssFactory.build()).delete(path);
+    }
+
+
+    public static String  uploadFileByte(String fileName, byte[] file) throws Exception {
+        if (file.length == 0) {
+            throw new RuntimeException("上传文件不能为空");
+        }
+        //上传文件
+        String suffix = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf(StringPool.DOT));
+        return Objects.requireNonNull(OssFactory.build()).uploadSuffix(file, suffix);
+    }
+
+    /**
+     * 校验文件
+     * @param file 上传的文件
+     * @param rule 校验规则
+     * @throws MyException 校验失败抛出异常
+     */
+    public static void fileTypeValidate(MultipartFile file, FileCheckRuleConfig rule) {
+        // 2. 文件名校验
+        String originalFilename = file.getOriginalFilename();
+        if (StringUtils.isBlank(originalFilename)) {
+            throw new MyException("文件名不能为空");
+        }
+
+        // 3. 文件扩展名校验
+        String fileExtension = getFileExtension(originalFilename);
+        if (!rule.getAllowedExtensions().isEmpty() &&
+                !rule.getAllowedExtensions().contains(fileExtension.toLowerCase())) {
+            throw new MyException("不支持的文件类型,仅支持: " +
+                    String.join(", ", rule.getAllowedExtensions()));
+        }
+
+        // 4. MIME类型校验
+        String contentType = file.getContentType();
+        if (!rule.getAllowedMimeTypes().isEmpty() &&
+                !rule.getAllowedMimeTypes().contains(contentType)) {
+            throw new MyException("文件类型不匹配,仅支持: " +
+                    String.join(", ", rule.getAllowedMimeTypes()));
+        }
+    }
+
+    // 安全的获取扩展名方法
+    private static String getFileExtension(String filename) {
+        // 处理没有扩展名的情况
+        int dotIndex = filename.lastIndexOf('.');
+        if (dotIndex < 0) {
+            throw new MyException("文件缺少扩展名");
+        }
+        return filename.substring(dotIndex + 1).toLowerCase();
+    }
+}

+ 4 - 4
src/main/java/com/xjrsoft/common/utils/WeChatUtil.java

@@ -201,19 +201,19 @@ public class WeChatUtil {
     //                   }
     //           }
     //       }
-    public Boolean sendTemplateMessage(JSONObject object){
+    public String sendTemplateMessage(JSONObject object){
         String active = SpringUtil.getActiveProfile();
         if("dev".equals(active)){
             log.info("测试环境,无法执行数据推送");
-            return false;
+            return null;
         }
         String token = this.getToken(WeChatType.WEWEB);
         String result = HttpUtil.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+token, JSONObject.toJSONString(object));
         if(!result.contains("ok")){
             log.error(JSONObject.toJSONString(object), result);
         }
-        System.out.printf(result);
-        return true;
+//        System.err.printf(result);
+        return result;
     }
 
     public String getTicket(String type) {

+ 1 - 1
src/main/java/com/xjrsoft/common/xss/XssHttpServletRequestWrapper.java

@@ -34,7 +34,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
 
     private String method;
 
-    private final List<String> ignoreXssUrl = ListUtil.toList("/magic-api/**", "/magic/web/**", "/workflow/execute/*", "/oa/wfMeetingApply/update_meetingSummary");
+    private final List<String> ignoreXssUrl = ListUtil.toList("/magic-api/**", "/magic/web/**", "/workflow/execute/*", "/oa/wfMeetingApply/update_meetingSummary", "/base/baseClassDynamics", "/teacher/classInternshipDynamic", "/teacher/classHomework");
     //html过滤
     private final static HTMLFilter HTML_FILTER = new HTMLFilter();
 

+ 1 - 1
src/main/java/com/xjrsoft/config/CommonPropertiesConfig.java

@@ -19,7 +19,7 @@ public class CommonPropertiesConfig {
 
     private String druidPassword;
 
-    private String defaultPassword;
+//    private String defaultPassword;
 
     /**
      * api域名地址

+ 154 - 0
src/main/java/com/xjrsoft/config/FileCheckRuleConfig.java

@@ -0,0 +1,154 @@
+package com.xjrsoft.config;
+
+import lombok.Getter;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 文件校验规则配置(优化版)
+ */
+@Getter
+public final class FileCheckRuleConfig {
+    /* ========== 基础类型规则 ========== */
+    /**
+     * 图片规则(严格模式)
+     */
+    public static final FileCheckRuleConfig IMAGE = builder()
+            .withExtensions("jpg", "jpeg", "png", "gif", "webp", "bmp")
+            .withMimeTypes(
+                    "image/jpeg",
+                    "image/png",
+                    "image/gif",
+                    "image/webp",
+                    "image/bmp"
+            )
+            .build();
+    /**
+     * 视频规则
+     */
+    public static final FileCheckRuleConfig VIDEO = builder()
+            .withExtensions("mp4", "mov", "avi", "wmv", "flv", "mkv")
+            .withMimeTypes(
+                    "video/mp4",
+                    "video/quicktime",
+                    "video/x-msvideo",
+                    "video/x-ms-wmv",
+                    "video/x-flv",
+                    "video/x-matroska"
+            )
+            .build();
+    /**
+     * 音频规则
+     */
+    public static final FileCheckRuleConfig AUDIO = builder()
+            .withExtensions("mp3", "wav", "aac", "flac", "ogg", "m4a")
+            .withMimeTypes(
+                    "audio/mpeg",
+                    "audio/wav",
+                    "audio/aac",
+                    "audio/flac",
+                    "audio/ogg",
+                    "audio/x-m4a"
+            )
+            .build();
+    /**
+     * 文档规则
+     */
+    public static final FileCheckRuleConfig DOCUMENT = builder()
+            .withExtensions("pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt")
+            .withMimeTypes(
+                    "application/pdf",
+                    "application/msword",
+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+                    "application/vnd.ms-excel",
+                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+                    "application/vnd.ms-powerpoint",
+                    "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+                    "text/plain"
+            )
+            .build();
+    /* ========== 组合类型规则 ========== */
+    /**
+     * 媒体规则(图片+视频)
+     */
+    public static final FileCheckRuleConfig MEDIA = combine(IMAGE, VIDEO);
+    /**
+     * 图片和文档规则
+     */
+    public static final FileCheckRuleConfig IMAGE_AND_DOCUMENT = combine(IMAGE, DOCUMENT);
+    /**
+     * 所有类型规则
+     */
+    public static final FileCheckRuleConfig ALL = combine(IMAGE, VIDEO, AUDIO, DOCUMENT);
+
+    private final Set<String> allowedExtensions;
+    private final Set<String> allowedMimeTypes;
+
+    private FileCheckRuleConfig(Builder builder) {
+        this.allowedExtensions = Collections.unmodifiableSet(builder.extensions);
+        this.allowedMimeTypes = Collections.unmodifiableSet(builder.mimeTypes);
+    }
+
+    /**
+     * 创建新的构建器
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * 合并多个规则配置
+     */
+    public static FileCheckRuleConfig combine(FileCheckRuleConfig... configs) {
+        Builder builder = builder();
+        for (FileCheckRuleConfig config : configs) {
+            builder.extensions.addAll(config.allowedExtensions);
+            builder.mimeTypes.addAll(config.allowedMimeTypes);
+        }
+        return builder.build();
+    }
+
+    /**
+     * 构建器类
+     */
+    public static final class Builder {
+        private final Set<String> extensions = new HashSet<>();
+        private final Set<String> mimeTypes = new HashSet<>();
+
+        private Builder() {
+        }
+
+        public Builder withExtensions(String... extensions) {
+            this.extensions.addAll(Arrays.asList(extensions));
+            return this;
+        }
+
+        public Builder withMimeTypes(String... mimeTypes) {
+            this.mimeTypes.addAll(Arrays.asList(mimeTypes));
+            return this;
+        }
+
+        public Builder addExtension(String extension) {
+            this.extensions.add(extension);
+            return this;
+        }
+
+        public Builder addMimeType(String mimeType) {
+            this.mimeTypes.add(mimeType);
+            return this;
+        }
+
+        public Builder from(FileCheckRuleConfig config) {
+            this.extensions.addAll(config.allowedExtensions);
+            this.mimeTypes.addAll(config.allowedMimeTypes);
+            return this;
+        }
+
+        public FileCheckRuleConfig build() {
+            return new FileCheckRuleConfig(this);
+        }
+    }
+}

+ 12 - 5
src/main/java/com/xjrsoft/config/JacksonConfig.java

@@ -9,10 +9,8 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
 import com.xjrsoft.common.handler.EasyExcelLocalDateTimeConverter;
@@ -53,7 +51,15 @@ public class JacksonConfig {
         return builder -> {
             builder.serializerByType(Long.class, ToStringSerializer.instance);
             builder.serializerByType(Long.TYPE, ToStringSerializer.instance);
-            builder.serializerByType(BigDecimal.class, ToStringSerializer.instance);
+
+            // 自定义 BigDecimal 序列化器,使用 toPlainString()
+            builder.serializerByType(BigDecimal.class, new JsonSerializer<BigDecimal>() {
+                @Override
+                public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+                    gen.writeString(value.stripTrailingZeros().toPlainString());
+                }
+            });
+
             builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
             builder.serializerByType(INTERVALDS.class, intervalDSSerializer());
             builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
@@ -143,4 +149,5 @@ public class JacksonConfig {
             }
         };
     }
+
 }

+ 8 - 3
src/main/java/com/xjrsoft/module/assessment/entity/AssessmentTemplatePlan.java

@@ -1,12 +1,17 @@
 package com.xjrsoft.module.assessment.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.github.yulichang.annotation.EntityMapping;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 
@@ -41,7 +46,7 @@ public class AssessmentTemplatePlan implements Serializable {
      */
     @ApiModelProperty("")
     @TableField(fill = FieldFill.INSERT)
-    private Date createDate;
+    private LocalDateTime createDate;
     /**
      *
      */
@@ -53,7 +58,7 @@ public class AssessmentTemplatePlan implements Serializable {
      */
     @ApiModelProperty("")
     @TableField(fill = FieldFill.UPDATE)
-    private Date modifyDate;
+    private LocalDateTime modifyDate;
     /**
      *
      */

+ 5 - 0
src/main/java/com/xjrsoft/module/assessment/service/impl/AssessmentTemplatePlanServiceImpl.java

@@ -4,6 +4,7 @@ import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -818,6 +819,10 @@ public class AssessmentTemplatePlanServiceImpl extends MPJBaseServiceImpl<Assess
                         .eq(AssessmentPlanAnswerClass::getDeleteMark, DeleteMark.NODELETE.getCode())
                         .eq(AssessmentPlanAnswerClass::getAssessmentTemplatePlanId, templatePlan.getId())
         );
+        String active = SpringUtil.getActiveProfile();
+        if (!"prod".equals(active)) {
+            return true;
+        }
         for (AssessmentPlanAnswerClass answerClass : classList) {
             this.sendMsg(new AssessmentTemplatePlanSureDto() {{
                 setClassId(answerClass.getClassId());

+ 16 - 0
src/main/java/com/xjrsoft/module/attendance/controller/AttendanceRuleCategoryController.java

@@ -69,6 +69,22 @@ public class AttendanceRuleCategoryController {
         return RT.ok(pageOutput);
     }
 
+    @GetMapping(value = "/list")
+    @ApiOperation(value = "考勤规则列表(不分页)")
+    @SaCheckPermission("attendancerulecategory:detail")
+    @XjrLog(value = "考勤规则列表(不分页)")
+    public RT<List<AttendanceRuleCategoryPageVo>> list(@Valid AttendanceRuleCategoryPageDto dto) {
+
+        LambdaQueryWrapper<AttendanceRuleCategory> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper
+                .orderByDesc(AttendanceRuleCategory::getId)
+                .eq(dto.getRoleId() != null, AttendanceRuleCategory::getRoleId, dto.getRoleId())
+                .select(AttendanceRuleCategory.class, x -> VoToColumnUtil.fieldsToColumns(AttendanceRuleCategoryPageVo.class).contains(x.getProperty()));
+        List<AttendanceRuleCategory> page = attendanceRuleCategoryService.list(queryWrapper);
+        List<AttendanceRuleCategoryPageVo> pageOutput = BeanUtil.copyToList(page, AttendanceRuleCategoryPageVo.class);
+        return RT.ok(pageOutput);
+    }
+
     @GetMapping(value = "/info")
     @ApiOperation(value = "根据id查询考勤规则信息")
     @SaCheckPermission("attendancerulecategory:detail")

+ 107 - 23
src/main/java/com/xjrsoft/module/attendance/controller/StatisticsController.java

@@ -2,15 +2,25 @@ package com.xjrsoft.module.attendance.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.yulichang.toolkit.MPJWrappers;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 import com.xjrsoft.common.annotation.XjrLog;
+import com.xjrsoft.common.enums.DeleteMark;
 import com.xjrsoft.common.enums.OutInStatusEnum;
 import com.xjrsoft.common.enums.StudyStatusEnum;
+import com.xjrsoft.common.model.result.R;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.attendance.dto.AttendanceStatisticDto;
 import com.xjrsoft.module.attendance.dto.TeacherDetailsDto;
+import com.xjrsoft.module.attendance.entity.AttendanceRuleCategory;
+import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
+import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
 import com.xjrsoft.module.attendance.service.ITeacherAttendanceRecordService;
 import com.xjrsoft.module.attendance.vo.TeacherStatisticsPageVo;
 import com.xjrsoft.module.attendance.vo.TeacherStatisticsVo;
@@ -24,8 +34,12 @@ import com.xjrsoft.module.personnel.service.IReservationSchoolService;
 import com.xjrsoft.module.student.entity.BaseStudent;
 import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
 import com.xjrsoft.module.student.service.IStudentLeaveService;
+import com.xjrsoft.module.system.service.IDictionarydetailService;
+import com.xjrsoft.module.teacher.dto.BaseTeacherPageDto;
 import com.xjrsoft.module.teacher.entity.BaseTeacher;
 import com.xjrsoft.module.teacher.entity.XjrUser;
+import com.xjrsoft.module.teacher.service.ITeacherbaseManagerService;
+import com.xjrsoft.module.teacher.vo.XjrUserPageVo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -39,6 +53,8 @@ import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -61,19 +77,34 @@ public class StatisticsController {
     private final IStudentLeaveService studentLeaveService;
     private final IReservationSchoolService reservationSchoolService;
     private final ITeacherAttendanceRecordService attendanceRecordService;
+    private final IAttendanceRuleCategoryService ruleCategoryService;
 
     @GetMapping(value = "/teacher-statistics")
     @ApiOperation(value = "教职工考勤统计")
     @SaCheckPermission("statistics:detail")
-    @XjrLog(value = "", saveResponseData = true)
+    @XjrLog(value = "教职工考勤统计", saveResponseData = true)
     public RT<TeacherStatisticsVo> teacherStatistics(@Valid AttendanceStatisticDto dto) {
         TeacherStatisticsVo statisticsVo = new TeacherStatisticsVo();
+
+        if(dto.getRuleCategoryId() == null){
+            AttendanceRuleCategory ruleCategory = ruleCategoryService.getOne(
+                    new QueryWrapper<AttendanceRuleCategory>().lambda()
+                            .eq(AttendanceRuleCategory::getIsDefaultShow, 1)
+                            .eq(AttendanceRuleCategory::getRoleId, 2)
+            );
+            if(ruleCategory != null){
+                dto.setRuleCategoryId(ruleCategory.getId());
+            }
+        }
+
         //查询总人数
         MPJLambdaWrapper<XjrUser> queryWrapper = MPJWrappers.<XjrUser>lambdaJoin()
-                .disableSubLogicDel()
+                .disableLogicDel()
                 .eq(ObjectUtil.isNotNull(dto.getDeptId()), UserDeptRelation::getDeptId, dto.getDeptId())
+                .eq(AttendanceUserRelation::getAttendanceRuleCategoryId, dto.getRuleCategoryId())
                 .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
-                .innerJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId);
+                .innerJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId)
+                .innerJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId);
         long allCount = xjrUserService.count(queryWrapper);
         statisticsVo.setAllCount(allCount);
 
@@ -81,38 +112,91 @@ public class StatisticsController {
         detailsDto.setDate(dto.getDate());
         detailsDto.setDeptId(dto.getDeptId());
         detailsDto.setTimePeriod(dto.getTimePeriod());
+        detailsDto.setRuleCategoryId(dto.getRuleCategoryId());
         List<TeacherStatisticsPageVo> list = attendanceRecordService.getList(detailsDto);
 
-        Long actualCount = 0L;
-        Long lateCount = 0L;
-        Long leaveCount = 0L;
-        Long absenteeismCount = 0L;
-        Integer dividendCount = 0;
+        Set<Long> actualCount = new HashSet<>();
+        Set<Long> lateCount = new HashSet<>();
+        Set<Long> leaveCount = new HashSet<>();
+        Set<Long> absenteeismCount = new HashSet<>();
+        Set<Long> dividendCount = new HashSet<>();
+        Set<Long> teacherIds = new HashSet<>();
+        List<String> leaveTypes = new ArrayList<>();
+        leaveTypes.add("事假");leaveTypes.add("公假");leaveTypes.add("会议活动");leaveTypes.add("病假");
         for (TeacherStatisticsPageVo recordVo : list) {
+            teacherIds.add(recordVo.getUserId());
             if ("迟到".equals(recordVo.getStatus())) {
-                lateCount++;
-                dividendCount++;
-            } else if ("请假".equals(recordVo.getStatus())) {
-                leaveCount++;
-                dividendCount++;
+                lateCount.add(recordVo.getUserId());
+                dividendCount.add(recordVo.getUserId());
+            } else if (leaveTypes.contains(recordVo.getStatus())) {
+                leaveCount.add(recordVo.getUserId());
+                dividendCount.add(recordVo.getUserId());
             } else if ("缺勤".equals(recordVo.getStatus())) {
-                absenteeismCount++;
-                dividendCount++;
+                absenteeismCount.add(recordVo.getUserId());
+                dividendCount.add(recordVo.getUserId());
             }
             if (recordVo.getRecordTime() != null) {
-                actualCount++;
-                dividendCount++;
+                actualCount.add(recordVo.getUserId());
+                dividendCount.add(recordVo.getUserId());
             }
         }
-        statisticsVo.setLateCount(lateCount);
-        statisticsVo.setActualCount(actualCount);
-        statisticsVo.setLeaveCount(leaveCount);
-        statisticsVo.setAbsenteeismCount(absenteeismCount);
+        statisticsVo.setLateCount(lateCount.stream().count());
+        statisticsVo.setActualCount(actualCount.stream().count());
+        statisticsVo.setLeaveCount(leaveCount.stream().count());
+        statisticsVo.setAbsenteeismCount(absenteeismCount.stream().count());
+
+//        //查询不需要考勤的人
+//        List<AttendanceRuleCategory> ruleCategories = ruleCategoryService.list(
+//                new QueryWrapper<AttendanceRuleCategory>().lambda()
+//                        .eq(AttendanceRuleCategory::getDeleteMark, DeleteMark.NODELETE.getCode())
+//                        .eq(AttendanceRuleCategory::getRoleId, 2)
+//                        .le(AttendanceRuleCategory::getStartDate, LocalDate.now())
+//                        .ge(AttendanceRuleCategory::getEndDate, LocalDate.now())
+//        );
+//        if(!ruleCategories.isEmpty()){
+//            //查询所有需要考勤的人
+//            BaseTeacherPageDto teacherPageDto = new BaseTeacherPageDto();
+//            List<Long> userIds = new ArrayList<>();
+//            List<Long> deptIds = new ArrayList<>();
+//            for (AttendanceRuleCategory ruleCategory : ruleCategories) {
+//                JsonArray userRelation = new JsonParser().parse(ruleCategory.getUserRelation()).getAsJsonArray();
+//
+//                for (JsonElement jsonElement : userRelation) {
+//                    JsonObject jsonObject = jsonElement.getAsJsonObject();
+//                    if(jsonObject.get("deptId") != null && !jsonObject.get("deptId").isJsonNull()){
+//                        deptIds.add(jsonObject.get("deptId").getAsLong());
+//                    }
+//                    if(jsonObject.get("userId") != null && !jsonObject.get("userId").isJsonNull()){
+//                        userIds.add(jsonObject.get("userId").getAsLong());
+//                    }
+//                }
+//            }
+//            teacherPageDto.setDeptIds(deptIds);
+//            List<XjrUserPageVo> attendanceTeacherList = teacherbaseManagerService.getList(teacherPageDto);
+//
+//            teacherPageDto = new BaseTeacherPageDto();
+//            teacherPageDto.setUserIds(userIds);
+//            attendanceTeacherList.addAll(teacherbaseManagerService.getList(teacherPageDto));
+//            //将所有需要考勤的人的id存入set集合
+//            Set<String> attendanceUserIdSet = attendanceTeacherList.stream().map(XjrUserPageVo::getId).collect(Collectors.toSet());
+//
+//            //查询所有人
+//            teacherPageDto = new BaseTeacherPageDto();
+//            if(dto.getDeptId() != null){
+//                List<Long> dtoDeptIds = new ArrayList<>();
+//                dtoDeptIds.add(dto.getDeptId());
+//                teacherPageDto.setDeptIds(dtoDeptIds);
+//            }
+//
+//            List<XjrUserPageVo> allTeacherList = teacherbaseManagerService.getList(teacherPageDto);
+//            statisticsVo.setNotAttendanceCount(allTeacherList.stream().filter(x -> !attendanceUserIdSet.contains(x.getId())).collect(Collectors.toList()).size());
+//        }
+
 
         //计算出勤率
         BigDecimal divide = BigDecimal.ZERO;
-        if (dividendCount != 0) {
-            divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(dividendCount), 4, RoundingMode.HALF_UP);
+        if (!dividendCount.isEmpty()) {
+            divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(dividendCount.size()), 4, RoundingMode.HALF_UP);
         }
         statisticsVo.setAttendanceRate(divide.doubleValue() + "");
 

+ 1 - 0
src/main/java/com/xjrsoft/module/attendance/controller/TeacherStatisticsController.java

@@ -92,6 +92,7 @@ public class TeacherStatisticsController {
                             " WHERE t1.delete_mark = 0 AND t2.user_id = t.id) as dept_name")
                     .eq(ObjectUtil.isNotNull(dto.getDeptId()), UserDeptRelation::getDeptId, dto.getDeptId())
                     .eq(StrUtil.isNotEmpty(dto.getAttendanceMode()), AttendanceUserRelation::getAttendanceMode, dto.getAttendanceMode())
+                    .eq(ObjectUtil.isNotNull(dto.getRuleCategoryId()), AttendanceUserRelation::getAttendanceRuleCategoryId, dto.getRuleCategoryId())
                     .like(StrUtil.isNotEmpty(dto.getCarNumber()), AttendanceUserRelation::getCarNumber, dto.getCarNumber())
                     .like(StrUtil.isNotEmpty(dto.getName()), User::getName, dto.getName())
                     .selectAs(User::getName, TeacherStatisticsPageVo::getTeacherName)

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/dto/AddAttendanceRuleCategoryDto.java

@@ -74,4 +74,7 @@ public class AddAttendanceRuleCategoryDto implements Serializable {
 
     @ApiModelProperty("非考勤周期是否允许进出(1:是 0:否)")
     private Integer notCycleIsInOut;
+
+    @ApiModelProperty("是否默认显示(1:是 0:否)")
+    private Integer isDefaultShow;
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/dto/AttendanceRuleCategoryPageDto.java

@@ -1,6 +1,7 @@
 package com.xjrsoft.module.attendance.dto;
 
 import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -15,5 +16,7 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = false)
 public class AttendanceRuleCategoryPageDto extends PageInput {
 
+    @ApiModelProperty("被考勤角色(xjr_role)")
+    private Long roleId;
 
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/dto/AttendanceStatisticDto.java

@@ -29,4 +29,7 @@ public class AttendanceStatisticDto extends PageInput {
 
     @ApiModelProperty("部门id")
     private Long deptId;
+
+    @ApiModelProperty("考勤规则id")
+    private Long ruleCategoryId;
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/dto/TeacherDetailsDto.java

@@ -32,4 +32,7 @@ public class TeacherDetailsDto extends PageInput {
 
     @ApiModelProperty("车牌号")
     private String carNumber;
+
+    @ApiModelProperty("考勤规则id")
+    private Long ruleCategoryId;
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/entity/AttendanceRuleCategory.java

@@ -125,4 +125,7 @@ public class AttendanceRuleCategory implements Serializable {
     @ApiModelProperty("非考勤周期是否允许进出(1:是 0:否)")
     private Integer notCycleIsInOut;
 
+    @ApiModelProperty("是否默认显示(1:是 0:否)")
+    private Integer isDefaultShow;
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/entity/AttendanceStatistics.java

@@ -132,4 +132,7 @@ public class AttendanceStatistics implements Serializable {
     @EntityMapping(thisField = "id", joinField = "attendanceStatisticsId")
     private List<AttendanceStatisticsRecord> attendanceStatisticsRecordList;
 
+    @ApiModelProperty("备注")
+    private String remarks;
+
 }

+ 4 - 0
src/main/java/com/xjrsoft/module/attendance/mapper/TeacherAttendanceRecordMapper.java

@@ -6,6 +6,7 @@ import com.xjrsoft.module.attendance.dto.TeacherDetailsDto;
 import com.xjrsoft.module.attendance.entity.TeacherAttendanceRecord;
 import com.xjrsoft.module.attendance.vo.TeacherStatisticsPageVo;
 import com.xjrsoft.module.teacher.entity.WfTeacherleave;
+import org.apache.ibatis.annotations.Delete;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -25,4 +26,7 @@ public interface TeacherAttendanceRecordMapper extends MPJBaseMapper<TeacherAtte
 
 
     List<TeacherAttendanceRecord> getLeaveList(@Param("dto") WfTeacherleave dto);
+
+    @Delete("delete from teacher_attendance_record where time_interval = #{timePeriod} and attendance_date = #{attendanceDate}")
+    Boolean deleteRecord(@Param("timePeriod") Integer timePeriod, @Param("attendanceDate") String attendanceDate);
 }

+ 5 - 0
src/main/java/com/xjrsoft/module/attendance/service/ITeacherAttendanceRecordService.java

@@ -6,7 +6,10 @@ import com.xjrsoft.module.attendance.dto.ResetTeacherAttendanceRecordDto;
 import com.xjrsoft.module.attendance.dto.TeacherDetailsDto;
 import com.xjrsoft.module.attendance.entity.TeacherAttendanceRecord;
 import com.xjrsoft.module.attendance.vo.TeacherStatisticsPageVo;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Param;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -23,4 +26,6 @@ public interface ITeacherAttendanceRecordService extends MPJBaseService<TeacherA
     List<TeacherStatisticsPageVo> getList(TeacherDetailsDto dto);
 
     Boolean resetData(ResetTeacherAttendanceRecordDto dto);
+
+    Boolean deleteRecord(Integer timePeriod, String attendanceDate);
 }

+ 15 - 0
src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceRuleCategoryServiceImpl.java

@@ -57,6 +57,13 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(AddAttendanceRuleCategoryDto dto) {
+        List<AttendanceRuleCategory> defaultShowRuleCategories = this.list(
+                new QueryWrapper<AttendanceRuleCategory>().lambda()
+                        .eq(AttendanceRuleCategory::getIsDefaultShow, 1)
+        );
+        if(!defaultShowRuleCategories.isEmpty() && dto.getIsDefaultShow() != null && dto.getIsDefaultShow() == 1){
+            throw new MyException("已存在一个默认显示的规则,无法再次添加");
+        }
         AttendanceRuleCategory attendanceRuleCategory = BeanUtil.toBean(dto, AttendanceRuleCategory.class);
         attendanceRuleCategory.setUserRelation(JsonUtil.toJsonString(dto.getAttendanceUserRelationList()));
 
@@ -209,6 +216,14 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean update(UpdateAttendanceRuleCategoryDto dto) {
+        List<AttendanceRuleCategory> defaultShowRuleCategories = this.list(
+                new QueryWrapper<AttendanceRuleCategory>().lambda()
+                        .eq(AttendanceRuleCategory::getIsDefaultShow, 1)
+                        .ne(AttendanceRuleCategory::getId, dto.getId())
+        );
+        if(!defaultShowRuleCategories.isEmpty() && dto.getIsDefaultShow() != null && dto.getIsDefaultShow() == 1){
+            throw new MyException("已存在一个默认显示的规则,无法再次添加");
+        }
         AttendanceRuleCategory attendanceRuleCategory = BeanUtil.toBean(dto, AttendanceRuleCategory.class);
         attendanceRuleCategory.setUserRelation(JsonUtil.toJsonString(dto.getAttendanceUserRelationList()));
         if (attendanceRuleCategory.getAttendanceRange() == 1) {

+ 53 - 36
src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceStatisticsServiceImpl.java

@@ -17,7 +17,11 @@ import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.attendance.dto.AddAttendanceStatisticsDto;
 import com.xjrsoft.module.attendance.dto.AttendanceStatisticsPageDto;
 import com.xjrsoft.module.attendance.dto.AttendanceStatisticsRecordDto;
-import com.xjrsoft.module.attendance.entity.*;
+import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
+import com.xjrsoft.module.attendance.entity.AttendanceStatistics;
+import com.xjrsoft.module.attendance.entity.AttendanceStatisticsRecord;
+import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
+import com.xjrsoft.module.attendance.entity.TeacherAttendanceRecord;
 import com.xjrsoft.module.attendance.mapper.AttendanceStatisticsMapper;
 import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
 import com.xjrsoft.module.attendance.service.IAttendanceStatisticsRecordService;
@@ -40,7 +44,15 @@ import com.xjrsoft.module.teacher.mapper.FaceImportMapper;
 import com.xjrsoft.module.teacher.service.IWfTeacherleaveService;
 import lombok.AllArgsConstructor;
 import me.zhyd.oauth.log.Log;
-import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.stereotype.Service;
@@ -51,9 +63,16 @@ import java.io.IOException;
 import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -89,24 +108,15 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(AddAttendanceStatisticsDto dto) {
-        try {
-            AttendanceStatistics statistics = BeanUtil.toBean(dto, AttendanceStatistics.class);
-            statistics.setCreateDate(new Date());
-            statistics.setStatus(0);
-            statisticsMapper.insert(statistics);
-
-            //1、同步出入记录的数据
-            //2、固化考勤数据
-            refreshRecord(statistics.getId());
-            return true;
-        } catch (Exception e) {
-            Log.error(e.getMessage(), e);
-            if(e.getClass().equals(MyException.class)){
-                throw new MyException(e.getMessage());
-            }else{
-                throw new MyException("添加报错,请联系管理员");
-            }
-        }
+        AttendanceStatistics statistics = BeanUtil.toBean(dto, AttendanceStatistics.class);
+        statistics.setCreateDate(new Date());
+        statistics.setStatus(0);
+        statisticsMapper.insert(statistics);
+
+        //1、同步出入记录的数据
+        //2、固化考勤数据
+        refreshRecord(statistics.getId());
+        return true;
     }
 
     @Override
@@ -173,6 +183,9 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean refreshRecord(Long id) {
+        String remarks = null;
+        int personCount = 0;
+        int attendanceDays = 0;
         try {
             //1、修改状态为统计中
             AttendanceStatistics statistics = this.getById(id);
@@ -182,7 +195,8 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
 
             List<LocalDate> dateList2 = getDatesBetween(statistics.getStartDate(), statistics.getEndDate());
             LocalDateTime now = LocalDateTime.now();
-            if (dateList2.contains(now.toLocalDate())) {
+
+            if (dateList2.contains(now.toLocalDate()) && (statistics.getTimePeriod() == 1 && now.toLocalTime().isBefore(LocalTime.MIDNIGHT))) {
                 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                 String sql = "DELETE FROM teacher_attendance_record WHERE attendance_date = '" + now.toLocalDate().format(dtf) + "'" +
                         " AND time_interval = " + statistics.getTimePeriod();
@@ -199,10 +213,11 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
                     outInRecordUtil.getTeacherRecords(faceImportMapper, startDateTime, endDateTime, teacherRules);
                     //拉取车辆数据
                     outInRecordUtil.GetVehicleRecord(faceImportMapper, startDateTime, endDateTime);
-                } catch (ParseException e) {
-                    Log.error(e.getMessage(), e);
+                }catch (Exception e){
+                    Log.error(e.getMessage());
                 }
 
+
                 AttendanceRecordTask recordTask = new AttendanceRecordTask();
                 recordTask.teacherAttendanceRecord(startDateTime, statistics.getTimePeriod(),
                         userService,
@@ -215,7 +230,6 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
                 );
             }
 
-
             //2、删除以前的数据
             statisticsRecordService.remove(
                     new QueryWrapper<AttendanceStatisticsRecord>().lambda()
@@ -263,6 +277,7 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
 
             //3.4、计算出所有的天数
             List<LocalDate> dateList = getDatesBetween(statistics.getStartDate(), statistics.getEndDate(), ruleMap, weekEnMap);
+            attendanceDays = dateList.size();
 
             //3.5、循环计算,并存入insertList,方便后续批量入库
             List<AttendanceStatisticsRecord> insertList = new ArrayList<>();
@@ -274,9 +289,6 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
             for (User user : userList) {
                 AttendanceStatisticsRecord record = new AttendanceStatisticsRecord();
                 record.setUserId(user.getId());
-                if (14954799879750L == user.getId()) {
-                    System.out.println(user.getName());
-                }
                 record.setAttendanceStatisticsId(statistics.getId());
                 Long normalCount = 0L;
                 Long leaveCount = 0L;
@@ -336,24 +348,29 @@ public class AttendanceStatisticsServiceImpl extends MPJBaseServiceImpl<Attendan
             //3.6、插入数据
             if (!insertList.isEmpty()) {
                 statisticsRecordService.saveBatch(insertList);
+                personCount = insertList.size();
             }
 
-            //4、将状态改为统计完成
-            statistics = this.getById(id);
-            statistics.setStatus(1);
-            statistics.setModifyDate(new Date());
-            statistics.setPersonCount(insertList.size());
-            statistics.setAttendanceDays(dateList.size());
-            this.updateById(statistics);
-
             return true;
         } catch (Exception e) {
             Log.error(e.getMessage(), e);
             if (e.getClass().equals(MyException.class)) {
                 throw new MyException(e.getMessage());
+            }else if(e.getClass().equals(ParseException.class) || e.getClass().equals(ClassCastException.class)){
+                remarks = "未能拉取海康数据,统计可能不准确";
             } else {
                 throw new MyException("刷新出错,请联系管理员");
             }
+        }finally {
+            //4、将状态改为统计完成
+            AttendanceStatistics statistics = this.getById(id);
+            statistics.setStatus(1);
+            statistics.setModifyDate(new Date());
+            statistics.setPersonCount(personCount);
+            statistics.setAttendanceDays(attendanceDays);
+            statistics.setRemarks(remarks);
+            this.updateById(statistics);
+            return true;
         }
     }
 

+ 5 - 0
src/main/java/com/xjrsoft/module/attendance/service/impl/TeacherAttendanceRecordServiceImpl.java

@@ -71,4 +71,9 @@ public class TeacherAttendanceRecordServiceImpl extends MPJBaseServiceImpl<Teach
         }
         return true;
     }
+
+    @Override
+    public Boolean deleteRecord(Integer timePeriod, String attendanceDate) {
+        return this.baseMapper.deleteRecord(timePeriod, attendanceDate);
+    }
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/vo/AttendanceRuleCategoryPageVo.java

@@ -93,4 +93,7 @@ public class AttendanceRuleCategoryPageVo {
     @ApiModelProperty("非考勤周期是否允许进出(1:是 0:否)")
     private Integer notCycleIsInOut;
 
+    @ApiModelProperty("是否默认显示(1:是 0:否)")
+    private Integer isDefaultShow;
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/vo/AttendanceRuleCategoryVo.java

@@ -76,4 +76,7 @@ public class AttendanceRuleCategoryVo {
     @ApiModelProperty("attendanceUserRelation子表")
     private List<AddAttendanceUserRelationDto> attendanceUserRelationList;
 
+    @ApiModelProperty("是否默认显示(1:是 0:否)")
+    private Integer isDefaultShow;
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/vo/AttendanceStatisticsPageVo.java

@@ -76,4 +76,7 @@ public class AttendanceStatisticsPageVo {
     @ApiModelProperty("应出勤天数")
     private Integer attendanceDays;
 
+    @ApiModelProperty("备注")
+    private String remarks;
+
 }

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/vo/TeacherStatisticsVo.java

@@ -40,4 +40,7 @@ public class TeacherStatisticsVo {
 
     @ApiModelProperty("旷课人数")
     private Integer playTruantCount;
+
+    @ApiModelProperty("不考勤人数")
+    private Integer notAttendanceCount;
 }

+ 94 - 0
src/main/java/com/xjrsoft/module/banding/entity/BandingTaskClassStudentSure.java

@@ -0,0 +1,94 @@
+package com.xjrsoft.module.banding.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * @title: 新生分班任务班级配置
+ * @Author dzx
+ * @Date: 2024-07-01
+ * @Version 1.0
+ */
+@Data
+@TableName("banding_task_class_student_sure")
+@ApiModel(value = "banding_task_class_student_sure", description = "新生分班任务班级学生关系确认表")
+public class BandingTaskClassStudentSure implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableId
+    private Long id;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUserId;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createDate;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long modifyUserId;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.UPDATE)
+    private Date modifyDate;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
+    private Integer deleteMark;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer enabledMark;
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    private Integer sortCode;
+    /**
+     * 规则名称
+     */
+    @ApiModelProperty("分班表的id")
+    private Long bandingTaskClassId;
+    /**
+     * 专业方向id
+     */
+    @ApiModelProperty("新生id")
+    private Long newStudentId;
+
+    @ApiModelProperty("状态(0:未确认 1:已确认)")
+    private Integer status;
+
+    @ApiModelProperty("就读方式")
+    private String stduyStatus;
+
+}

+ 4 - 0
src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassMapper.java

@@ -25,12 +25,16 @@ public interface BandingTaskClassMapper extends MPJBaseMapper<BandingTaskClass>
 
     List<BandingTaskClassStudentListVo> getClassStudent(@Param("dto") BandingTaskClassStudentPageDto dto);
 
+    List<BandingTaskClassStudentListVo> getClassStudentSure(@Param("dto") BandingTaskClassStudentPageDto dto);
+
     List<IdCountVo> getMajorClassCount(@Param("id") Long bandingTaskId);
 
     List<IdCountVo> getMajorClassStudentCount(@Param("id") Long bandingTaskId);
 
     List<BandingTaskClassSureListVo> getClassSure(@Param("dto") BandingTaskClassStudentPageDto dto);
 
+    List<BandingTaskClassSureListVo> getClassNotSure(@Param("dto") BandingTaskClassStudentPageDto dto);
+
 
     List<BandingTaskClass> getListOrderByAsc(@Param("id") Long bandingTaskId);
 

+ 7 - 0
src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassStudentMapper.java

@@ -3,6 +3,7 @@ package com.xjrsoft.module.banding.mapper;
 import com.github.yulichang.base.MPJBaseMapper;
 import com.xjrsoft.module.banding.dto.StudentDto;
 import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
+import com.xjrsoft.module.banding.vo.SyncStudentDataListVo;
 import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -20,5 +21,11 @@ public interface BandingTaskClassStudentMapper extends MPJBaseMapper<BandingTask
 
     List<BaseNewStudentPageDto> satisfyStudent(@Param("dto") StudentDto dto);
 
+    List<BaseNewStudentPageDto> satisfyStudentSure(@Param("dto") StudentDto dto);
+
     List<BaseNewStudentPageDto> surplusStudent(@Param("dto") StudentDto dto);
+
+    List<BaseNewStudentPageDto> surplusStudentSure(@Param("dto") StudentDto dto);
+
+    List<SyncStudentDataListVo> getSyncStudentDataList(@Param("studentReportPlanId") Long studentReportPlanId);
 }

+ 26 - 0
src/main/java/com/xjrsoft/module/banding/mapper/BandingTaskClassStudentSureMapper.java

@@ -0,0 +1,26 @@
+package com.xjrsoft.module.banding.mapper;
+
+import com.github.yulichang.base.MPJBaseMapper;
+import com.xjrsoft.module.banding.dto.StudentDto;
+import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
+import com.xjrsoft.module.banding.entity.BandingTaskClassStudentSure;
+import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+/**
+ * @title: 新生分班任务班级学生关系确认表
+ * @Author dzx
+ * @Date: 2025年5月28日
+ * @Version 1.0
+ */
+@Mapper
+public interface BandingTaskClassStudentSureMapper extends MPJBaseMapper<BandingTaskClassStudentSure> {
+
+    @Update("DELETE FROM banding_task_class_student_sure WHERE banding_task_class_id IN( " +
+            " SELECT id FROM banding_task_class WHERE banding_task_id = #{taskId} )")
+    Boolean deleteByTaskId(@Param("taskId") Long taskId);
+}

+ 5 - 0
src/main/java/com/xjrsoft/module/banding/service/IBandingTaskClassStudentService.java

@@ -5,6 +5,7 @@ import com.xjrsoft.module.banding.dto.ChangeClassDto;
 import com.xjrsoft.module.banding.dto.StudentDto;
 import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
 import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
+import com.xjrsoft.module.student.entity.StudentReportPlan;
 
 import java.util.List;
 
@@ -54,4 +55,8 @@ public interface IBandingTaskClassStudentService extends MPJBaseService<BandingT
 
 
     Boolean insertStudent(ChangeClassDto dto);
+
+    Boolean syncStudentData(StudentReportPlan studentReportPlan);
+
+    Boolean changeClassByWorkFlow(Long userId, Long classId);
 }

+ 34 - 6
src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskClassServiceImpl.java

@@ -32,10 +32,12 @@ import com.xjrsoft.module.banding.vo.BandingTaskClassReportStatisticsVo;
 import com.xjrsoft.module.banding.vo.BandingTaskClassStudentListVo;
 import com.xjrsoft.module.banding.vo.BandingTaskClassSureListVo;
 import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
 import com.xjrsoft.module.base.entity.BaseClassroom;
 import com.xjrsoft.module.base.entity.BaseGrade;
 import com.xjrsoft.module.base.entity.BaseMajorSet;
 import com.xjrsoft.module.base.mapper.BaseClassMapper;
+import com.xjrsoft.module.base.mapper.BaseClassTeacherChangeMapper;
 import com.xjrsoft.module.base.mapper.BaseGradeMapper;
 import com.xjrsoft.module.base.service.IBaseClassroomService;
 import com.xjrsoft.module.base.service.IBaseMajorSetService;
@@ -60,6 +62,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -93,7 +96,7 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
     private final BaseGradeMapper gradeMapper;
     private final IUserRoleRelationService roleRelationService;
     private final RedisUtil redisUtil;
-
+    private final BaseClassTeacherChangeMapper teacherChangeMapper;
 
     @Override
     public Boolean add(BandingTaskClass bandingTaskClass) {
@@ -154,12 +157,19 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
         BandingTask bandingTask = bandingTaskMapper.selectById(dto.getBandingTaskId());
         dto.setGradeId(bandingTask.getGradeId());
         dto.setEnrollType(bandingTask.getEnrollType());
+        if(bandingTask != null && bandingTask.getStatus() != null && bandingTask.getStatus() == 1){
+            return this.baseMapper.getClassStudentSure(dto);
+        }
         return this.baseMapper.getClassStudent(dto);
     }
 
     @Override
     public List<BandingTaskClassSureListVo> getClassSure(BandingTaskClassStudentPageDto dto) {
-        return this.baseMapper.getClassSure(dto);
+        BandingTask task = bandingTaskMapper.selectById(dto.getBandingTaskId());
+        if(task != null && task.getStatus() != null && task.getStatus() == 1){
+            return this.baseMapper.getClassSure(dto);
+        }
+        return this.baseMapper.getClassNotSure(dto);
     }
 
     @Override
@@ -315,6 +325,15 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
                     }
                     classMapper.updateById(baseClass);
 
+                    teacherChangeMapper.insert(new BaseClassTeacherChange(){{
+                        setClassId(baseClass.getId());
+                        setBeforeTeacherId(baseClass.getTeacherId());
+                        setAfterTeacherId(sourceObj.getTeacherId());
+                        setDeleteMark(DeleteMark.NODELETE.getCode());
+                        setEnabledMark(EnabledMark.ENABLED.getCode());
+                        setCreateDate(LocalDateTime.now());
+                    }});
+
                     //给该老师添加班主任角色
                     if (baseClass.getTeacherId() != null) {
                         long count = roleRelationService.count(
@@ -350,6 +369,14 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
                     classMapper.insert(baseClass);
                     sourceObj.setBaseClassId(baseClass.getId());
 
+                    teacherChangeMapper.insert(new BaseClassTeacherChange(){{
+                        setClassId(baseClass.getId());
+                        setAfterTeacherId(sourceObj.getTeacherId());
+                        setDeleteMark(DeleteMark.NODELETE.getCode());
+                        setEnabledMark(EnabledMark.ENABLED.getCode());
+                        setCreateDate(LocalDateTime.now());
+                    }});
+
                     if (baseClass.getTeacherId() != null) {
                         long count = roleRelationService.count(
                                 new QueryWrapper<UserRoleRelation>().lambda()
@@ -442,7 +469,6 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
                         .eq(BandingTask::getGradeId, baseClass.getGradeId())
                         .eq(BandingTask::getEnrollType, baseClass.getEnrollType())
                         .orderByDesc(BandingTask::getId)
-                        .eq(BandingTask::getStatus, 0)
         );
         if(bandingTasks.isEmpty()){
             return true;
@@ -465,6 +491,7 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
             one.setClassroomId(baseClass.getClassroomId());
             one.setDeleteMark(DeleteMark.NODELETE.getCode());
             one.setCreateDate(new Date());
+            one.setBaseClassId(baseClass.getId());
             one.setEnabledMark(EnabledMark.ENABLED.getCode());
             one.setName(baseClass.getName());
             one.setCreateUserId(StpUtil.getLoginIdAsLong());
@@ -610,9 +637,10 @@ public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskC
                 .filter(x -> x.getIsReport() == 0)
                 .collect(Collectors.toList());
         result.setNotArrivedCount(notArrivedList.size());
-
-        BigDecimal divide = BigDecimal.valueOf(result.getArrivedCount()).divide(BigDecimal.valueOf(result.getAllCount()), 4, RoundingMode.HALF_UP);
-        result.setReportRate(divide.doubleValue() + "");
+        if(result.getAllCount() != 0){
+            BigDecimal divide = BigDecimal.valueOf(result.getArrivedCount()).divide(BigDecimal.valueOf(result.getAllCount()), 4, RoundingMode.HALF_UP);
+            result.setReportRate(divide.doubleValue() + "");
+        }
 
         return result;
     }

+ 239 - 117
src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskClassStudentServiceImpl.java

@@ -1,31 +1,28 @@
 package com.xjrsoft.module.banding.service.impl;
 
-import cn.dev33.satoken.secure.BCrypt;
 import cn.dev33.satoken.stp.StpUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.yulichang.base.MPJBaseServiceImpl;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.constant.GlobalConstant;
-import com.xjrsoft.common.enums.ArchivesStatusEnum;
 import com.xjrsoft.common.enums.DeleteMark;
 import com.xjrsoft.common.enums.EnabledMark;
-import com.xjrsoft.common.enums.RoleEnum;
-import com.xjrsoft.common.utils.LocalDateUtil;
+import com.xjrsoft.common.exception.MyException;
 import com.xjrsoft.common.utils.RedisUtil;
 import com.xjrsoft.common.utils.VoToColumnUtil;
-import com.xjrsoft.config.CommonPropertiesConfig;
 import com.xjrsoft.module.banding.dto.ChangeClassDto;
 import com.xjrsoft.module.banding.dto.StudentDto;
+import com.xjrsoft.module.banding.entity.BandingTask;
 import com.xjrsoft.module.banding.entity.BandingTaskClass;
 import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
 import com.xjrsoft.module.banding.mapper.BandingTaskClassMapper;
 import com.xjrsoft.module.banding.mapper.BandingTaskClassStudentMapper;
 import com.xjrsoft.module.banding.mapper.BandingTaskMapper;
 import com.xjrsoft.module.banding.service.IBandingTaskClassStudentService;
+import com.xjrsoft.module.banding.vo.SyncStudentDataListVo;
 import com.xjrsoft.module.base.entity.BaseClass;
 import com.xjrsoft.module.base.entity.BaseSemester;
-import com.xjrsoft.module.base.mapper.BaseMajorSetMapper;
 import com.xjrsoft.module.base.service.IBaseClassService;
 import com.xjrsoft.module.base.service.IBaseSemesterService;
 import com.xjrsoft.module.organization.entity.User;
@@ -34,30 +31,23 @@ import com.xjrsoft.module.organization.service.IUserRoleRelationService;
 import com.xjrsoft.module.organization.service.IUserService;
 import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
 import com.xjrsoft.module.student.entity.BaseNewStudent;
-import com.xjrsoft.module.student.entity.BaseStudent;
-import com.xjrsoft.module.student.entity.BaseStudentFamily;
-import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
 import com.xjrsoft.module.student.entity.StudentReportPlan;
 import com.xjrsoft.module.student.entity.StudentReportRecord;
-import com.xjrsoft.module.student.mapper.BaseClassMajorSetMapper;
 import com.xjrsoft.module.student.mapper.StudentReportRecordMapper;
 import com.xjrsoft.module.student.service.IBaseNewStudentService;
-import com.xjrsoft.module.student.service.IBaseStudentFamilyService;
-import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService;
-import com.xjrsoft.module.student.service.IBaseStudentService;
 import com.xjrsoft.module.student.service.IStudentReportPlanService;
 import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
@@ -70,22 +60,17 @@ import java.util.stream.Collectors;
 @Service
 @AllArgsConstructor
 public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<BandingTaskClassStudentMapper, BandingTaskClassStudent> implements IBandingTaskClassStudentService {
+
+    private final BandingTaskMapper taskMapper;
     private final BandingTaskClassMapper taskClassMapper;
-    private final BandingTaskMapper bandingTaskMapper;
     private final IStudentReportPlanService reportPlanService;
     private final IBaseSemesterService semesterService;
     private final IBaseNewStudentService newStudentService;
     private final StudentReportRecordMapper reportRecordMapper;
 
     private final IBaseClassService classService;
-    private final BaseClassMajorSetMapper classMajorSetMapper;
-    private final CommonPropertiesConfig propertiesConfig;
     private final IUserService userService;
     private final IUserRoleRelationService roleRelationService;
-    private final IBaseStudentSchoolRollService schoolRollService;
-    private final IBaseStudentService studentService;
-    private final IBaseStudentFamilyService familyService;
-    private final BaseMajorSetMapper majorSetMapper;
     private final RedisUtil redisUtil;
 
     @Override
@@ -122,6 +107,11 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
                         .in(BaseNewStudent::getId, dto.getNewStudentIds())
         );
 
+        List<BaseNewStudent> notPaymnyList = list.stream().filter(x -> "未缴费".equals(x.getPaymnystate())).collect(Collectors.toList());
+        if(!notPaymnyList.isEmpty() && dto.getIsHandle() == 1){
+            throw new MyException("选择的学生中存在未交费情况,无法手动分班");
+        }
+
         List<BandingTaskClassStudent> dataList = new ArrayList<>();
         long createUserId = StpUtil.getLoginIdAsLong();
 
@@ -149,6 +139,9 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
             }
             //新增报到计划,如果有多个分班任务确认,需要保证试读报到计划只有一个
             BaseSemester semester = semesterService.getCurrentSemester();
+            if(semester == null){
+                throw new MyException("未能查询到当前学期,请检查学期时间设置");
+            }
             List<StudentReportPlan> planList = reportPlanService.list(
                     new QueryWrapper<StudentReportPlan>().lambda()
                             .eq(StudentReportPlan::getDeleteMark, DeleteMark.NODELETE.getCode())
@@ -159,6 +152,7 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
 
             for (StudentReportPlan plan : planList) {
                 for (Long newStudentId : dto.getNewStudentIds()) {
+                    reportRecordMapper.deleteRecordByUserIdAndPlanId(newStudentId, plan.getId());
                     StudentReportRecord record = new StudentReportRecord();
                     record.setCreateDate(new Date());
                     record.setCreateUserId(StpUtil.getLoginIdAsLong());
@@ -181,100 +175,100 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
             if(!updateList.isEmpty()){
                 newStudentService.updateBatchById(updateList);
             }
-            {
-                /**
-                 * 新增学生数据
-                 * 1、新增用户xjr_user,需要先查询用户信息是否已经存在
-                 * 2、新增用户与角色的关系xjr_user_role_relation
-                 * 3、新增学生基本信息base_student
-                 * 4、新增学籍信息表base_student_school_roll
-                 * 5、新增家庭信息表base_student_family
-                 */
-                LocalDateTime now = LocalDateTime.now();
-                List<String> idNumbers = updateList.stream().map(BaseNewStudent::getCredentialNumber).collect(Collectors.toList());
-                List<User> students = userService.list(
-                        new MPJLambdaWrapper<User>()
-                                .disableLogicDel()
-                                .in(User::getCredentialNumber, idNumbers)
-                                .orderByAsc(User::getCreateDate)
-                );
-                Map<String, Long> userSet = new HashMap<>();
-                Map<String, Integer> userDeleteMarkMap = new HashMap<>();
-                for (User student : students) {
-                    userSet.put(student.getCredentialNumber(), student.getId());
-                    userDeleteMarkMap.put(student.getCredentialNumber(), student.getDeleteMark());
-                }
-                for (BaseNewStudent student : updateList) {
-                    if(userSet.containsKey(student.getCredentialNumber())){
-                        schoolRollService.updateStudentClass(dto.getBandingTaskClassId(), userSet.get(student.getCredentialNumber()));
-                        Integer deleteMark = userDeleteMarkMap.get(student.getCredentialNumber());
-                        if(deleteMark != null && deleteMark == 1){
-                            userService.recoveryStudentInfo(userSet.get(student.getCredentialNumber()));
-                        }
-                        continue;
-                    }
-                    LocalDate birthDate = LocalDateUtil.getBirthDate(student.getCredentialNumber());
-                    User xjrUser = new User() {{
-                        setCreateDate(now);
-                        setPassword(BCrypt.hashpw(propertiesConfig.getDefaultPassword(), BCrypt.gensalt()));
-                        setName(student.getName());
-                        setUserName(student.getCredentialNumber());
-                        setCredentialNumber(student.getCredentialNumber());
-                        setCredentialType("ZZLS10007");
-                        setMobile(student.getMobile());
-                        setEnabledMark(EnabledMark.DISABLED.getCode());
-                        setGender(student.getGender());
-                        setIsChangePassword(1);
-                        setBirthDate(birthDate.atStartOfDay());
-                    }};
-                    userService.save(xjrUser);
-
-                    UserRoleRelation userRoleRelation = new UserRoleRelation() {{
-                        setRoleId(RoleEnum.STUDENT.getCode());
-                        setUserId(xjrUser.getId());
-                    }};
-                    roleRelationService.save(userRoleRelation);
-
-                    BaseStudent baseStudent = new BaseStudent() {{
-                        setUserId(xjrUser.getId());
-                        setCreateDate(now);
-                        setStudentId(student.getCredentialNumber());
-                        if(student.getHeight() != null){
-                            setHeight(student.getHeight().doubleValue());
-                        }
-                        if(student.getWeight() != null){
-                            setWeight(student.getWeight().doubleValue());
-                        }
-                    }};
-                    studentService.save(baseStudent);
-
-                    BaseStudentSchoolRoll schoolRoll = new BaseStudentSchoolRoll() {{
-                        setUserId(xjrUser.getId());
-                        if(student.getScore() != null){
-                            setGraduatedScore(student.getScore().doubleValue());
-                        }
-
-                        setGraduatedUniversity(student.getGraduateSchool());
-                        setClassId(dto.getBandingTaskClassId());
-                        setMajorSetId(aClass.getMajorSetId());
-                        setStduyStatus(student.getStduyStatus());
-                        setEnrollType(aClass.getEnrollType());
-                        setStudentSource(student.getSource());
-                        setGradeId(aClass.getGradeId());
-                        setArchivesStatus(ArchivesStatusEnum.FB2901.getCode());
-                        setCreateDate(now);
-                    }};
-                    schoolRollService.save(schoolRoll);
-
-                    BaseStudentFamily studentFamily = new BaseStudentFamily() {{
-                        setCreateDate(now);
-                        setUserId(xjrUser.getId());
-                        setTelephone(student.getFamilyMobile());
-                        setAddress(student.getFamilyAddress());
-                    }};
-                    familyService.save(studentFamily);
-                }
-            }
+//            {
+//                /**
+//                 * 新增学生数据
+//                 * 1、新增用户xjr_user,需要先查询用户信息是否已经存在
+//                 * 2、新增用户与角色的关系xjr_user_role_relation
+//                 * 3、新增学生基本信息base_student
+//                 * 4、新增学籍信息表base_student_school_roll
+//                 * 5、新增家庭信息表base_student_family
+//                 */
+//                LocalDateTime now = LocalDateTime.now();
+//                List<String> idNumbers = updateList.stream().map(BaseNewStudent::getCredentialNumber).collect(Collectors.toList());
+//                List<User> students = userService.list(
+//                        new MPJLambdaWrapper<User>()
+//                                .disableLogicDel()
+//                                .in(User::getCredentialNumber, idNumbers)
+//                                .orderByAsc(User::getCreateDate)
+//                );
+//                Map<String, Long> userSet = new HashMap<>();
+//                Map<String, Integer> userDeleteMarkMap = new HashMap<>();
+//                for (User student : students) {
+//                    userSet.put(student.getCredentialNumber(), student.getId());
+//                    userDeleteMarkMap.put(student.getCredentialNumber(), student.getDeleteMark());
+//                }
+//                for (BaseNewStudent student : updateList) {
+//                    if(userSet.containsKey(student.getCredentialNumber())){
+//                        schoolRollService.updateStudentClass(dto.getBandingTaskClassId(), userSet.get(student.getCredentialNumber()));
+//                        Integer deleteMark = userDeleteMarkMap.get(student.getCredentialNumber());
+//                        if(deleteMark != null && deleteMark == 1){
+//                            userService.recoveryStudentInfo(userSet.get(student.getCredentialNumber()));
+//                        }
+//                        continue;
+//                    }
+//                    LocalDate birthDate = LocalDateUtil.getBirthDate(student.getCredentialNumber());
+//                    User xjrUser = new User() {{
+//                        setCreateDate(now);
+//                        setPassword(BCrypt.hashpw(propertiesConfig.getDefaultPassword(), BCrypt.gensalt()));
+//                        setName(student.getName());
+//                        setUserName(student.getCredentialNumber());
+//                        setCredentialNumber(student.getCredentialNumber());
+//                        setCredentialType("ZZLS10007");
+//                        setMobile(student.getMobile());
+//                        setEnabledMark(EnabledMark.DISABLED.getCode());
+//                        setGender(student.getGender());
+//                        setIsChangePassword(1);
+//                        setBirthDate(birthDate.atStartOfDay());
+//                    }};
+//                    userService.save(xjrUser);
+//
+//                    UserRoleRelation userRoleRelation = new UserRoleRelation() {{
+//                        setRoleId(RoleEnum.STUDENT.getCode());
+//                        setUserId(xjrUser.getId());
+//                    }};
+//                    roleRelationService.save(userRoleRelation);
+//
+//                    BaseStudent baseStudent = new BaseStudent() {{
+//                        setUserId(xjrUser.getId());
+//                        setCreateDate(now);
+//                        setStudentId(student.getCredentialNumber());
+//                        if(student.getHeight() != null){
+//                            setHeight(student.getHeight().doubleValue());
+//                        }
+//                        if(student.getWeight() != null){
+//                            setWeight(student.getWeight().doubleValue());
+//                        }
+//                    }};
+//                    studentService.save(baseStudent);
+//
+//                    BaseStudentSchoolRoll schoolRoll = new BaseStudentSchoolRoll() {{
+//                        setUserId(xjrUser.getId());
+//                        if(student.getScore() != null){
+//                            setGraduatedScore(student.getScore().doubleValue());
+//                        }
+//
+//                        setGraduatedUniversity(student.getGraduateSchool());
+//                        setClassId(dto.getBandingTaskClassId());
+//                        setMajorSetId(aClass.getMajorSetId());
+//                        setStduyStatus(student.getStduyStatus());
+//                        setEnrollType(aClass.getEnrollType());
+//                        setStudentSource(student.getSource());
+//                        setGradeId(aClass.getGradeId());
+//                        setArchivesStatus(ArchivesStatusEnum.FB2901.getCode());
+//                        setCreateDate(now);
+//                    }};
+//                    schoolRollService.save(schoolRoll);
+//
+//                    BaseStudentFamily studentFamily = new BaseStudentFamily() {{
+//                        setCreateDate(now);
+//                        setUserId(xjrUser.getId());
+//                        setTelephone(student.getFamilyMobile());
+//                        setAddress(student.getFamilyAddress());
+//                    }};
+//                    familyService.save(studentFamily);
+//                }
+//            }
             CompletableFuture.runAsync(() -> {
                 List<User> userList = userService.list();
                 redisUtil.set(GlobalConstant.USER_CACHE_KEY, userList);
@@ -343,6 +337,12 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
     public List<BaseNewStudentPageDto> satisfyStudent(StudentDto dto) {
         BandingTaskClass taskClass = taskClassMapper.selectById(dto.getBandingTaskClassId());
         dto.setBandingTaskId(taskClass.getBandingTaskId());
+
+        BandingTask task = taskMapper.selectById(taskClass.getBandingTaskId());
+        if(task != null && task.getStatus() != null && task.getStatus() == 1){
+            return this.baseMapper.satisfyStudentSure(dto);
+        }
+
         return this.baseMapper.satisfyStudent(dto);
     }
 
@@ -351,6 +351,12 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
         BandingTaskClass taskClass = taskClassMapper.selectById(dto.getBandingTaskClassId());
         dto.setMajorSetId(taskClass.getMajorSetId());
         dto.setBandingTaskId(taskClass.getBandingTaskId());
+
+        BandingTask task = taskMapper.selectById(taskClass.getBandingTaskId());
+        if(task != null && task.getStatus() != null && task.getStatus() == 1){
+            return this.baseMapper.satisfyStudentSure(dto);
+        }
+
         return this.baseMapper.surplusStudent(dto);
     }
 
@@ -375,4 +381,120 @@ public class BandingTaskClassStudentServiceImpl extends MPJBaseServiceImpl<Bandi
         return true;
     }
 
+    /**
+     * 同步修改学生的班级信息
+     */
+    @Override
+    @Transactional
+    public Boolean syncStudentData(StudentReportPlan studentReportPlan) {
+        //先删除所有的
+        reportRecordMapper.deleteRecordByPlanId(studentReportPlan.getId());
+        
+        //拷贝试读报到的数据过来
+        StudentReportPlan tryReadingReportPlan = reportPlanService.getOne(
+                new QueryWrapper<StudentReportPlan>().lambda()
+                        .eq(StudentReportPlan::getCategory, 2)
+                        .eq(StudentReportPlan::getBandingTaskId, studentReportPlan.getBandingTaskId())
+        );
+
+        List<StudentReportRecord> records = reportRecordMapper.selectList(
+                new QueryWrapper<StudentReportRecord>().lambda()
+                        .eq(StudentReportRecord::getStudentReportPlanId, tryReadingReportPlan.getId())
+        );
+        Date createDate = new Date();
+        Set<Long> existInsertUserIds = new HashSet<>();
+        for (StudentReportRecord record : records) {
+            if(existInsertUserIds.contains(record.getUserId())){
+                continue;
+            }
+            record.setReportTime(null);
+            record.setModifyUserId(null);
+            record.setModifyDate(null);
+            record.setCreateDate(createDate);
+            record.setStudentReportPlanId(studentReportPlan.getId());
+            record.setId(null);
+            reportRecordMapper.insert(record);
+            existInsertUserIds.add(record.getUserId());
+        }
+
+        List<SyncStudentDataListVo> syncStudentDataList = this.baseMapper.getSyncStudentDataList(studentReportPlan.getId());
+        if(CollectionUtils.isNotEmpty(syncStudentDataList)){
+            List<Long> newStudentIds = syncStudentDataList.stream().map(SyncStudentDataListVo::getNewStudentId).collect(Collectors.toList());
+
+            //修改新生基本信息
+            Map<Long, String> stduyStatusMap = syncStudentDataList.stream().collect(Collectors.toMap(SyncStudentDataListVo::getNewStudentId, SyncStudentDataListVo::getStduyStatus));
+            List<BaseNewStudent> studentList = newStudentService.listByIds(newStudentIds);
+            for (BaseNewStudent student : studentList) {
+                student.setStduyStatus(stduyStatusMap.get(student.getId()));
+            }
+            newStudentService.updateBatchById(studentList);
+
+            //修改班级信息
+            Map<Long, Long> bandingTaskClassMap = syncStudentDataList.stream().filter(x -> x.getBandingTaskClassId() != null).collect(Collectors.toMap(SyncStudentDataListVo::getNewStudentId, SyncStudentDataListVo::getBandingTaskClassId));
+            List<BandingTaskClass> taskClassList = taskClassMapper.selectList(
+                    new QueryWrapper<BandingTaskClass>().lambda()
+                            .eq(BandingTaskClass::getBandingTaskId, studentReportPlan.getBandingTaskId())
+            );
+            Map<Long, Long> taskClassMap = taskClassList.stream().collect(Collectors.toMap(BandingTaskClass::getBaseClassId, BandingTaskClass::getId));
+
+            List<BandingTaskClassStudent> insertList = new ArrayList<>();
+            for (BaseNewStudent student : studentList) {
+                Long bandingTaskClassId = bandingTaskClassMap.get(student.getId());
+                if(bandingTaskClassId == null){
+                    continue;
+                }
+                insertList.add(new BandingTaskClassStudent(){{
+                    setBandingTaskClassId(taskClassMap.get(bandingTaskClassId));
+                    setNewStudentId(student.getId());
+                    setCreateDate(new Date());
+                    setStatus(1);
+                }});
+            }
+
+            if(!insertList.isEmpty()){
+                this.remove(
+                        new QueryWrapper<BandingTaskClassStudent>().lambda()
+                                .in(BandingTaskClassStudent::getNewStudentId, newStudentIds)
+                );
+                this.saveBatch(insertList);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional
+    public Boolean changeClassByWorkFlow(Long userId, Long classId) {
+        User user = userService.getById(userId);
+        if(user == null){
+            return false;
+        }
+        BaseNewStudent newStudent = newStudentService.getOne(
+                new QueryWrapper<BaseNewStudent>().lambda()
+                        .eq(BaseNewStudent::getDeleteMark, DeleteMark.NODELETE.getCode())
+                        .eq(BaseNewStudent::getCredentialNumber, user.getCredentialNumber())
+        );
+        BandingTaskClass taskClass = taskClassMapper.selectOne(
+                new QueryWrapper<BandingTaskClass>().lambda()
+                        .eq(BandingTaskClass::getDeleteMark, DeleteMark.NODELETE.getCode())
+                        .eq(BandingTaskClass::getBaseClassId, classId)
+        );
+        if(newStudent != null && taskClass != null){
+            this.remove(
+                    new QueryWrapper<BandingTaskClassStudent>().lambda()
+                            .eq(BandingTaskClassStudent::getNewStudentId, newStudent.getId())
+            );
+
+            this.save(new BandingTaskClassStudent(){{
+                setCreateDate(new Date());
+                setBandingTaskClassId(taskClass.getId());
+                setNewStudentId(newStudent.getId());
+                setStatus(1);
+                setDeleteMark(DeleteMark.NODELETE.getCode());
+                setEnabledMark(EnabledMark.ENABLED.getCode());
+            }});
+        }
+        return null;
+    }
+
 }

+ 49 - 6
src/main/java/com/xjrsoft/module/banding/service/impl/BandingTaskServiceImpl.java

@@ -2,6 +2,7 @@ package com.xjrsoft.module.banding.service.impl;
 
 import cn.dev33.satoken.secure.BCrypt;
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -26,10 +27,12 @@ import com.xjrsoft.module.banding.entity.BandingRule;
 import com.xjrsoft.module.banding.entity.BandingTask;
 import com.xjrsoft.module.banding.entity.BandingTaskClass;
 import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
+import com.xjrsoft.module.banding.entity.BandingTaskClassStudentSure;
 import com.xjrsoft.module.banding.entity.BandingTaskMajorCondition;
 import com.xjrsoft.module.banding.entity.BandingTaskRule;
 import com.xjrsoft.module.banding.mapper.BandingRuleMapper;
 import com.xjrsoft.module.banding.mapper.BandingTaskClassMapper;
+import com.xjrsoft.module.banding.mapper.BandingTaskClassStudentSureMapper;
 import com.xjrsoft.module.banding.mapper.BandingTaskMapper;
 import com.xjrsoft.module.banding.mapper.BandingTaskRuleMapper;
 import com.xjrsoft.module.banding.service.IBandingTaskClassStudentService;
@@ -98,6 +101,7 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
     private final BandingRuleMapper ruleMapper;
     private final BandingTaskRuleMapper taskRuleMapper;
     private final BandingTaskClassMapper taskClassMapper;
+    private final BandingTaskClassStudentSureMapper taskClassStudentSureMapper;
     private final IBaseNewStudentService newStudentService;
     private final IBandingTaskClassStudentService classStudentService;
     private final IBandingTaskMajorConditionService conditionService;
@@ -281,7 +285,7 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
 
         Map<Long, List<BaseNewStudent>> classStudentMap = new HashMap<>();
         if(ruleCodes.contains("BR0002")){
-            classStudentMap.putAll(divideStudentByScore(classConditionMap, baseNewStudents, classList));
+            classStudentMap.putAll(divideStudentByScore(classConditionMap, baseNewStudents, classList, ruleCodes));
         }
 
         //存班级和学生的关系
@@ -344,8 +348,12 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
                     continue;
                 }
                 //专业不匹配,直接跳过
-                if(!Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId()) && !Objects.equals(taskClass.getMajorSetId(), newStudent.getSecondAmbitionId())){
+                if(ruleCodes.contains("BR0006") && !Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId())){
                     continue;
+                }else{
+                    if(!Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId()) && !Objects.equals(taskClass.getMajorSetId(), newStudent.getSecondAmbitionId())){
+                        continue;
+                    }
                 }
                 //判断该班性别是否已满,如果设置了排序,即使性别满了班级人数没满继续分班
                 if(ruleCodes.contains("BR0001")){
@@ -419,9 +427,14 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
                     continue;
                 }
                 //专业不匹配,直接跳过
-                if(!Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId()) && !Objects.equals(taskClass.getMajorSetId(), newStudent.getSecondAmbitionId())){
+                if(ruleCodes.contains("BR0006") && !Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId())){
                     continue;
+                }else{
+                    if(!Objects.equals(taskClass.getMajorSetId(), newStudent.getFirstAmbitionId()) && !Objects.equals(taskClass.getMajorSetId(), newStudent.getSecondAmbitionId())){
+                        continue;
+                    }
                 }
+
                 //判断该班性别是否已满
                 List<Boolean> conditionList = new ArrayList<>();
                 BandingTaskMajorCondition condition = classConditionMap.get(taskClass.getMajorSetId());
@@ -477,7 +490,7 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
      * @return 班级id和学生
      */
     Map<Long, List<BaseNewStudent>> divideStudentByScore(Map<Long, BandingTaskMajorCondition> classConditionMap, List<BaseNewStudent> baseNewStudents,
-                                                         List<BandingTaskClass> classList){
+                                                         List<BandingTaskClass> classList, List<String> ruleCodes){
         Map<Long, List<BaseNewStudent>> classStudentMap = new HashMap<>();
         for (Long majorSetId : classConditionMap.keySet()) {
             //查询该专业下面有几个班级,把这部分学生按照成绩均匀分组
@@ -493,7 +506,15 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
             List<BaseNewStudent> stuList = new ArrayList<>();
 
             for (BaseNewStudent newStudent : baseNewStudents) {
-                if(!Objects.equals(majorSetId, newStudent.getFirstAmbitionId()) && !Objects.equals(majorSetId, newStudent.getSecondAmbitionId())){
+                //专业不匹配,直接跳过
+                if(
+                        !Objects.equals(majorSetId, newStudent.getFirstAmbitionId()) &&
+                                (
+                                        !ruleCodes.contains("BR0006") &&
+                                                !Objects.equals(majorSetId, newStudent.getSecondAmbitionId())
+                                )
+                )
+                {
                     continue;
                 }
 
@@ -651,7 +672,12 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
                 LocalDate birthDate = getBirthDate(student.getCredentialNumber());
                 User xjrUser = new User() {{
                     setCreateDate(now);
-                    setPassword(BCrypt.hashpw(propertiesConfig.getDefaultPassword(), BCrypt.gensalt()));
+//                    setPassword(BCrypt.hashpw(propertiesConfig.getDefaultPassword(), BCrypt.gensalt()));
+                    String credentialNumber = student.getCredentialNumber();
+                    String lastSixDigits = credentialNumber.length() <= 6
+                            ? credentialNumber
+                            : credentialNumber.substring(credentialNumber.length() - 6);
+                    setPassword(BCrypt.hashpw(lastSixDigits, BCrypt.gensalt()));
                     setName(student.getName());
                     setUserName(student.getCredentialNumber());
                     setCredentialNumber(student.getCredentialNumber());
@@ -838,6 +864,8 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
                 reportRecordMapper.insert(record);
             }
         }
+        //确认分班时,将已经分班的数据固化下来,后续查询也需要进行调整
+        lockData(bandingTask.getId(), classStudents, list);
 
         bandingTask.setStatus(1);
         bandingTask.setModifyDate(new Date());
@@ -868,4 +896,19 @@ public class BandingTaskServiceImpl extends MPJBaseServiceImpl<BandingTaskMapper
     void updateBaseNewStudentStatus(Long bandingTaskId, Integer operateMode, Long baseNewStudentId){
 
     };
+
+    /**
+     * 确认后,将分班数的数据情况固化
+     */
+    void lockData(Long taskId, List<BandingTaskClassStudent> classStudents, List<BaseNewStudent> newStudents){
+        taskClassStudentSureMapper.deleteByTaskId(taskId);
+
+        Map<Long, String> newStudentMaps = newStudents.stream().collect(Collectors.toMap(BaseNewStudent::getId, BaseNewStudent::getStduyStatus));
+
+        for (BandingTaskClassStudent bandingTaskClassStudent : classStudents) {
+            BandingTaskClassStudentSure studentSure = BeanUtil.toBean(bandingTaskClassStudent, BandingTaskClassStudentSure.class);
+            studentSure.setStduyStatus(newStudentMaps.get(bandingTaskClassStudent.getNewStudentId()));
+            taskClassStudentSureMapper.insert(studentSure);
+        }
+    }
 }

+ 12 - 0
src/main/java/com/xjrsoft/module/banding/vo/BandingTaskClassSureListVo.java

@@ -51,5 +51,17 @@ public class BandingTaskClassSureListVo {
     @ApiModelProperty("走读人数")
     private Integer notStayCount;
 
+    @ApiModelProperty("男生住校人数")
+    private Integer maleStayCount;
+
+    @ApiModelProperty("男生走读人数")
+    private Integer maleNotStayCount;
+
+    @ApiModelProperty("女生住校人数")
+    private Integer femaleStayCount;
+
+    @ApiModelProperty("女生走读人数")
+    private Integer femaleNotStayCount;
+
 
 }

+ 31 - 0
src/main/java/com/xjrsoft/module/banding/vo/SyncStudentDataListVo.java

@@ -0,0 +1,31 @@
+package com.xjrsoft.module.banding.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @title: 分班后的学生导出
+ * @Author dzx
+ * @Date: 2024-07-01
+ * @Version 1.0
+ */
+@Data
+public class SyncStudentDataListVo {
+
+    @ApiModelProperty("新生id")
+    private Long newStudentId;
+
+    @ApiModelProperty("班级id")
+    private String classId;
+
+    @ApiModelProperty("就读方式")
+    private String stduyStatus;
+
+    @ApiModelProperty("分班班级id")
+    private Long bandingTaskClassId;
+
+}

+ 27 - 0
src/main/java/com/xjrsoft/module/base/controller/BaseClassController.java

@@ -1,9 +1,13 @@
 package com.xjrsoft.module.base.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
 import com.xjrsoft.common.annotation.XjrLog;
+import com.xjrsoft.common.enums.DeleteMark;
+import com.xjrsoft.common.enums.EnabledMark;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
@@ -11,7 +15,9 @@ import com.xjrsoft.module.base.dto.AddBaseClassPageDto;
 import com.xjrsoft.module.base.dto.BaseClassPageDto;
 import com.xjrsoft.module.base.dto.UpdateBaseClassPageDto;
 import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
 import com.xjrsoft.module.base.service.IBaseClassService;
+import com.xjrsoft.module.base.service.IBaseClassTeacherChangeService;
 import com.xjrsoft.module.base.vo.BaseClassPageVo;
 import com.xjrsoft.module.base.vo.BaseClassVo;
 import io.swagger.annotations.Api;
@@ -27,6 +33,8 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -41,6 +49,7 @@ import java.util.List;
 @AllArgsConstructor
 public class BaseClassController {
     private final IBaseClassService baseClassService;
+    private final IBaseClassTeacherChangeService classTeacherChangeService;
 
     @GetMapping(value = "/page")
     @ApiOperation(value = "班级列表(分页)")
@@ -57,6 +66,24 @@ public class BaseClassController {
     @SaCheckPermission("baseclass:delete")
     @XjrLog(value = "删除", saveResponseData = true)
     public RT<Boolean> delete(@Valid @RequestBody List<Long> ids) {
+        List<BaseClass> classList = baseClassService.listByIds(ids);
+        List<BaseClassTeacherChange> classTeacherChangeList = new ArrayList<>();
+        for (BaseClass baseClass : classList) {
+            classTeacherChangeList.add(
+                    new BaseClassTeacherChange(){{
+                        setClassId(baseClass.getId());
+                        setBeforeTeacherId(baseClass.getTeacherId());
+                        setCreateDate(LocalDateTime.now());
+                        setCreateUserId(StpUtil.getLoginIdAsLong());
+                        setDeleteMark(DeleteMark.NODELETE.getCode());
+                        setEnabledMark(EnabledMark.ENABLED.getCode());
+                    }}
+            );
+            baseClass.setDeleteMark(DeleteMark.DELETED.getCode());
+        }
+        if(!classTeacherChangeList.isEmpty()){
+            classTeacherChangeService.saveBatch(classTeacherChangeList);
+        }
         return RT.ok(baseClassService.removeByIds(ids));
     }
 

+ 11 - 0
src/main/java/com/xjrsoft/module/base/controller/BaseClassCourseController.java

@@ -254,6 +254,7 @@ public class BaseClassCourseController {
         List<BaseClassCourse> baseClassCourses = new ArrayList<>();
         List<String> duplicateLogs = new ArrayList<>();
         List<String> errorLogs = new ArrayList<>();
+        // 班级数据
         List<BaseClass> classList = classService.list(new QueryWrapper<BaseClass>());
         Map<String, Long> classMap = new HashMap<>();
         for (BaseClass baseClass : classList) {
@@ -262,6 +263,7 @@ public class BaseClassCourseController {
         if (ObjectUtils.isEmpty(classMap)) {
             throw new MyException("系统中还没有维护班级数据");
         }
+        // 课程数据
         List<BaseCourseSubject> courseSubjectList = subjectService.list(new QueryWrapper<BaseCourseSubject>());
         Map<String, Long> courseSubjectMap = new HashMap<>();
         for (BaseCourseSubject baseCourseSubject : courseSubjectList) {
@@ -270,6 +272,7 @@ public class BaseClassCourseController {
         if (ObjectUtils.isEmpty(courseSubjectMap)) {
             throw new MyException("系统中还没有维护课程学科数据");
         }
+        // 教材数据
         List<Textbook> textbookList = textbookService.list(new QueryWrapper<Textbook>());
         Map<String, Long> textbookMap = new HashMap<>();
         for (Textbook textbook : textbookList) {
@@ -278,6 +281,7 @@ public class BaseClassCourseController {
         if (ObjectUtils.isEmpty(textbookMap)) {
             throw new MyException("系统中还没有维护教材数据");
         }
+        //学期数据
         List<BaseSemester> semesterList = semesterService.list(new QueryWrapper<BaseSemester>());
         Map<String, Long> semesterMap = new HashMap<>();
         for (BaseSemester baseSemester : semesterList) {
@@ -342,6 +346,7 @@ public class BaseClassCourseController {
                 baseClassAdminCourse.setClassId(classId);
                 baseClassAdminCourse.setBaseSemesterId(baseSemesterId);
                 baseClassAdminCourseMapper.insert(baseClassAdminCourse);
+                classAdminCourseId = baseClassAdminCourse.getId();
                 classSemester.put(newClassSemester, baseClassAdminCourse.getId());
             }
 
@@ -351,11 +356,17 @@ public class BaseClassCourseController {
             Long textbookId = null;
             if (ObjectUtils.isNotEmpty(vo.getCourseName())) {
                 courseId = courseSubjectMap.get(vo.getCourseName());
+                if (ObjectUtils.isEmpty(courseId)) {
+                    throw new MyException("第" + (i + 4) + "行数据的课程信息不存在于系统中");
+                }
                 baseClassCourse.setCourseId(courseId);
             }
 
             if (ObjectUtils.isNotEmpty(vo.getTextbookName())) {
                 textbookId = textbookMap.get(vo.getTextbookName());
+                if (ObjectUtils.isEmpty(textbookId)) {
+                    throw new MyException("第" + (i + 4) + "行数据的教材信息不存在于系统中");
+                }
                 baseClassCourse.setTextbookId(textbookId);
             }
 

+ 42 - 27
src/main/java/com/xjrsoft/module/base/controller/BaseClassDynamicsController.java

@@ -6,6 +6,7 @@ import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.annotation.XjrLog;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
@@ -13,16 +14,17 @@ import com.xjrsoft.common.page.PageOutput;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.dto.AddBaseClassDynamicsDto;
 import com.xjrsoft.module.base.dto.BaseClassDynamicsPageDto;
+import com.xjrsoft.module.base.dto.BaseClassDynamicsRelationPageDto;
 import com.xjrsoft.module.base.dto.UpdateBaseClassDynamicsDto;
 import com.xjrsoft.module.base.entity.BaseClassDynamics;
-import com.xjrsoft.module.base.entity.BaseUserStudent;
+import com.xjrsoft.module.base.entity.BaseClassDynamicsRelation;
 import com.xjrsoft.module.base.service.IBaseClassDynamicsService;
-import com.xjrsoft.module.base.service.IBaseUserStudentService;
 import com.xjrsoft.module.base.vo.BaseClassDynamicsPageVo;
+import com.xjrsoft.module.base.vo.BaseClassDynamicsRelationPageVo;
 import com.xjrsoft.module.base.vo.BaseClassDynamicsVo;
 import com.xjrsoft.module.organization.entity.User;
 import com.xjrsoft.module.organization.service.IUserService;
-import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService;
+import com.xjrsoft.module.student.entity.BaseStudent;
 import com.xjrsoft.module.system.entity.File;
 import com.xjrsoft.module.system.service.IFileService;
 import io.swagger.annotations.Api;
@@ -38,7 +40,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
-import java.util.ArrayList;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 
@@ -56,8 +58,6 @@ public class BaseClassDynamicsController {
 
 
     private final IBaseClassDynamicsService baseClassDynamicsService;
-    private final IBaseStudentSchoolRollService rollService;
-    private final IBaseUserStudentService userStudentService;
     private final IUserService userService;
     private final IFileService fileService;
 
@@ -66,34 +66,46 @@ public class BaseClassDynamicsController {
     @SaCheckPermission("baseclassdynamics:detail")
     @XjrLog(value = "班级动态表列表(分页)")
     public RT<PageOutput<BaseClassDynamicsPageVo>> page(@Valid BaseClassDynamicsPageDto dto) {
-        List<String> roleList = StpUtil.getRoleList();
         long userId = StpUtil.getLoginIdAsLong();
-        Integer roleType = null;
-        List<Long> classIds = new ArrayList<>();
-        if (roleList.contains("STUDENT")) {
-            roleType = 3;
-            classIds.add(rollService.getClassIdByUserId(userId));
-        }
-        if (roleList.contains("PARENT")) {
-            roleType = 4;
-            List<BaseUserStudent> list = userStudentService.list(new QueryWrapper<BaseUserStudent>().lambda().eq(BaseUserStudent::getUserId, userId));
-            for (BaseUserStudent userStudent : list) {
-                classIds.add(rollService.getClassIdByUserId(userStudent.getStudentId()));
-            }
-        }
+        MPJLambdaWrapper<BaseClassDynamics> queryWrapper = new MPJLambdaWrapper<>();
 
-        LambdaQueryWrapper<BaseClassDynamics> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper
-                .orderByDesc(BaseClassDynamics::getId)
+                .select(BaseClassDynamics::getId)
                 .select(BaseClassDynamics.class, x -> VoToColumnUtil.fieldsToColumns(BaseClassDynamicsPageVo.class).contains(x.getProperty()))
-                .like(roleType != null, BaseClassDynamics::getRoleType, roleType)
-                .in(!classIds.isEmpty(), BaseClassDynamics::getClassId, classIds)
+                .innerJoin(BaseClassDynamicsRelation.class, BaseClassDynamicsRelation::getBaseClassDynamicsId, BaseClassDynamics::getId)
+                .eq(BaseClassDynamicsRelation::getUserId, userId)
+                .orderByDesc(BaseClassDynamics::getId)
         ;
+        if(dto.getStartDate() != null && dto.getEndDate() != null){
+            queryWrapper.between(BaseClassDynamics::getCreateDate, dto.getStartDate().atStartOfDay(), dto.getEndDate().atTime(23,59,59));
+        }
+
         IPage<BaseClassDynamics> page = baseClassDynamicsService.page(ConventPage.getPage(dto), queryWrapper);
         PageOutput<BaseClassDynamicsPageVo> pageOutput = ConventPage.getPageOutput(page, BaseClassDynamicsPageVo.class);
         return RT.ok(pageOutput);
     }
 
+    @GetMapping(value = "/reader-page")
+    @ApiOperation(value = "班级动态读者信息(分页)")
+    @SaCheckPermission("baseclassdynamics:detail")
+    @XjrLog(value = "班级动态读者信息(分页)")
+    public RT<PageOutput<BaseClassDynamicsRelationPageVo>> page(@Valid BaseClassDynamicsRelationPageDto dto) {
+        MPJLambdaWrapper<User> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper
+                .select(User::getId)
+                .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
+                .select(BaseClassDynamicsRelation::getReadDate)
+                .select(BaseClassDynamicsRelation::getReadMark)
+                .innerJoin(BaseClassDynamicsRelation.class, BaseClassDynamicsRelation::getUserId, User::getId)
+                .innerJoin(BaseStudent.class, BaseStudent::getUserId, User::getId)
+                .eq(dto.getReadMark() != null, BaseClassDynamicsRelation::getReadMark, dto.getReadMark())
+                .eq(BaseClassDynamicsRelation::getBaseClassDynamicsId, dto.getBaseClassDynamicsId())
+        ;
+        IPage<BaseClassDynamicsRelationPageVo> page = userService.selectJoinListPage(ConventPage.getPage(dto), BaseClassDynamicsRelationPageVo.class, queryWrapper);
+        PageOutput<BaseClassDynamicsRelationPageVo> pageOutput = ConventPage.getPageOutput(page, BaseClassDynamicsRelationPageVo.class);
+        return RT.ok(pageOutput);
+    }
+
     @GetMapping(value = "/release-page")
     @ApiOperation(value = "班主任发布列表(分页)")
     @SaCheckPermission("baseclassdynamics:detail")
@@ -105,6 +117,9 @@ public class BaseClassDynamicsController {
                 .orderByDesc(BaseClassDynamics::getId)
                 .select(BaseClassDynamics.class, x -> VoToColumnUtil.fieldsToColumns(BaseClassDynamicsPageVo.class).contains(x.getProperty()))
                 .eq(BaseClassDynamics::getCreateUserId, userId);
+        if(dto.getStartDate() != null && dto.getEndDate() != null){
+            queryWrapper.between(BaseClassDynamics::getCreateDate, dto.getStartDate().atStartOfDay(), dto.getEndDate().atTime(23,59,59));
+        }
         IPage<BaseClassDynamics> page = baseClassDynamicsService.page(ConventPage.getPage(dto), queryWrapper);
         PageOutput<BaseClassDynamicsPageVo> pageOutput = ConventPage.getPageOutput(page, BaseClassDynamicsPageVo.class);
         return RT.ok(pageOutput);
@@ -131,6 +146,8 @@ public class BaseClassDynamicsController {
             }
         }
 
+        baseClassDynamicsService.read(id);
+
         return RT.ok(dynamicsVo);
     }
 
@@ -140,9 +157,7 @@ public class BaseClassDynamicsController {
     @SaCheckPermission("baseclassdynamics:add")
     @XjrLog(value = "新增班级动态表", saveResponseData = true)
     public RT<Boolean> add(@Valid @RequestBody AddBaseClassDynamicsDto dto) {
-        BaseClassDynamics baseClassDynamics = BeanUtil.toBean(dto, BaseClassDynamics.class);
-        baseClassDynamics.setCreateDate(new Date());
-        boolean isSuccess = baseClassDynamicsService.save(baseClassDynamics);
+        Boolean isSuccess = baseClassDynamicsService.add(dto);
         return RT.ok(isSuccess);
     }
 

+ 100 - 0
src/main/java/com/xjrsoft/module/base/controller/BaseClassTeacherChangeController.java

@@ -0,0 +1,100 @@
+package com.xjrsoft.module.base.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.xjrsoft.common.annotation.XjrLog;
+import com.xjrsoft.common.model.result.RT;
+import com.xjrsoft.common.page.ConventPage;
+import com.xjrsoft.common.page.PageOutput;
+import com.xjrsoft.module.base.dto.AddBaseClassTeacherChangeDto;
+import com.xjrsoft.module.base.dto.BaseClassTeacherChangePageDto;
+import com.xjrsoft.module.base.dto.UpdateBaseClassTeacherChangeDto;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
+import com.xjrsoft.module.base.service.IBaseClassTeacherChangeService;
+import com.xjrsoft.module.base.vo.BaseClassTeacherChangePageVo;
+import com.xjrsoft.module.base.vo.BaseClassTeacherChangeVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@RestController
+@RequestMapping("/base" + "/baseClassTeacherChange")
+@Api(value = "/base"  + "/baseClassTeacherChange",tags = "班主任异动记录表代码")
+@AllArgsConstructor
+public class BaseClassTeacherChangeController {
+
+
+    private final IBaseClassTeacherChangeService baseClassTeacherChangeService;
+
+    @GetMapping(value = "/page")
+    @ApiOperation(value="班主任异动记录表列表(分页)")
+    @SaCheckPermission("baseclassteacherchange:detail")
+    @XjrLog(value = "班主任异动记录表列表(分页)")
+    public RT<PageOutput<BaseClassTeacherChangePageVo>> page(@Valid BaseClassTeacherChangePageDto dto){
+
+        Page<BaseClassTeacherChangePageVo> page = baseClassTeacherChangeService.getPage(new Page<>(dto.getLimit(), dto.getSize()), dto);
+        PageOutput<BaseClassTeacherChangePageVo> pageOutput = ConventPage.getPageOutput(page, BaseClassTeacherChangePageVo.class);
+        return RT.ok(pageOutput);
+    }
+
+    @GetMapping(value = "/info")
+    @ApiOperation(value="根据id查询班主任异动记录表信息")
+    @SaCheckPermission("baseclassteacherchange:detail")
+    @XjrLog(value = "根据id查询班主任异动记录表信息")
+    public RT<BaseClassTeacherChangeVo> info(@RequestParam Long id){
+        BaseClassTeacherChange baseClassTeacherChange = baseClassTeacherChangeService.getById(id);
+        if (baseClassTeacherChange == null) {
+           return RT.error("找不到此数据!");
+        }
+        return RT.ok(BeanUtil.toBean(baseClassTeacherChange, BaseClassTeacherChangeVo.class));
+    }
+
+
+    @PostMapping
+    @ApiOperation(value = "新增班主任异动记录表")
+    @SaCheckPermission("baseclassteacherchange:add")
+    @XjrLog(value = "新增班主任异动记录表")
+    public RT<Boolean> add(@Valid @RequestBody AddBaseClassTeacherChangeDto dto){
+        BaseClassTeacherChange baseClassTeacherChange = BeanUtil.toBean(dto, BaseClassTeacherChange.class);
+        boolean isSuccess = baseClassTeacherChangeService.save(baseClassTeacherChange);
+    return RT.ok(isSuccess);
+    }
+
+    @PutMapping
+    @ApiOperation(value = "修改班主任异动记录表")
+    @SaCheckPermission("baseclassteacherchange:edit")
+    @XjrLog(value = "修改班主任异动记录表")
+    public RT<Boolean> update(@Valid @RequestBody UpdateBaseClassTeacherChangeDto dto){
+
+        BaseClassTeacherChange baseClassTeacherChange = BeanUtil.toBean(dto, BaseClassTeacherChange.class);
+        return RT.ok(baseClassTeacherChangeService.updateById(baseClassTeacherChange));
+
+    }
+
+    @DeleteMapping
+    @ApiOperation(value = "删除班主任异动记录表")
+    @SaCheckPermission("baseclassteacherchange:delete")
+    @XjrLog(value = "删除班主任异动记录表")
+    public RT<Boolean> delete(@Valid @RequestBody List<Long> ids){
+        return RT.ok(baseClassTeacherChangeService.removeBatchByIds(ids));
+    }
+
+}

+ 46 - 3
src/main/java/com/xjrsoft/module/base/controller/BaseCourseSubjectController.java

@@ -9,6 +9,7 @@ import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.annotation.XjrLog;
+import com.xjrsoft.common.enums.DeleteMark;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
@@ -17,9 +18,11 @@ import com.xjrsoft.module.base.dto.AddBaseCourseSubjectDto;
 import com.xjrsoft.module.base.dto.BaseCourseSubjectPageDto;
 import com.xjrsoft.module.base.dto.UpdateBaseCourseSubjectDto;
 import com.xjrsoft.module.base.entity.BaseCourseSubject;
+import com.xjrsoft.module.base.entity.CourseSubjectDetail;
 import com.xjrsoft.module.base.service.IBaseCourseSubjectService;
 import com.xjrsoft.module.base.vo.BaseCourseSubjectPageVo;
 import com.xjrsoft.module.base.vo.BaseCourseSubjectVo;
+import com.xjrsoft.module.system.entity.DictionaryDetail;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -64,12 +67,52 @@ public class BaseCourseSubjectController {
 
         MPJLambdaWrapper<BaseCourseSubject> queryWrapper = new MPJLambdaWrapper<>();
         queryWrapper
-                .orderByDesc(BaseCourseSubject::getId)
+                .disableSubLogicDel()
                 .select(BaseCourseSubject::getId)
                 .select(BaseCourseSubject.class, x -> VoToColumnUtil.fieldsToColumns(BaseCourseSubjectPageVo.class).contains(x.getProperty()))
+                .leftJoin(CourseSubjectDetail.class, CourseSubjectDetail::getBaseCourseSubjectId, BaseCourseSubject::getId)
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCourseCategory,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCourseCategoryCn)
+                        )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCourseNature,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCourseNatureCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCourseNature,
+                wrapper -> wrapper
+                        .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCourseNatureCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCourseAttribute,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCourseAttributeCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCourseType,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCourseTypeCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getSubjectQuality,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getSubjectQualityCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getCoreCourse,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getCoreCourseCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getOnlineCourse,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getOnlineCourseCn)
+                )
+                .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, CourseSubjectDetail::getIdeologyDemo,
+                        wrapper -> wrapper
+                                .selectAs(DictionaryDetail::getName, BaseCourseSubjectPageVo::getIdeologyDemoCn)
+                )
                 .like(StrUtil.isNotEmpty(dto.getName()), BaseCourseSubject::getName, dto.getName())
-                .like(StrUtil.isNotEmpty(dto.getCode()), BaseCourseSubject::getCode, dto.getCode());
-        IPage<BaseCourseSubject> page = baseCourseSubjectService.page(ConventPage.getPage(dto), queryWrapper);
+                .like(StrUtil.isNotEmpty(dto.getCode()), BaseCourseSubject::getCode, dto.getCode())
+                .eq(BaseCourseSubject::getDeleteMark, DeleteMark.NODELETE.getCode())
+                .orderByDesc(BaseCourseSubject::getId)
+        ;
+        IPage<BaseCourseSubjectPageVo> page = baseCourseSubjectService.selectJoinListPage(ConventPage.getPage(dto), BaseCourseSubjectPageVo.class, queryWrapper);
         PageOutput<BaseCourseSubjectPageVo> pageOutput = ConventPage.getPageOutput(page, BaseCourseSubjectPageVo.class);
         return RT.ok(pageOutput);
     }

+ 3 - 0
src/main/java/com/xjrsoft/module/base/dto/AddBaseClassPageDto.java

@@ -45,4 +45,7 @@ public class AddBaseClassPageDto implements Serializable {
 
     @ApiModelProperty("专业方向id(base_major_set)")
     private Long majorSetId;
+
+    @ApiModelProperty("实习次数")
+    private Integer internshipFrequency;
 }

+ 37 - 0
src/main/java/com/xjrsoft/module/base/dto/AddBaseClassTeacherChangeDto.java

@@ -0,0 +1,37 @@
+package com.xjrsoft.module.base.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Data
+public class AddBaseClassTeacherChangeDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+    * 班级id(base_class)
+    */
+    @ApiModelProperty("班级id(base_class)")
+    private Long classId;
+    /**
+    * 异动前班主任(xjr_user)
+    */
+    @ApiModelProperty("异动前班主任(xjr_user)")
+    private Long beforeTeacherId;
+    /**
+    * 异动后班主任(xjr_user)
+    */
+    @ApiModelProperty("异动后班主任(xjr_user)")
+    private Long afterTeacherId;
+
+}

+ 10 - 0
src/main/java/com/xjrsoft/module/base/dto/BaseClassDynamicsPageDto.java

@@ -1,8 +1,12 @@
 package com.xjrsoft.module.base.dto;
 
 import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
 
 
 /**
@@ -15,5 +19,11 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = false)
 public class BaseClassDynamicsPageDto extends PageInput {
 
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty("开始时间")
+    private LocalDate startDate;
 
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty("结束时间")
+    private LocalDate endDate;
 }

+ 27 - 0
src/main/java/com/xjrsoft/module/base/dto/BaseClassDynamicsRelationPageDto.java

@@ -0,0 +1,27 @@
+package com.xjrsoft.module.base.dto;
+
+import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+
+/**
+ * @title: 班级动态表分页查询入参
+ * @Author dzx
+ * @Date: 2024-09-04
+ * @Version 1.0
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class BaseClassDynamicsRelationPageDto extends PageInput {
+
+    @ApiModelProperty("是否已阅读(0:否 1:是)")
+    private Integer readMark;
+
+    @ApiModelProperty("动态id(base_class_dynamics)")
+    private Long baseClassDynamicsId;
+}

+ 46 - 0
src/main/java/com/xjrsoft/module/base/dto/BaseClassTeacherChangePageDto.java

@@ -0,0 +1,46 @@
+package com.xjrsoft.module.base.dto;
+
+import com.xjrsoft.common.page.PageInput;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+
+/**
+* @title: 班主任异动记录表分页查询入参
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class BaseClassTeacherChangePageDto extends PageInput {
+
+    @ApiModelProperty("班级名称")
+    private String className;
+
+    @ApiModelProperty("班级代码")
+    private String classCode;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty("异动时间-开始")
+    private LocalDate createDateStart;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty("异动时间-结束")
+    private LocalDate createDateEnd;
+
+    @ApiModelProperty("异动前班主任")
+    private String beforeTeacherName;
+
+    @ApiModelProperty("异动后班主任")
+    private String afterTeacherName;
+
+    @ApiModelProperty("年级")
+    private Long gradeId;
+
+
+}

+ 32 - 0
src/main/java/com/xjrsoft/module/base/dto/UpdateBaseClassTeacherChangeDto.java

@@ -0,0 +1,32 @@
+package com.xjrsoft.module.base.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.io.Serializable;
+
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.List;
+import java.util.Date;
+
+
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-27
+* @Version 1.0
+*/
+@Data
+public class UpdateBaseClassTeacherChangeDto extends AddBaseClassTeacherChangeDto {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+    * 
+    */
+    @ApiModelProperty("")
+    private Long id;
+}

+ 5 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseClass.java

@@ -1,5 +1,6 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,6 +40,7 @@ public class BaseClass implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
@@ -76,4 +78,7 @@ public class BaseClass implements Serializable {
 
     @ApiModelProperty("专业方向id(base_major_set)")
     private Long majorSetId;
+
+    @ApiModelProperty("实习次数")
+    private Integer internshipFrequency;
 }

+ 53 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseClassDynamicsRelation.java

@@ -0,0 +1,53 @@
+package com.xjrsoft.module.base.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+
+/**
+ * @title: 班级动态表阅读表
+ * @Author dzx
+ * @Date: 2025年4月27日
+ * @Version 1.0
+ */
+@Data
+@TableName("base_class_dynamics_relation")
+@ApiModel(value = "base_class_dynamics_relation", description = "班级动态表阅读表")
+public class BaseClassDynamicsRelation implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ApiModelProperty("")
+    @TableId
+    private Long id;
+
+    @ApiModelProperty("阅读时间")
+    private LocalDateTime readDate;
+
+    @ApiModelProperty("动态id(base_class_dynamics)")
+    private Long baseClassDynamicsId;
+
+    @ApiModelProperty("是否已阅读(0:否 1:是)")
+    private Integer readMark;
+
+
+    @ApiModelProperty("阅读用户")
+    private Long userId;
+
+    @ApiModelProperty("回复内容")
+    private String replyContent;
+
+}

+ 0 - 1
src/main/java/com/xjrsoft/module/base/entity/BaseClassMerge.java

@@ -12,7 +12,6 @@ import lombok.Data;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import java.util.Date;
 import java.util.List;
 
 

+ 93 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseClassTeacherChange.java

@@ -0,0 +1,93 @@
+package com.xjrsoft.module.base.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.github.yulichang.annotation.EntityMapping;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.io.Serializable;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Date;
+
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-27
+* @Version 1.0
+*/
+@Data
+@TableName("base_class_teacher_change")
+@ApiModel(value = "base_class_teacher_change", description = "班主任异动记录表")
+public class BaseClassTeacherChange implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+    * 
+    */
+    @ApiModelProperty("")
+    @TableId
+    private Long id;
+    /**
+    * 创建人
+    */
+    @ApiModelProperty("创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUserId;
+    /**
+    * 创建时间
+    */
+    @ApiModelProperty("创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createDate;
+    /**
+    * 修改人
+    */
+    @ApiModelProperty("修改人")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long modifyUserId;
+    /**
+    * 修改日期
+    */
+    @ApiModelProperty("修改日期")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime modifyDate;
+    /**
+    * 删除标记
+    */
+    @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
+    private Integer deleteMark;
+    /**
+    * 有效标记
+    */
+    @ApiModelProperty("有效标记")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer enabledMark;
+    /**
+    * 班级id(base_class)
+    */
+    @ApiModelProperty("班级id(base_class)")
+    private Long classId;
+    /**
+    * 异动前班主任(xjr_user)
+    */
+    @ApiModelProperty("异动前班主任(xjr_user)")
+    private Long beforeTeacherId;
+    /**
+    * 异动后班主任(xjr_user)
+    */
+    @ApiModelProperty("异动后班主任(xjr_user)")
+    private Long afterTeacherId;
+
+
+}

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseClassroom.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseClassroom implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("教室名称")

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseGrade.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseGrade implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("年级名称")

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseLabel.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseLabel implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("标签名称")

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseMajorSet.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseMajorSet implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("专业方向名称")

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseOfficeBuild.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseOfficeBuild implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("楼栋名称")

+ 6 - 0
src/main/java/com/xjrsoft/module/base/entity/BaseSemester.java

@@ -1,5 +1,8 @@
 package com.xjrsoft.module.base.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -39,9 +42,12 @@ public class BaseSemester implements Serializable {
     private Date modifyDate;
 
     @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
     private Integer deleteMark;
 
     @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
     private Integer enabledMark;
 
     @ApiModelProperty("学期名称")

+ 0 - 2
src/main/java/com/xjrsoft/module/base/entity/CourseSubjectDetail.java

@@ -164,6 +164,4 @@ public class CourseSubjectDetail implements Serializable {
      */
     @ApiModelProperty("主要开设实习项目名称")
     private String internshipName;
-
-
 }

+ 17 - 0
src/main/java/com/xjrsoft/module/base/mapper/BaseClassDynamicsRelationMapper.java

@@ -0,0 +1,17 @@
+package com.xjrsoft.module.base.mapper;
+
+import com.github.yulichang.base.MPJBaseMapper;
+import com.xjrsoft.module.base.entity.BaseClassDynamics;
+import com.xjrsoft.module.base.entity.BaseClassDynamicsRelation;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @title: 班级动态表
+ * @Author dzx
+ * @Date: 2024-09-04
+ * @Version 1.0
+ */
+@Mapper
+public interface BaseClassDynamicsRelationMapper extends MPJBaseMapper<BaseClassDynamicsRelation> {
+
+}

+ 21 - 0
src/main/java/com/xjrsoft/module/base/mapper/BaseClassTeacherChangeMapper.java

@@ -0,0 +1,21 @@
+package com.xjrsoft.module.base.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.base.MPJBaseMapper;
+import com.xjrsoft.module.base.dto.BaseClassTeacherChangePageDto;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
+import com.xjrsoft.module.base.vo.BaseClassTeacherChangePageVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Mapper
+public interface BaseClassTeacherChangeMapper extends MPJBaseMapper<BaseClassTeacherChange> {
+
+    Page<BaseClassTeacherChangePageVo> getPage(Page<BaseClassTeacherChangePageVo> page, @Param("dto") BaseClassTeacherChangePageDto dto);
+}

+ 5 - 0
src/main/java/com/xjrsoft/module/base/service/IBaseClassDynamicsService.java

@@ -1,6 +1,7 @@
 package com.xjrsoft.module.base.service;
 
 import com.github.yulichang.base.MPJBaseService;
+import com.xjrsoft.module.base.dto.AddBaseClassDynamicsDto;
 import com.xjrsoft.module.base.entity.BaseClassDynamics;
 
 /**
@@ -11,4 +12,8 @@ import com.xjrsoft.module.base.entity.BaseClassDynamics;
  */
 
 public interface IBaseClassDynamicsService extends MPJBaseService<BaseClassDynamics> {
+
+    Boolean add(AddBaseClassDynamicsDto dto);
+
+    Boolean read(Long baseClassDynamicsId);
 }

+ 20 - 0
src/main/java/com/xjrsoft/module/base/service/IBaseClassTeacherChangeService.java

@@ -0,0 +1,20 @@
+package com.xjrsoft.module.base.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.base.MPJBaseService;
+import com.xjrsoft.module.base.dto.BaseClassTeacherChangePageDto;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
+import com.xjrsoft.module.base.vo.BaseClassTeacherChangePageVo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+
+public interface IBaseClassTeacherChangeService extends MPJBaseService<BaseClassTeacherChange> {
+
+    Page<BaseClassTeacherChangePageVo> getPage(Page<BaseClassTeacherChangePageVo> page, @Param("dto") BaseClassTeacherChangePageDto dto);
+}

+ 9 - 1
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassCourseServiceImpl.java

@@ -41,7 +41,15 @@ import com.xjrsoft.module.textbook.mapper.TextbookStudentClaimMapper;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.BeanUtils;

+ 155 - 0
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassDynamicsServiceImpl.java

@@ -1,11 +1,43 @@
 package com.xjrsoft.module.base.service.impl;
 
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.yulichang.base.MPJBaseServiceImpl;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.utils.LocalDateTimeUtil;
+import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.config.CommonPropertiesConfig;
+import com.xjrsoft.module.base.dto.AddBaseClassDynamicsDto;
+import com.xjrsoft.module.base.entity.BaseClass;
 import com.xjrsoft.module.base.entity.BaseClassDynamics;
+import com.xjrsoft.module.base.entity.BaseClassDynamicsRelation;
 import com.xjrsoft.module.base.mapper.BaseClassDynamicsMapper;
+import com.xjrsoft.module.base.mapper.BaseClassDynamicsRelationMapper;
 import com.xjrsoft.module.base.service.IBaseClassDynamicsService;
+import com.xjrsoft.module.base.service.IBaseClassService;
+import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
+import com.xjrsoft.module.organization.entity.User;
+import com.xjrsoft.module.organization.entity.UserStudent;
+import com.xjrsoft.module.organization.service.IUserService;
+import com.xjrsoft.module.organization.service.IWeChatService;
+import com.xjrsoft.module.student.dto.BaseStudentUserPageDto;
+import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
+import com.xjrsoft.module.student.service.IBaseStudentService;
+import com.xjrsoft.module.student.vo.BaseStudentUserPageVo;
+import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
 import lombok.AllArgsConstructor;
+import me.zhyd.oauth.log.Log;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @title: 班级动态表
@@ -16,4 +48,127 @@ import org.springframework.stereotype.Service;
 @Service
 @AllArgsConstructor
 public class BaseClassDynamicsServiceImpl extends MPJBaseServiceImpl<BaseClassDynamicsMapper, BaseClassDynamics> implements IBaseClassDynamicsService {
+
+    private final IBaseStudentService studentService;
+    private final IUserService userService;
+    private final BaseClassDynamicsRelationMapper dynamicsRelationMapper;
+    private final CommonPropertiesConfig commonPropertiesConfig;
+    private final IWeChatService weChatService;
+    private final IBaseClassService classService;
+    @Override
+    @Transactional
+    public Boolean add(AddBaseClassDynamicsDto dto) {
+        LocalDateTime now = LocalDateTime.now();
+        BaseClassDynamics baseClassDynamics = BeanUtil.toBean(dto, BaseClassDynamics.class);
+        baseClassDynamics.setCreateDate(new Date());
+        this.save(baseClassDynamics);
+
+        BaseClass aClass = classService.getById(dto.getClassId());
+
+        List<Long> classIds = new ArrayList<>();
+        classIds.add(dto.getClassId());
+        if(baseClassDynamics.getRoleType().contains("3")){
+            List<BaseStudentUserPageVo> studentList = studentService.getStudentList(new BaseStudentUserPageDto() {{
+                setClassIds(classIds);
+            }});
+            for (BaseStudentUserPageVo studentUserPageVo : studentList) {
+                BaseClassDynamicsRelation dynamicsRelation = new BaseClassDynamicsRelation() {{
+                    setBaseClassDynamicsId(baseClassDynamics.getId());
+                    setUserId(Long.parseLong(studentUserPageVo.getId()));
+                    setReadMark(0);
+                }};
+                dynamicsRelationMapper.insert(dynamicsRelation);
+
+                try {
+                    WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
+                    weChatSendMessageDto.setUserId(studentUserPageVo.getOpenId());
+                    weChatSendMessageDto.setTemplateId("qmpXORPM1Cocqn503Qa4On6BJhR92UZ00eod2-6IcGo");
+                    weChatSendMessageDto.setUrl(StrUtil.format("{}pages/student/trends/detail?id={}", commonPropertiesConfig.getDomainApp(), baseClassDynamics.getId()));
+                    weChatSendMessageDto.setMsgId(dynamicsRelation.getId().toString());
+                    JSONObject data = new JSONObject();
+
+                    JSONObject data1 = new JSONObject();
+                    data1.put("value", baseClassDynamics.getTitle());
+                    data.put("thing23", data1);
+
+                    JSONObject data2 = new JSONObject();
+                    data2.put("value", (aClass.getName() == null) ? "重庆铜梁职业教育中心" : aClass.getName());
+                    data.put("thing29", data2);
+
+                    JSONObject data3 = new JSONObject();
+                    data3.put("value", LocalDateTimeUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
+                    data.put("time17", data3);
+                    weChatSendMessageDto.setContent(data);
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
+                }catch (Exception e){
+                    Log.error(e.getMessage());
+                }
+            }
+        }
+
+        if(baseClassDynamics.getRoleType().contains("4")){
+            List<User> list = userService.list(
+                    new MPJLambdaWrapper<User>()
+                            .select(User::getId)
+                            .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
+                            .innerJoin(UserStudent.class, UserStudent::getUserId, User::getId)
+                            .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, UserStudent::getStudentId)
+                            .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, UserStudent::getId)
+                            .eq(BaseStudentSchoolRoll::getClassId, dto.getClassId())
+                            .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED)
+                            .isNotNull(User::getOpenId)
+            );
+
+            for (User user : list) {
+                BaseClassDynamicsRelation dynamicsRelation = new BaseClassDynamicsRelation() {{
+                    setBaseClassDynamicsId(baseClassDynamics.getId());
+                    setUserId(user.getId());
+                    setReadMark(0);
+                }};
+                dynamicsRelationMapper.insert(dynamicsRelation);
+
+                try {
+                    WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
+                    weChatSendMessageDto.setUserId(user.getOpenId());
+                    weChatSendMessageDto.setTemplateId("qmpXORPM1Cocqn503Qa4On6BJhR92UZ00eod2-6IcGo");
+                    weChatSendMessageDto.setUrl(StrUtil.format("{}pages/student/trends/detail?id={}", commonPropertiesConfig.getDomainApp(), baseClassDynamics.getId()));
+                    weChatSendMessageDto.setMsgId(dynamicsRelation.getId().toString());
+                    JSONObject data = new JSONObject();
+
+                    JSONObject data1 = new JSONObject();
+                    data1.put("value", baseClassDynamics.getTitle());
+                    data.put("thing23", data1);
+
+                    JSONObject data2 = new JSONObject();
+                    data2.put("value", (aClass.getName() == null) ? "重庆铜梁职业教育中心" : aClass.getName());
+                    data.put("thing29", data2);
+
+                    JSONObject data3 = new JSONObject();
+                    data3.put("value", LocalDateTimeUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
+                    data.put("time17", data3);
+                    weChatSendMessageDto.setContent(data);
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
+                }catch (Exception e){
+                    Log.error(e.getMessage());
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional
+    public Boolean read(Long baseClassDynamicsId) {
+        List<BaseClassDynamicsRelation> list = dynamicsRelationMapper.selectList(
+                new QueryWrapper<BaseClassDynamicsRelation>().lambda()
+                        .eq(BaseClassDynamicsRelation::getBaseClassDynamicsId, baseClassDynamicsId)
+                        .eq(BaseClassDynamicsRelation::getUserId, StpUtil.getLoginIdAsLong())
+        );
+        for (BaseClassDynamicsRelation dynamicsRelation : list) {
+            dynamicsRelation.setReadMark(1);
+            dynamicsRelation.setReadDate(LocalDateTime.now());
+            dynamicsRelationMapper.updateById(dynamicsRelation);
+        }
+        return true;
+    }
 }

+ 52 - 2
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassMergeServiceImpl.java

@@ -1,30 +1,39 @@
 package com.xjrsoft.module.base.service.impl;
 
 import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.yulichang.base.MPJBaseServiceImpl;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.enums.ArchivesStatusEnum;
 import com.xjrsoft.common.enums.DeleteMark;
+import com.xjrsoft.common.enums.EnabledMark;
 import com.xjrsoft.common.enums.StudentChangeTypeEnum;
 import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.mybatis.SqlRunnerAdapter;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.dto.BaseClassMergeStudentPageDto;
 import com.xjrsoft.module.base.entity.BaseClass;
 import com.xjrsoft.module.base.entity.BaseClassMerge;
 import com.xjrsoft.module.base.entity.BaseClassMergeStudent;
+import com.xjrsoft.module.base.entity.BaseSystemConfig;
 import com.xjrsoft.module.base.mapper.BaseClassMapper;
 import com.xjrsoft.module.base.mapper.BaseClassMergeMapper;
 import com.xjrsoft.module.base.mapper.BaseClassMergeStudentMapper;
 import com.xjrsoft.module.base.service.IBaseClassMergeService;
+import com.xjrsoft.module.base.service.IBaseSystemConfigService;
 import com.xjrsoft.module.base.vo.BaseClassMergeStudentVo;
 import com.xjrsoft.module.organization.entity.User;
-import com.xjrsoft.module.student.entity.StudentChangeRecord;
+import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
+import com.xjrsoft.module.student.entity.StudentChangeClass;
 import com.xjrsoft.module.student.mapper.BaseStudentSchoolRollMapper;
+import com.xjrsoft.module.student.mapper.StudentChangeClassMapper;
 import com.xjrsoft.module.student.service.IStudentChangeRecordService;
-import com.xjrsoft.module.system.entity.DictionaryDetail;
+import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
 import lombok.AllArgsConstructor;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -49,6 +58,8 @@ public class BaseClassMergeServiceImpl extends MPJBaseServiceImpl<BaseClassMerge
     private final BaseClassMapper baseClassMapper;
     private final BaseStudentSchoolRollMapper schoolRollMapper;
     private final IStudentChangeRecordService changeRecordService;
+    private final IBaseSystemConfigService systemConfigService;
+    private final StudentChangeClassMapper studentChangeClassMapper;
 
 
     @Override
@@ -58,6 +69,45 @@ public class BaseClassMergeServiceImpl extends MPJBaseServiceImpl<BaseClassMerge
         if(collect.contains(baseClassMerge.getTargetClassId())){
             throw new MyException("原有班级中不能包含目标班级,请重新选择原有班级");
         }
+
+        BaseSystemConfig classNumberMax = systemConfigService.getOne(
+                new QueryWrapper<BaseSystemConfig>().lambda()
+                        .eq(BaseSystemConfig::getCode, "classNumberMax")
+        );
+        if(classNumberMax != null){
+            int classNumberMaxNum = Integer.parseInt(classNumberMax.getValue());
+            Integer actualStudentCount = schoolRollMapper.selectJoinCount(
+                    new MPJLambdaWrapper<BaseStudentSchoolRoll>()
+                            .distinct()
+                            .select(BaseStudentSchoolRoll::getUserId)
+                            .innerJoin(User.class, User::getId, BaseStudentSchoolRoll::getUserId)
+                            .eq(BaseStudentSchoolRoll::getDeleteMark, DeleteMark.NODELETE.getCode())
+                            .eq(BaseStudentSchoolRoll::getEnabledMark, EnabledMark.ENABLED.getCode())
+                            .eq(BaseStudentSchoolRoll::getArchivesStatus, ArchivesStatusEnum.FB2901.getCode())
+                            .eq(BaseStudentSchoolRoll::getClassId, baseClassMerge.getTargetClassId())
+            );
+
+            Integer count = studentChangeClassMapper.selectJoinCount(
+                    new MPJLambdaWrapper<StudentChangeClass>()
+                            .distinct()
+                            .select(StudentChangeClass::getStudentUserId)
+                            .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, StudentChangeClass::getId)
+                            .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
+            );
+
+            String sql = "SELECT DISTINCT student_user_id FROM temporary_change_class t1" +
+                    " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = CAST(t2.form_key_value AS SIGNED)" +
+                    " WHERE t1.delete_mark = 0 AND t2.current_state = 'ACTIVE'";
+            List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
+
+            int classCount = actualStudentCount + count + list.size();
+            int difference  = classCount - classNumberMaxNum;
+            int absoluteValue = (difference < 0) ? -difference : difference;
+            if(baseClassMerge.getBaseClassMergeStudentList().size() > absoluteValue){
+                throw new MyException("转入班级的人数大于班级剩余空位,该班级剩余" + absoluteValue + "人");
+            }
+        }
+
         baseClassMerge.setStudentCount(baseClassMerge.getBaseClassMergeStudentList().size());
         this.baseMapper.insert(baseClassMerge);
         BaseClass baseClass = baseClassMapper.selectById(baseClassMerge.getTargetClassId());

+ 31 - 0
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassServiceImpl.java

@@ -20,8 +20,10 @@ import com.xjrsoft.module.base.dto.AddBaseClassPageDto;
 import com.xjrsoft.module.base.dto.BaseClassPageDto;
 import com.xjrsoft.module.base.dto.UpdateBaseClassPageDto;
 import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
 import com.xjrsoft.module.base.entity.BaseGrade;
 import com.xjrsoft.module.base.mapper.BaseClassMapper;
+import com.xjrsoft.module.base.mapper.BaseClassTeacherChangeMapper;
 import com.xjrsoft.module.base.mapper.BaseGradeMapper;
 import com.xjrsoft.module.base.service.IBaseClassService;
 import com.xjrsoft.module.base.vo.BaseClassPageVo;
@@ -40,6 +42,7 @@ import com.xjrsoft.module.teacher.entity.XjrUser;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
@@ -63,6 +66,8 @@ public class BaseClassServiceImpl extends MPJBaseServiceImpl<BaseClassMapper, Ba
 
     private final BaseGradeMapper gradeMapper;
 
+    private final BaseClassTeacherChangeMapper teacherChangeMapper;
+
     /**
      * 获取家长关联的学生 id 是家长的ID
      *
@@ -211,6 +216,14 @@ public class BaseClassServiceImpl extends MPJBaseServiceImpl<BaseClassMapper, Ba
                     });
                 }
             }
+
+            teacherChangeMapper.insert(new BaseClassTeacherChange(){{
+                setClassId(baseClass.getId());
+                setAfterTeacherId(baseClass.getTeacherId());
+                setDeleteMark(DeleteMark.NODELETE.getCode());
+                setEnabledMark(EnabledMark.ENABLED.getCode());
+                setCreateDate(LocalDateTime.now());
+            }});
         }
         return isSuccess;
     }
@@ -231,6 +244,16 @@ public class BaseClassServiceImpl extends MPJBaseServiceImpl<BaseClassMapper, Ba
             if (count > 0) {
                 throw new MyException("该老师已是其他在读班级班主任,无法修改");
             }
+
+            //增加异动记录
+            teacherChangeMapper.insert(new BaseClassTeacherChange(){{
+                setClassId(aClass.getId());
+                setBeforeTeacherId(aClass.getTeacherId());
+                setAfterTeacherId(dto.getTeacherId());
+                setDeleteMark(DeleteMark.NODELETE.getCode());
+                setEnabledMark(EnabledMark.ENABLED.getCode());
+                setCreateDate(LocalDateTime.now());
+            }});
         }
         if(!aClass.getCode().equals(dto.getCode())){
             List<BaseClass> list = this.list(
@@ -298,6 +321,14 @@ public class BaseClassServiceImpl extends MPJBaseServiceImpl<BaseClassMapper, Ba
                                     .eq(UserRoleRelation::getRoleId, RoleEnum.CLASSTE.getCode())
                     );
                 }
+
+                teacherChangeMapper.insert(new BaseClassTeacherChange(){{
+                    setClassId(aClass.getId());
+                    setAfterTeacherId(aClass.getTeacherId());
+                    setDeleteMark(DeleteMark.NODELETE.getCode());
+                    setEnabledMark(EnabledMark.ENABLED.getCode());
+                    setCreateDate(LocalDateTime.now());
+                }});
             }
             CompletableFuture.runAsync(() -> {
                 List<UserRoleRelation> userRoleRelationList = roleRelationService.list(Wrappers.lambdaQuery(UserRoleRelation.class));

+ 26 - 0
src/main/java/com/xjrsoft/module/base/service/impl/BaseClassTeacherChangeServiceImpl.java

@@ -0,0 +1,26 @@
+package com.xjrsoft.module.base.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.base.MPJBaseServiceImpl;
+import com.xjrsoft.module.base.dto.BaseClassTeacherChangePageDto;
+import com.xjrsoft.module.base.entity.BaseClassTeacherChange;
+import com.xjrsoft.module.base.mapper.BaseClassTeacherChangeMapper;
+import com.xjrsoft.module.base.service.IBaseClassTeacherChangeService;
+import com.xjrsoft.module.base.vo.BaseClassTeacherChangePageVo;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+* @title: 班主任异动记录表
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Service
+@AllArgsConstructor
+public class BaseClassTeacherChangeServiceImpl extends MPJBaseServiceImpl<BaseClassTeacherChangeMapper, BaseClassTeacherChange> implements IBaseClassTeacherChangeService {
+    @Override
+    public Page<BaseClassTeacherChangePageVo> getPage(Page<BaseClassTeacherChangePageVo> page, BaseClassTeacherChangePageDto dto) {
+        return this.baseMapper.getPage(page, dto);
+    }
+}

+ 8 - 1
src/main/java/com/xjrsoft/module/base/service/impl/BaseCourseSubjectServiceImpl.java

@@ -1,5 +1,6 @@
 package com.xjrsoft.module.base.service.impl;
 
+import cn.dev33.satoken.stp.StpUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.yulichang.base.MPJBaseServiceImpl;
 import com.xjrsoft.module.base.entity.BaseCourseSubject;
@@ -11,6 +12,7 @@ import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -35,6 +37,8 @@ public class BaseCourseSubjectServiceImpl extends MPJBaseServiceImpl<BaseCourseS
         baseCourseSubjectBaseCourseSubjectMapper.insert(baseCourseSubject);
         for (CourseSubjectDetail courseSubjectDetail : baseCourseSubject.getCourseSubjectDetailList()) {
             courseSubjectDetail.setBaseCourseSubjectId(baseCourseSubject.getId());
+            courseSubjectDetail.setCreateDate(new Date());
+            courseSubjectDetail.setCreateUserId(StpUtil.getLoginIdAsLong());
             baseCourseSubjectCourseSubjectDetailMapper.insert(courseSubjectDetail);
         }
 
@@ -58,12 +62,15 @@ public class BaseCourseSubjectServiceImpl extends MPJBaseServiceImpl<BaseCourseS
             for (CourseSubjectDetail courseSubjectDetail : baseCourseSubject.getCourseSubjectDetailList()) {
                 //如果不等于空则修改
                 if (courseSubjectDetail.getId() != null) {
+                    courseSubjectDetail.setCreateDate(new Date());
+                    courseSubjectDetail.setCreateUserId(StpUtil.getLoginIdAsLong());
                     baseCourseSubjectCourseSubjectDetailMapper.updateById(courseSubjectDetail);
                 }
                 //如果等于空 则新增
                 else {
-                    //已经不存在的id 删除
                     courseSubjectDetail.setBaseCourseSubjectId(baseCourseSubject.getId());
+                    courseSubjectDetail.setCreateDate(new Date());
+                    courseSubjectDetail.setCreateUserId(StpUtil.getLoginIdAsLong());
                     baseCourseSubjectCourseSubjectDetailMapper.insert(courseSubjectDetail);
                 }
             }

+ 2 - 2
src/main/java/com/xjrsoft/module/base/service/impl/BaseSemesterServiceImpl.java

@@ -8,7 +8,7 @@ import com.xjrsoft.module.base.mapper.BaseSemesterMapper;
 import com.xjrsoft.module.base.service.IBaseSemesterService;
 import org.springframework.stereotype.Service;
 
-import java.time.LocalDateTime;
+import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -24,7 +24,7 @@ public class BaseSemesterServiceImpl extends ServiceImpl<BaseSemesterMapper, Bas
 
     @Override
     public BaseSemester getCurrentSemester() {
-        LocalDateTime now = LocalDateTime.now();
+        LocalDate now = LocalDate.now();
         List<BaseSemester> semesterList = this.list(
                 new QueryWrapper<BaseSemester>().lambda()
                         .eq(BaseSemester::getDeleteMark, DeleteMark.NODELETE.getCode())

+ 27 - 0
src/main/java/com/xjrsoft/module/base/vo/BaseClassDynamicsRelationPageVo.java

@@ -0,0 +1,27 @@
+package com.xjrsoft.module.base.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * @title: 班级动态表分页列表出参
+ * @Author dzx
+ * @Date: 2024-09-04
+ * @Version 1.0
+ */
+@Data
+public class BaseClassDynamicsRelationPageVo {
+
+    @ApiModelProperty("姓名")
+    private String name;
+
+    @ApiModelProperty("阅读时间")
+    private LocalDateTime readDate;
+
+    @ApiModelProperty("是否已阅读(0:否 1:是)")
+    private Integer readMark;
+
+}

+ 3 - 0
src/main/java/com/xjrsoft/module/base/vo/BaseClassPageVo.java

@@ -73,4 +73,7 @@ public class BaseClassPageVo {
 
     @ApiModelProperty("手机号")
     private String teacherMobile;
+
+    @ApiModelProperty("实习次数")
+    private Integer internshipFrequency;
 }

+ 42 - 0
src/main/java/com/xjrsoft/module/base/vo/BaseClassTeacherChangePageVo.java

@@ -0,0 +1,42 @@
+package com.xjrsoft.module.base.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+* @title: 班主任异动记录表分页列表出参
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Data
+public class BaseClassTeacherChangePageVo {
+
+
+    @ApiModelProperty("主键编号")
+    private String id;
+
+    @ApiModelProperty("年级名称")
+    private String gradeName;
+
+    @ApiModelProperty("班级名称")
+    private String className;
+
+    @ApiModelProperty("班级代码")
+    private String classCode;
+
+    @ApiModelProperty("异动时间")
+    private LocalDateTime createDate;
+
+    @ApiModelProperty("操作人")
+    private String createUserName;
+
+    @ApiModelProperty("异动前班主任")
+    private String beforeTeacherName;
+
+    @ApiModelProperty("异动后班主任")
+    private String afterTeacherName;
+
+}

+ 38 - 0
src/main/java/com/xjrsoft/module/base/vo/BaseClassTeacherChangeVo.java

@@ -0,0 +1,38 @@
+package com.xjrsoft.module.base.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+* @title: 班主任异动记录表表单出参
+* @Author dzx
+* @Date: 2025-04-24
+* @Version 1.0
+*/
+@Data
+public class BaseClassTeacherChangeVo {
+
+    /**
+    * 
+    */
+    @ApiModelProperty("")
+    private Long id;
+    /**
+    * 班级id(base_class)
+    */
+    @ApiModelProperty("班级id(base_class)")
+    private Long classId;
+    /**
+    * 异动前班主任(xjr_user)
+    */
+    @ApiModelProperty("异动前班主任(xjr_user)")
+    private Long beforeTeacherId;
+    /**
+    * 异动后班主任(xjr_user)
+    */
+    @ApiModelProperty("异动后班主任(xjr_user)")
+    private Long afterTeacherId;
+
+
+
+}

+ 3 - 0
src/main/java/com/xjrsoft/module/base/vo/BaseClassVo.java

@@ -71,4 +71,7 @@ public class BaseClassVo {
     @ApiModelProperty("专业方向id(base_major_set)")
     private Long majorSetId;
 
+    @ApiModelProperty("实习次数")
+    private Integer internshipFrequency;
+
 }

+ 101 - 43
src/main/java/com/xjrsoft/module/base/vo/BaseCourseSubjectPageVo.java

@@ -23,13 +23,6 @@ public class BaseCourseSubjectPageVo {
     @ExcelProperty("主键")
     @ApiModelProperty("主键")
     private String id;
-    /**
-     * 创建人
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("创建人")
-    @ApiModelProperty("创建人")
-    private Long createUserId;
     /**
      * 创建时间
      */
@@ -37,34 +30,6 @@ public class BaseCourseSubjectPageVo {
     @ExcelProperty("创建时间")
     @ApiModelProperty("创建时间")
     private Date createDate;
-    /**
-     * 修改人
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("修改人")
-    @ApiModelProperty("修改人")
-    private Long modifyUserId;
-    /**
-     * 修改时间
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("修改时间")
-    @ApiModelProperty("修改时间")
-    private Date modifyDate;
-    /**
-     * 删除标记
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("删除标记")
-    @ApiModelProperty("删除标记")
-    private Integer deleteMark;
-    /**
-     * 有效标志
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("有效标志")
-    @ApiModelProperty("有效标志")
-    private Integer enabledMark;
     /**
      * 课程学科名称
      */
@@ -79,13 +44,6 @@ public class BaseCourseSubjectPageVo {
     @ExcelProperty("课程学科代码")
     @ApiModelProperty("课程学科代码")
     private String code;
-    /**
-     * 备注
-     */
-    @ContentStyle(dataFormat = 49)
-    @ExcelProperty("备注")
-    @ApiModelProperty("备注")
-    private String remark;
     /**
      * 标签id(base_label)
      */
@@ -93,5 +51,105 @@ public class BaseCourseSubjectPageVo {
     @ExcelProperty("标签id(base_label)")
     @ApiModelProperty("标签id(base_label)")
     private Long baseLabelId;
-
+    /**
+     * 课程类别
+     */
+    @ApiModelProperty("课程类别")
+    private String courseCategory;
+    @ApiModelProperty("课程类别")
+    private String courseCategoryCn;
+    /**
+     * 课程性质
+     */
+    @ApiModelProperty("课程性质")
+    private String courseNature;
+    @ApiModelProperty("课程性质")
+    private String courseNatureCn;
+    /**
+     * 课程属性
+     */
+    @ApiModelProperty("课程属性")
+    private String courseAttribute;
+    @ApiModelProperty("课程属性")
+    private String courseAttributeCn;
+    /**
+     * 课程分类
+     */
+    @ApiModelProperty("课程分类")
+    private String courseType;
+    @ApiModelProperty("课程分类")
+    private String courseTypeCn;
+    /**
+     * 学科类别
+     */
+    @ApiModelProperty("学科类别")
+    private String subjectQuality;
+    @ApiModelProperty("学科类别")
+    private String subjectQualityCn;
+    /**
+     * 是否专业核心课程
+     */
+    @ApiModelProperty("是否专业核心课程")
+    private String coreCourse;
+    @ApiModelProperty("是否专业核心课程")
+    private String coreCourseCn;
+    /**
+     * 理论教学时数
+     */
+    @ApiModelProperty("理论教学时数")
+    private Integer theoryTime;
+    /**
+     * 实践教学时数
+     */
+    @ApiModelProperty("实践教学时数")
+    private Integer practiceTime;
+    /**
+     * 是否有线上课程
+     */
+    @ApiModelProperty("是否有线上课程")
+    private String onlineCourse;
+    @ApiModelProperty("是否有线上课程")
+    private String onlineCourseCn;
+    /**
+     * 线上课程网址
+     */
+    @ApiModelProperty("线上课程网址")
+    private String courseUrl;
+    /**
+     * 是否思政示范课程
+     */
+    @ApiModelProperty("是否思政示范课程")
+    private String ideologyDemo;
+    @ApiModelProperty("是否思政示范课程")
+    private String ideologyDemoCn;
+    /**
+     * 课堂教学设计主要选用课程资源
+     */
+    @ApiModelProperty("课堂教学设计主要选用课程资源")
+    private String courseResource;
+    /**
+     * 虚拟仿真实训课时数
+     */
+    @ApiModelProperty("虚拟仿真实训课时数")
+    private Integer emulationTime;
+    /**
+     * 主要开设虚拟仿真实训项目名称
+     */
+    @ApiModelProperty("主要开设虚拟仿真实训项目名称")
+    private String emulationName;
+    /**
+     * 主要开设实验项目名称
+     */
+    @ApiModelProperty("主要开设实验项目名称")
+    private String experimentName;
+    /**
+     * 主要开设实训项目名称
+     */
+    @ApiModelProperty("主要开设实训项目名称")
+    private String trainingName;
+    /**
+     * 主要开设实习项目名称
+     */
+    @ApiModelProperty("主要开设实习项目名称")
+    private String internshipName;
 }

+ 4 - 0
src/main/java/com/xjrsoft/module/courseTable/service/ICourseTableService.java

@@ -13,6 +13,7 @@ import com.xjrsoft.module.schedule.entity.WfCourseAdjust;
 import com.xjrsoft.module.schedule.vo.ClassOptionVo;
 import com.xjrsoft.module.schedule.vo.CourseListVo;
 import com.xjrsoft.module.schedule.vo.CourseTableVo;
+import com.xjrsoft.module.schedule.vo.CurrentWeekVo;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -64,4 +65,7 @@ public interface ICourseTableService extends IService<CourseTable> {
     ByteArrayOutputStream exportQuery(CourseTableExportQueryDto dto) throws IOException;
 
 
+    CurrentWeekVo getCurrentWeek(CourseTableDto dto);
+
+
 }

+ 35 - 0
src/main/java/com/xjrsoft/module/courseTable/service/impl/CourseTableServiceImpl.java

@@ -27,6 +27,7 @@ import com.xjrsoft.common.enums.TimeNumberEnum;
 import com.xjrsoft.common.enums.TimePeriodEnum;
 import com.xjrsoft.common.enums.WeekEnum;
 import com.xjrsoft.common.exception.MyException;
+import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.common.utils.excel.ExcelFillCellMergePrevColUtil;
 import com.xjrsoft.common.utils.excel.ExcelMergeUtil;
@@ -518,6 +519,9 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
             } else if (CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())) {
                 for (String courseId : courseIds) {
                     CourseTable courseTable = courseTableMapper.selectById(courseId);
+                    if(courseTable == null){
+                        continue;
+                    }
 
                     User applyUser = userService.getById(courseAdjust.getUserId());//申请人
                     User exchangeUser = userService.getById(courseAdjust.getExchangeTeacherId());//顶课人
@@ -1519,4 +1523,35 @@ public class CourseTableServiceImpl extends ServiceImpl<CourseTableMapper, Cours
         return bot;
     }
 
+    @Override
+    public CurrentWeekVo getCurrentWeek(CourseTableDto dto) {
+        BaseSemester baseSemester = baseSemesterService.getCurrentSemester();
+        if (baseSemester == null) {
+            return null;
+        }
+        LocalDateTime now = LocalDateTime.now();
+        if (dto.getScheduleDate() != null) {
+            now = dto.getScheduleDate();
+        }
+        //计算本周是第几周
+        LocalDateTime startDateTime = LocalDateTime.ofInstant(baseSemester.getTeachingStart().toInstant(), ZoneId.systemDefault());
+        LocalDateTime endDateTime = LocalDateTime.ofInstant(baseSemester.getTeachingEnd().toInstant(), ZoneId.systemDefault());
+        Duration between = Duration.between(startDateTime, endDateTime);
+        long days = between.toDays();
+        int weeks = (int) Math.ceil((double) days / 7);
+
+        for (int i = 0; i < weeks; i++) {
+            LocalDateTime startDate = startDateTime.plusDays(i * 7L).withHour(0).withMinute(0).withSecond(0).withNano(0);
+            LocalDateTime endDate = startDate.plusDays(6).withHour(23).withMinute(59).withSecond(59).withNano(9999);
+            if (now.isAfter(startDate) && now.isBefore(endDate)) {
+                CurrentWeekVo currentWeekVo = new CurrentWeekVo();
+                currentWeekVo.setWeek(i+ 1);
+                currentWeekVo.setStartDate(startDate.toLocalDate());
+                currentWeekVo.setEndDate(endDate.toLocalDate());
+                return currentWeekVo;
+            }
+        }
+        return null;
+    }
+
 }

+ 110 - 7
src/main/java/com/xjrsoft/module/databoard/controller/DataboardController.java

@@ -11,6 +11,8 @@ import com.xjrsoft.common.enums.StudyStatusEnum;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.mybatis.SqlRunnerAdapter;
 import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.module.base.entity.BaseSemester;
+import com.xjrsoft.module.base.service.IBaseSemesterService;
 import com.xjrsoft.module.courseTable.entity.CourseTable;
 import com.xjrsoft.module.courseTable.service.ICourseTableService;
 import com.xjrsoft.module.databoard.dto.StatisticsDetailDto;
@@ -36,6 +38,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
@@ -58,6 +62,7 @@ public class DataboardController {
     private final IBaseStudentService studentService;
     private final ITeacherbaseManagerService teacherService;
     private final IWorkflowFormRelationService formRelationService;
+    private final IBaseSemesterService semesterService;
 
     @GetMapping(value = "/process-statistics")
     @ApiOperation(value = "流程统计")
@@ -328,7 +333,7 @@ public class DataboardController {
         list = SqlRunnerAdapter.db().selectList(sql);
         for (Map<String, Object> objectMap : list) {
             if (objectMap.get("gender") != null && GenderDictionaryEnum.FEMALE.getCode().equals(objectMap.get("gender").toString())) {
-                result.setInfectionFemaleCount(Integer.parseInt(objectMap.get("a_count").toString()));
+                result.setPsychologicalFemaleCount(Integer.parseInt(objectMap.get("a_count").toString()));
             }
             if (objectMap.get("gender") != null && GenderDictionaryEnum.MALE.getCode().equals(objectMap.get("gender").toString())) {
                 result.setPsychologicalMaleCount(Integer.parseInt(objectMap.get("a_count").toString()));
@@ -391,19 +396,28 @@ public class DataboardController {
         sql += " group by t1.city_in ";
         list = SqlRunnerAdapter.db().selectList(sql);
         List<ItemCountAmountVo> amountList = new ArrayList<>();
-        for (Map<String, Object> objectMap : list) {
-            Object cityInObj = objectMap.get("city_in");
+        List<Integer> city_in = new ArrayList<>();
+        city_in.add(1);city_in.add(0);
+        for (Integer i : city_in) {
             String item = "";
-            if (cityInObj != null && Integer.parseInt(cityInObj.toString()) == 1) {
+            if(i == 1){
                 item = "市外";
-            } else if (cityInObj != null && Integer.parseInt(cityInObj.toString()) == 0) {
-                item = "室内";
+            }else{
+                item = "市内";
+            }
+            Double amount = 0D;
+            for (Map<String, Object> objectMap : list) {
+                Object cityInObj = objectMap.get("city_in");
+                if (cityInObj != null && Integer.parseInt(cityInObj.toString()) == i) {
+                    amount = Double.parseDouble(objectMap.get("total_amount").toString());
+                }
             }
             ItemCountAmountVo amountVo = new ItemCountAmountVo();
             amountVo.setItem(item);
-            amountVo.setAmount(Double.parseDouble(objectMap.get("total_amount").toString()));
+            amountVo.setAmount(amount);
             amountList.add(amountVo);
         }
+
         result.setAmountList(amountList);
         return RT.ok(result);
     }
@@ -596,4 +610,93 @@ public class DataboardController {
         return RT.ok(result);
     }
 
+    @GetMapping(value = "/internship-statistics")
+    @ApiOperation(value = "实习统计")
+    @SaCheckPermission("databoard:detail")
+    @XjrLog(value = "实习统计", saveResponseData = true)
+    public RT<InternshipStatisticsVo> internshipStatistics(@Valid StatisticsDetailDto dto) {
+        BaseSemester semester = semesterService.getCurrentSemester();
+        if(semester == null){
+            return RT.error("未能查询计划到当前学期");
+        }
+
+        InternshipStatisticsVo result = new InternshipStatisticsVo();
+
+        String sql = " SELECT DISTINCT t1.participant_user_id FROM internship_plan_manage_participant t1" +
+                " INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id" +
+                " INNER JOIN xjr_user t3 ON t1.participant_user_id = t3.id" +
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+                " and t2.base_semester_id = " + semester.getId();
+
+        List<Map<String, Object>> studentlist = SqlRunnerAdapter.db().selectList(sql);
+
+
+        sql = "SELECT DISTINCT t3.id FROM student_internship_alone_apply t1" +
+            " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = CAST(t2.form_key_value AS SIGNED)" +
+            " INNER JOIN xjr_user t3 ON t3.id = t1.student_user_id" +
+            " INNER JOIN internship_plan_manage t4 ON t1.internship_plan_manage_id = t4.id" +
+            " WHERE t1.delete_mark = 0 AND t3.delete_mark = 0 AND t4.delete_mark = 0" +
+            " and t4.base_semester_id = " + semester.getId() +
+            " AND t2.current_state = 'COMPLETED'";
+        List<Map<String, Object>> list2 = SqlRunnerAdapter.db().selectList(sql);
+
+        int studentCount = studentlist.size() + list2.size();
+        result.setStudentCount(studentCount);
+
+        //实习班级
+        sql = " SELECT DISTINCT t3.id FROM internship_plan_class t1" +
+            " INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id" +
+            " INNER JOIN base_class t3 ON t1.class_id = t3.id" +
+            " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+            " and t2.base_semester_id = " + semester.getId();
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
+        result.setClassCount(list.size());
+
+        //实习企业
+        sql = " SELECT * FROM company_coop WHERE delete_mark = 0";
+        list = SqlRunnerAdapter.db().selectList(sql);
+        result.setCompanyCount(list.size());
+
+
+        sql = "SELECT DISTINCT t3.id FROM student_special_constitution t1" +
+            " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = CAST(t2.form_key_value AS SIGNED)" +
+            " INNER JOIN xjr_user t3 ON t3.id = t1.student_user_id" +
+            " WHERE t1.delete_mark = 0 AND t3.delete_mark = 0" +
+            " AND t2.current_state = 'COMPLETED'";
+        List<Map<String, Object>> specialConstitutions = SqlRunnerAdapter.db().selectList(sql);
+
+        int allCount = specialConstitutions.size() + studentCount;
+
+        List<ItemCountRatioVo> studentList = new ArrayList<>();
+        //统一实习
+        ItemCountRatioVo item = new ItemCountRatioVo();
+        item.setItem("统一实习");
+        item.setCount(studentlist.size());
+        //计算占比
+        BigDecimal divide = BigDecimal.valueOf(studentlist.size()).divide(BigDecimal.valueOf(allCount), 4, RoundingMode.HALF_UP);
+        item.setRatio(divide.doubleValue());
+        studentList.add(item);
+
+        //自主实习
+        item = new ItemCountRatioVo();
+        item.setItem("自主实习");
+        item.setCount(list2.size());
+        //计算占比
+        divide = BigDecimal.valueOf(list2.size()).divide(BigDecimal.valueOf(allCount), 4, RoundingMode.HALF_UP);
+        item.setRatio(divide.doubleValue());
+        studentList.add(item);
+
+        //自主实习
+        item = new ItemCountRatioVo();
+        item.setItem("自主实习");
+        item.setCount(specialConstitutions.size());
+        //计算占比
+        divide = BigDecimal.valueOf(specialConstitutions.size()).divide(BigDecimal.valueOf(allCount), 4, RoundingMode.HALF_UP);
+        item.setRatio(divide.doubleValue());
+        studentList.add(item);
+
+        result.setStudentList(studentList);
+        return RT.ok(result);
+    }
+
 }

+ 143 - 6
src/main/java/com/xjrsoft/module/databoard/controller/DatadetailController.java

@@ -16,6 +16,7 @@ import com.xjrsoft.common.utils.SqlRunnerAdapterUtil;
 import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.entity.BaseSemester;
 import com.xjrsoft.module.base.mapper.BaseSemesterMapper;
+import com.xjrsoft.module.base.service.IBaseSemesterService;
 import com.xjrsoft.module.databoard.dto.StatisticsDetailDto;
 import com.xjrsoft.module.databoard.dto.TeacherChangeStatisticsDetailDto;
 import com.xjrsoft.module.databoard.vo.CourseCountListVo;
@@ -24,6 +25,10 @@ import com.xjrsoft.module.databoard.vo.DistributionVo;
 import com.xjrsoft.module.databoard.vo.DurationVo;
 import com.xjrsoft.module.databoard.vo.HealthItemCountVo;
 import com.xjrsoft.module.databoard.vo.HealthStatisticsDetailVo;
+import com.xjrsoft.module.databoard.vo.InternshipStatisticsDetailClassVo;
+import com.xjrsoft.module.databoard.vo.InternshipStatisticsDetailCompanyVo;
+import com.xjrsoft.module.databoard.vo.InternshipStatisticsDetailEvaluateVo;
+import com.xjrsoft.module.databoard.vo.InternshipStatisticsDetailVo;
 import com.xjrsoft.module.databoard.vo.ItemCount2Vo;
 import com.xjrsoft.module.databoard.vo.ItemCountAmountVo;
 import com.xjrsoft.module.databoard.vo.ItemCountRatioVo;
@@ -96,6 +101,7 @@ public class DatadetailController {
     private final IBaseStudentService studentService;
     private final IWfSubscriptionService subscriptionService;
     private final BaseSemesterMapper baseSemesterMapper;
+    private final IBaseSemesterService semesterService;
 
     @GetMapping(value = "/process-statistics")
     @ApiOperation(value = "流程统计详情")
@@ -196,7 +202,7 @@ public class DatadetailController {
     @SaCheckPermission("datadetail:detail")
     @XjrLog(value = "学生健康统计", saveResponseData = true)
     public RT<HealthStatisticsDetailVo> healthStatistics(@Valid StatisticsDetailDto dto) {
-        String sql = "SELECT t1.gender,COUNT(t1.*) AS a_count FROM student_infection t1" +
+        String sql = "SELECT t1.gender,COUNT(t1.id) AS a_count FROM student_infection t1" +
                 " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = t2.form_key_value" +
                 " WHERE t2.current_state = 'COMPLETED' GROUP BY t1.gender";
         List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
@@ -210,7 +216,7 @@ public class DatadetailController {
             }
         }
 
-        sql = "SELECT t1.gender,COUNT(t1.*) AS a_count FROM student_psychological t1" +
+        sql = "SELECT t1.gender,COUNT(t1.id) AS a_count FROM student_psychological t1" +
                 " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = t2.form_key_value" +
                 " WHERE t2.current_state = 'COMPLETED' GROUP BY t1.gender";
         list = SqlRunnerAdapter.db().selectList(sql);
@@ -296,10 +302,12 @@ public class DatadetailController {
     @SaCheckPermission("datadetail:detail")
     @XjrLog(value = "教职工详情数据统计", saveResponseData = true)
     public RT<TeacherStatisticsDetailVo> teahcerStatistics(@Valid StatisticsDetailDto dto) throws ParseException {
-        String sql = "SELECT IFNULL(t2.name,'未填写') AS item ,ifnull(COUNT(*), 0) AS a_count FROM base_teacher_education t1" +
-                " left join base_teacher t3 on t1.user_id = t3.user_id" +
-                " LEFT JOIN xjr_dictionary_detail t2 ON t1.education  = t2.code" +
-                " WHERE t1.delete_mark = 0 and t3.job_state in ('ZZZT10004','ZZZT10009','JOB_WCPX','JOB_DDSX')" +
+        String sql = "SELECT IFNULL(t2.name,'未填写') AS item ,IFNULL(COUNT(*), 0) AS a_count FROM xjr_user t1" +
+                " INNER JOIN base_teacher_education t4 ON  t1.id = t4.user_id " +
+                " LEFT JOIN base_teacher t3 ON t1.id = t3.user_id" +
+                " LEFT JOIN xjr_dictionary_detail t2 ON t4.education  = t2.code" +
+                " WHERE t1.delete_mark = 0 AND t3.job_state IN ('ZZZT10004','ZZZT10009','JOB_WCPX','JOB_DDSX')" +
+                " AND t4.delete_mark = 0" +
                 " GROUP BY t2.name";
         List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
         TeacherStatisticsDetailVo result = new TeacherStatisticsDetailVo();
@@ -961,4 +969,133 @@ public class DatadetailController {
         return RT.ok(result);
     }
 
+
+    @GetMapping(value = "/internship-statistics")
+    @ApiOperation(value = "实习统计")
+    @SaCheckPermission("databoard:detail")
+    @XjrLog(value = "实习统计", saveResponseData = true)
+    public RT<InternshipStatisticsDetailVo> internshipStatistics(@Valid StatisticsDetailDto dto) {
+        InternshipStatisticsDetailVo result = new InternshipStatisticsDetailVo();
+        BaseSemester semester = semesterService.getCurrentSemester();
+        if(semester == null){
+            return RT.error("未能查询计划到当前学期");
+        }
+        String sql = " SELECT DISTINCT t1.participant_user_id FROM internship_plan_manage_participant t1" +
+                " INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id" +
+                " INNER JOIN xjr_user t3 ON t1.participant_user_id = t3.id" +
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+                " and t2.base_semester_id = " + semester.getId();
+
+        List<Map<String, Object>> studentlist = SqlRunnerAdapter.db().selectList(sql);
+
+
+        sql = "SELECT DISTINCT t3.id FROM student_internship_alone_apply t1" +
+                " INNER JOIN xjr_workflow_form_relation t2 ON t1.id = CAST(t2.form_key_value AS SIGNED)" +
+                " INNER JOIN xjr_user t3 ON t3.id = t1.student_user_id" +
+                " INNER JOIN internship_plan_manage t4 ON t1.internship_plan_manage_id = t4.id" +
+                " WHERE t1.delete_mark = 0 AND t3.delete_mark = 0 AND t4.delete_mark = 0" +
+                " and t4.base_semester_id = " + semester.getId() +
+                " AND t2.current_state = 'COMPLETED'";
+        List<Map<String, Object>> list2 = SqlRunnerAdapter.db().selectList(sql);
+
+        int studentCount = studentlist.size() + list2.size();
+        result.setStudentCount(studentCount);
+
+        //实习班级
+        sql = " SELECT DISTINCT t3.id FROM internship_plan_class t1" +
+                " INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id" +
+                " INNER JOIN base_class t3 ON t1.class_id = t3.id" +
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+                " and t2.base_semester_id = " + semester.getId();
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql);
+        result.setClassCount(list.size());
+
+        //实习企业
+        sql = " SELECT * FROM company_coop WHERE delete_mark = 0";
+        list = SqlRunnerAdapter.db().selectList(sql);
+        result.setCompanyCount(list.size());
+
+
+        sql = "SELECT DISTINCT t3.name,\n" +
+            "(SELECT COUNT(participant_user_id) FROM internship_plan_manage_participant\n" +
+            "WHERE class_id = t3.id AND internship_plan_manage_id = t2.id and delete_mark = 0) AS unite_count,\n" +
+            "(SELECT COUNT(a1.student_user_id) FROM student_internship_alone_apply a1" +
+            " INNER JOIN xjr_workflow_form_relation a2 ON t1.id = CAST(a2.form_key_value AS SIGNED)" +
+            " WHERE a1.class_id = t3.id AND a1.internship_plan_manage_id = t2.id and a1.delete_mark = 0" +
+            " and a2.current_state = 'COMPLETED'" +
+            " ) AS alone_count,\n" +
+            "(SELECT COUNT(student_user_id) FROM student_special_constitution a1" +
+            " INNER JOIN xjr_workflow_form_relation a2 ON t1.id = CAST(a2.form_key_value AS SIGNED)" +
+            " WHERE a1.class_id = t3.id and a1.delete_mark = 0 and a2.current_state = 'COMPLETED') AS special_count\n" +
+            "FROM internship_plan_class t1\n" +
+            "INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id\n" +
+            "INNER JOIN base_class t3 ON t1.class_id = t3.id\n" +
+            "WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+            " and t2.base_semester_id = " + semester.getId();
+        List<Map<String, Object>> classDatas = SqlRunnerAdapter.db().selectList(sql);
+
+        List<InternshipStatisticsDetailClassVo> classList = new ArrayList<>();
+        for (Map<String, Object> objectMap : classDatas) {
+            classList.add(new InternshipStatisticsDetailClassVo(){{
+                setClassName(objectMap.get("name").toString());
+                setUniteCount(Integer.parseInt(objectMap.get("unite_count").toString()));
+                setAloneCount(Integer.parseInt(objectMap.get("alone_count").toString()));
+                setSpecialCount(Integer.parseInt(objectMap.get("special_count").toString()));
+            }});
+        }
+        result.setClassList(classList);
+
+        sql = "SELECT t1.id,t1.company_name,\n" +
+                "(\n" +
+                "SELECT COUNT(a1.id) FROM internship_plan_manage_participant a1\n" +
+                "INNER JOIN internship_plan_manage a2 ON a2.id = a1.internship_plan_manage_id \n" +
+                "WHERE a1.delete_mark = 0 AND a2.delete_mark = 0\n" +
+                "AND a2.internship_unit_id = t1.id\n" +
+                ") AS counts\n" +
+                "FROM company_coop t1\n" +
+                "WHERE t1.delete_mark = 0\n" +
+                "AND id IN (\n" +
+                "SELECT DISTINCT internship_unit_id FROM internship_plan_manage\n" +
+                "WHERE delete_mark = 0 AND base_semester_id = "  +semester.getId() +
+                ")";
+        List<Map<String, Object>> companyDatas = SqlRunnerAdapter.db().selectList(sql);
+        List<InternshipStatisticsDetailCompanyVo> companyList = new ArrayList<>();
+        for (Map<String, Object> companyData : companyDatas) {
+            companyList.add(new InternshipStatisticsDetailCompanyVo(){{
+                setCompanyName(companyData.get("company_name").toString());
+                setStudentCount(Integer.parseInt(companyData.get("counts").toString()));
+            }});
+        }
+        result.setCompanyList(companyList);
+
+        sql = "SELECT t3.name,\n" +
+                "(SELECT COUNT(*) FROM internship_plan_manage_participant WHERE delete_mark = 0\n" +
+                "AND result = '1' AND class_id = t3.id AND internship_plan_manage_id = t2.id\n" +
+                ") AS unqualified, \n" +
+                "(SELECT COUNT(*) FROM internship_plan_manage_participant WHERE delete_mark = 0\n" +
+                "AND result = '2' AND class_id = t3.id AND internship_plan_manage_id = t2.id\n" +
+                ") AS qualified, \n" +
+                "(SELECT COUNT(*) FROM internship_plan_manage_participant WHERE delete_mark = 0\n" +
+                "AND result = '3' AND class_id = t3.id AND internship_plan_manage_id = t2.id\n" +
+                ") AS excellent\n" +
+                "FROM internship_plan_class t1\n" +
+                "INNER JOIN internship_plan_manage t2 ON t1.internship_plan_manage_id = t2.id\n" +
+                "INNER JOIN base_class t3 ON t1.class_id = t3.id\n" +
+                "WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.delete_mark = 0" +
+                " and t2.base_semester_id = " + semester.getId();
+        List<Map<String, Object>> evaluateDatas = SqlRunnerAdapter.db().selectList(sql);
+        List<InternshipStatisticsDetailEvaluateVo> evaluateList = new ArrayList<>();
+        for (Map<String, Object> companyData : evaluateDatas) {
+            evaluateList.add(new InternshipStatisticsDetailEvaluateVo(){{
+                setClassName(companyData.get("name").toString());
+                setUnqualifiedCount(Integer.parseInt(companyData.get("unqualified").toString()));
+                setQualifiedCount(Integer.parseInt(companyData.get("qualified").toString()));
+                setExcellentCount(Integer.parseInt(companyData.get("excellent").toString()));
+            }});
+        }
+        result.setEvaluateList(evaluateList);
+
+        return RT.ok(result);
+    }
+
 }

+ 37 - 0
src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailClassVo.java

@@ -0,0 +1,37 @@
+package com.xjrsoft.module.databoard.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @title: 实习详情统计-班级
+ * @Author dzx
+ * @Date: 2025年7月14日
+ * @Version 1.0
+ */
+@Data
+public class InternshipStatisticsDetailClassVo {
+
+    /**
+     * 发起流程总数
+     */
+    @ApiModelProperty("班级名称")
+    private String className;
+    /**
+     * 完成总数
+     */
+    @ApiModelProperty("统一实习学生数量")
+    private Integer uniteCount;
+    /**
+     * 未完成总数
+     */
+    @ApiModelProperty("自主实习学生数量")
+    private Integer aloneCount;
+
+
+    @ApiModelProperty("特殊体质学生数量")
+    private Integer specialCount;
+
+}

+ 28 - 0
src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailCompanyVo.java

@@ -0,0 +1,28 @@
+package com.xjrsoft.module.databoard.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @title: 实习详情统计-实习企业
+ * @Author dzx
+ * @Date: 2025年7月14日
+ * @Version 1.0
+ */
+@Data
+public class InternshipStatisticsDetailCompanyVo {
+
+    /**
+     * 发起流程总数
+     */
+    @ApiModelProperty("实习学生数量")
+    private Integer studentCount;
+    /**
+     * 完成总数
+     */
+    @ApiModelProperty("企业名称")
+    private String companyName;
+
+}

+ 34 - 0
src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailEvaluateVo.java

@@ -0,0 +1,34 @@
+package com.xjrsoft.module.databoard.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @title: 实习详情统计-实习类型
+ * @Author dzx
+ * @Date: 2025年7月14日
+ * @Version 1.0
+ */
+@Data
+public class InternshipStatisticsDetailEvaluateVo {
+
+    @ApiModelProperty("班级名称")
+    private String className;
+    /**
+     * 完成总数
+     */
+    @ApiModelProperty("不合格数量")
+    private Integer unqualifiedCount;
+    /**
+     * 未完成总数
+     */
+    @ApiModelProperty("合格数量")
+    private Integer qualifiedCount;
+
+
+    @ApiModelProperty("优秀数量")
+    private Integer excellentCount;
+
+}

+ 43 - 0
src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsDetailVo.java

@@ -0,0 +1,43 @@
+package com.xjrsoft.module.databoard.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @title: 数据看板-流程统计出参
+ * @Author dzx
+ * @Date: 2024年8月2日
+ * @Version 1.0
+ */
+@Data
+public class InternshipStatisticsDetailVo {
+
+    /**
+     * 发起流程总数
+     */
+    @ApiModelProperty("实习学生数量")
+    private Integer studentCount;
+    /**
+     * 完成总数
+     */
+    @ApiModelProperty("实习班级数量")
+    private Integer classCount;
+    /**
+     * 未完成总数
+     */
+    @ApiModelProperty("实习企业数量")
+    private Integer companyCount;
+
+
+    @ApiModelProperty("实习企业")
+    private List<InternshipStatisticsDetailCompanyVo> companyList;
+
+    @ApiModelProperty("实习班级")
+    private List<InternshipStatisticsDetailClassVo> classList;
+
+    @ApiModelProperty("实习结果")
+    private List<InternshipStatisticsDetailEvaluateVo> evaluateList;
+
+}

+ 37 - 0
src/main/java/com/xjrsoft/module/databoard/vo/InternshipStatisticsVo.java

@@ -0,0 +1,37 @@
+package com.xjrsoft.module.databoard.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @title: 数据看板-流程统计出参
+ * @Author dzx
+ * @Date: 2024年8月2日
+ * @Version 1.0
+ */
+@Data
+public class InternshipStatisticsVo {
+
+    /**
+     * 发起流程总数
+     */
+    @ApiModelProperty("实习学生数量")
+    private Integer studentCount;
+    /**
+     * 完成总数
+     */
+    @ApiModelProperty("实习班级数量")
+    private Integer classCount;
+    /**
+     * 未完成总数
+     */
+    @ApiModelProperty("实习企业数量")
+    private Integer companyCount;
+
+
+    @ApiModelProperty("学生组成占比")
+    private List<ItemCountRatioVo> studentList;
+
+}

+ 4 - 0
src/main/java/com/xjrsoft/module/evaluate/dto/EvaluateObjectListDto.java

@@ -5,6 +5,7 @@ import lombok.Data;
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 
 
 /**
@@ -43,4 +44,7 @@ public class EvaluateObjectListDto implements Serializable {
     @ApiModelProperty("结束时间")
     private Date endTime;
 
+    @ApiModelProperty("班级ids")
+    private String classIds;
+
 }

+ 181 - 7
src/main/java/com/xjrsoft/module/evaluate/service/impl/EvaluateObjectServiceImpl.java

@@ -14,6 +14,7 @@ import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.base.entity.BaseGrade;
 import com.xjrsoft.module.courseTable.dto.ClassTeacherDto;
 import com.xjrsoft.module.courseTable.mapper.CourseTableMapper;
+import com.xjrsoft.module.courseTable.service.ICourseTableService;
 import com.xjrsoft.module.courseTable.vo.ClassTeacherVo;
 import com.xjrsoft.module.evaluate.dto.*;
 import com.xjrsoft.module.evaluate.entity.EvaluateExecuter;
@@ -27,6 +28,11 @@ import com.xjrsoft.module.evaluate.service.IEvaluateObjectService;
 import com.xjrsoft.module.evaluate.vo.*;
 import com.xjrsoft.module.organization.entity.User;
 import com.xjrsoft.module.organization.service.IUserService;
+import com.xjrsoft.module.schedule.dto.CourseTableDto;
+import com.xjrsoft.module.schedule.vo.CurrentWeekVo;
+import com.xjrsoft.module.student.dto.BaseStudentUserPageDto;
+import com.xjrsoft.module.student.service.IBaseStudentService;
+import com.xjrsoft.module.student.vo.BaseStudentUserPageVo;
 import com.xjrsoft.module.teacher.entity.BaseTeacher;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
@@ -51,6 +57,8 @@ public class EvaluateObjectServiceImpl extends MPJBaseServiceImpl<EvaluateObject
     private final EvaluateExecuterMapper evaluateExecuterMapper;
     private final CourseTableMapper courseTableMapper;
     private final IUserService userService;
+    private final IBaseStudentService studentService;
+    private final ICourseTableService courseTableService;
 
 
     @Override
@@ -242,7 +250,8 @@ public class EvaluateObjectServiceImpl extends MPJBaseServiceImpl<EvaluateObject
                 objectListVo.setExecuterCount(executerList.size());
                 objectListVo.setExecuterList(executerList);
             }
-        } else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.DRILLMASTER_EVALUATE_CLASS.getCode())) {//入参评价类型是教官评价班级
+        }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.DRILLMASTER_EVALUATE_CLASS.getCode())) {//入参评价类型是教官评价班级
             newObjectList = evaluateObjectMapper.getNewObjectList(dto);
             List<EvaluateExecuterVo> newExecuterList = evaluateObjectMapper.getNewExecuterList(dto);
 
@@ -250,15 +259,16 @@ public class EvaluateObjectServiceImpl extends MPJBaseServiceImpl<EvaluateObject
                 objectListVo.setExecuterCount(newExecuterList.size());
                 objectListVo.setExecuterList(newExecuterList);
             }
-        } else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.TEACHER_EVALUATE_CLASS.getCode())) {//任课教师对班级评价
-            EvaluateManage manage = evaluateManageMapper.selectById(dto.getEvaluateManageId());
+        }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.TEACHER_EVALUATE_CLASS.getCode())) {//任课教师对班级评价
+            CurrentWeekVo currentWeek = courseTableService.getCurrentWeek(new CourseTableDto());
             newObjectList = evaluateObjectMapper.getNewObjectList(dto);
 
             List<ClassTeacherVo> classTeacher = courseTableMapper.getClassTeacherIds(
                     new ClassTeacherDto() {{
-                        setStartDate(manage.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
+                        setStartDate(currentWeek.getStartDate());
                         setGradeId(dto.getGradeId());
-                        setEndDate(manage.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
+                        setEndDate(currentWeek.getEndDate());
                     }}
             );
 
@@ -278,18 +288,21 @@ public class EvaluateObjectServiceImpl extends MPJBaseServiceImpl<EvaluateObject
 
                     String[] teacherIds = executerVo.getTeacherId().split(",");
                     for (String teacherId : teacherIds) {
+                        if("0".equals(teacherId)){
+                            continue;
+                        }
                         EvaluateExecuterVo evaluateExecuterVo = new EvaluateExecuterVo();
                         evaluateExecuterVo.setExecuterId(teacherId);
                         evaluateExecuterVo.setEvaluateObjectId(objectListVo.getObjectId());
                         evaluateExecuterVo.setExecuterName(userMap.get(Long.parseLong(teacherId.trim())));
-                        evaluateExecuterVo.setEvaluateManageId(dto.getEvaluateManageId().toString());
                         currentExecuterList.add(evaluateExecuterVo);
                     }
                 }
                 objectListVo.setExecuterCount(currentExecuterList.size());
                 objectListVo.setExecuterList(currentExecuterList);
             }
-        } else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.STUDENT_EVALUATE_COURSE_TEACHER.getCode())) {//入参评价类型是学生评价教师
+        }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.STUDENT_EVALUATE_COURSE_TEACHER.getCode())) {//入参评价类型是学生评价教师
             EvaluateManage manage = evaluateManageMapper.selectById(dto.getEvaluateManageId());
             //查询这个年级的所有学生
             List<EvaluateExecuterVo> newExecuterList = evaluateObjectMapper.getNewExecuterList(dto);
@@ -358,6 +371,167 @@ public class EvaluateObjectServiceImpl extends MPJBaseServiceImpl<EvaluateObject
                 newObjectList.add(objectListVo);
             }
         }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.STU_SELF_EVALUATE.getCode())){//学生自评
+            BaseStudentUserPageDto studentUserPageDto = new BaseStudentUserPageDto();
+            studentUserPageDto.setGradeId(dto.getGradeId());
+            if(StrUtil.isNotEmpty(dto.getClassIds())){
+                String[] ids = dto.getClassIds().split(",");
+                List<Long> classIds = new ArrayList<>();
+                for (String id : ids) {
+                    classIds.add(Long.parseLong(id));
+                }
+                studentUserPageDto.setClassIds(classIds);
+            }
+            List<BaseStudentUserPageVo> studentList = studentService.getStudentList(studentUserPageDto);
+
+            for (BaseStudentUserPageVo student : studentList) {
+                EvaluateObjectListVo object = new EvaluateObjectListVo();
+                object.setObjectName(student.getName());
+                object.setObjectId(student.getId());
+                object.setGradeId(student.getGradeId().toString());
+                object.setGradeName(student.getGradeName());
+                object.setClassId(student.getClassId().toString());
+
+                List<EvaluateExecuterVo> executerList = new ArrayList<>();
+
+                EvaluateExecuterVo executerVo = new EvaluateExecuterVo();
+                executerVo.setEvaluateObjectId(student.getId());
+                executerVo.setExecuterName(student.getName());
+                executerVo.setExecuterId(student.getId());
+                executerVo.setGradeId(student.getGradeId().toString());
+                executerVo.setClassId(student.getClassId().toString());
+
+                executerList.add(executerVo);
+                object.setExecuterList(executerList);
+                object.setExecuterCount(executerList.size());
+
+                newObjectList.add(object);
+            }
+        }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.CLASS_STU_EVALUATE.getCode())){//班级学生交叉互评
+            BaseStudentUserPageDto studentUserPageDto = new BaseStudentUserPageDto();
+            studentUserPageDto.setGradeId(dto.getGradeId());
+            if(StrUtil.isNotEmpty(dto.getClassIds())){
+                String[] ids = dto.getClassIds().split(",");
+                List<Long> classIds = new ArrayList<>();
+                for (String id : ids) {
+                    classIds.add(Long.parseLong(id));
+                }
+                studentUserPageDto.setClassIds(classIds);
+            }
+            List<BaseStudentUserPageVo> studentList = studentService.getStudentList(studentUserPageDto);
+            Map<Long, List<BaseStudentUserPageVo>> classStudentMap = studentList.stream().collect(Collectors.groupingBy(BaseStudentUserPageVo::getClassId));
+            for (BaseStudentUserPageVo student : studentList) {
+                EvaluateObjectListVo object = new EvaluateObjectListVo();
+                object.setObjectName(student.getName());
+                object.setObjectId(student.getId());
+                object.setGradeId(student.getGradeId().toString());
+                object.setGradeName(student.getGradeName());
+                object.setClassId(student.getClassId().toString());
+
+                List<BaseStudentUserPageVo> classStudentList = classStudentMap.get(student.getClassId());
+
+                List<EvaluateExecuterVo> executerList = new ArrayList<>();
+                if(classStudentList != null){
+                    for (BaseStudentUserPageVo otherStudent : classStudentList) {
+                        if(otherStudent.getId().equals(student.getId())){
+                            continue;
+                        }
+                        EvaluateExecuterVo executerVo = new EvaluateExecuterVo();
+                        executerVo.setEvaluateObjectId(student.getId());
+                        executerVo.setExecuterName(otherStudent.getName());
+                        executerVo.setExecuterId(otherStudent.getId());
+                        executerVo.setGradeId(otherStudent.getGradeId().toString());
+                        executerVo.setClassId(otherStudent.getClassId().toString());
+
+                        executerList.add(executerVo);
+                    }
+                }
+
+                object.setExecuterList(executerList);
+                object.setExecuterCount(executerList.size());
+                newObjectList.add(object);
+            }
+        }
+        else if (dto.getEvaluateType() != null && dto.getEvaluateType().equals(EvaluateTypeEnum.TEA_EVALUATE_STU.getCode())){//教师评价班级学生
+            BaseStudentUserPageDto studentUserPageDto = new BaseStudentUserPageDto();
+            studentUserPageDto.setGradeId(dto.getGradeId());
+            if(StrUtil.isNotEmpty(dto.getClassIds())){
+                String[] ids = dto.getClassIds().split(",");
+                List<Long> classIds = new ArrayList<>();
+                for (String id : ids) {
+                    classIds.add(Long.parseLong(id));
+                }
+                studentUserPageDto.setClassIds(classIds);
+            }
+
+
+            List<BaseStudentUserPageVo> studentList = studentService.getStudentList(studentUserPageDto);
+
+            for (BaseStudentUserPageVo student : studentList) {
+                EvaluateObjectListVo object = new EvaluateObjectListVo();
+                object.setObjectName(student.getName());
+                object.setObjectId(student.getId());
+                object.setGradeId(student.getGradeId().toString());
+                object.setGradeName(student.getGradeName());
+                object.setClassId(student.getClassId().toString());
+                newObjectList.add(object);
+            }
+
+
+            CurrentWeekVo currentWeek = courseTableService.getCurrentWeek(new CourseTableDto());
+            List<ClassTeacherVo> classTeacher = courseTableMapper.getClassTeacherIds(
+                    new ClassTeacherDto() {{
+                        setStartDate(currentWeek.getStartDate());
+                        setGradeId(dto.getGradeId());
+                        setEndDate(currentWeek.getEndDate());
+                    }}
+            );
+
+            List<User> userList = userService.list(
+                    new MPJLambdaWrapper<User>()
+                            .select(User::getId)
+                            .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
+                            .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
+            );
+            Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getName));
+            for (EvaluateObjectListVo objectListVo : newObjectList) {
+                List<EvaluateExecuterVo> currentExecuterList = new ArrayList<>();
+                for (ClassTeacherVo executerVo : classTeacher) {
+                    if (!objectListVo.getClassId().equals(executerVo.getClassId().toString())) {
+                        continue;
+                    }
+
+                    String[] teacherIds = executerVo.getTeacherId().split(",");
+                    for (String teacherId : teacherIds) {
+                        if("0".equals(teacherId)){
+                            continue;
+                        }
+                        EvaluateExecuterVo evaluateExecuterVo = new EvaluateExecuterVo();
+                        evaluateExecuterVo.setExecuterId(teacherId);
+                        evaluateExecuterVo.setEvaluateObjectId(objectListVo.getObjectId());
+                        evaluateExecuterVo.setExecuterName(userMap.get(Long.parseLong(teacherId.trim())));
+                        currentExecuterList.add(evaluateExecuterVo);
+                    }
+                }
+                objectListVo.setExecuterCount(currentExecuterList.size());
+                objectListVo.setExecuterList(currentExecuterList);
+
+
+                Set<String> collect = currentExecuterList.stream().map(EvaluateExecuterVo::getExecuterId).collect(Collectors.toSet());
+                List<EvaluateExecuterVo> notExecuterList = new ArrayList<>();
+                List<User> notUserList = userList.stream().filter(x -> !collect.contains(x.getId().toString())).collect(Collectors.toList());
+                for (User user : notUserList) {
+                    EvaluateExecuterVo evaluateExecuterVo = new EvaluateExecuterVo();
+                    evaluateExecuterVo.setExecuterId(user.getId().toString());
+                    evaluateExecuterVo.setEvaluateObjectId(objectListVo.getObjectId());
+                    evaluateExecuterVo.setExecuterName(user.getName());
+                    notExecuterList.add(evaluateExecuterVo);
+                }
+                objectListVo.setNotExecuterList(notExecuterList);
+            }
+
+        }
 
         return newObjectList;
     }

+ 3 - 0
src/main/java/com/xjrsoft/module/evaluate/vo/EvaluateObjectListVo.java

@@ -52,6 +52,9 @@ public class EvaluateObjectListVo {
     @ApiModelProperty("参与评价的人")
     private List<EvaluateExecuterVo> executerList;
 
+    @ApiModelProperty("待选参与评价的人")
+    private List<EvaluateExecuterVo> notExecuterList;
+
     /**
      * 被评价对象id
      */

+ 1 - 1
src/main/java/com/xjrsoft/module/form/controller/FormExecuteController.java

@@ -222,7 +222,7 @@ public class FormExecuteController {
         return R.ok(formExecuteService.workFlowInfo(dto));
     }
 
-    //    @GetMapping(value = "/export")
+//    @GetMapping(value = "/export")
 //    @ApiOperation(value = "导出")
 //    @XjrLog(value = "导出表单数据")
 //    public ResponseEntity<byte[]> export(@Valid FormExecuteListDto dto) throws IOException {

+ 23 - 0
src/main/java/com/xjrsoft/module/form/entity/QueryCondition.java

@@ -0,0 +1,23 @@
+package com.xjrsoft.module.form.entity;
+
+import lombok.Data;
+
+@Data
+public class QueryCondition {
+    private String fieldName;
+    private Object value;
+    private String operator; // "=", ">=", "<=", "LIKE"等
+    private boolean isDate;
+    private int index; // 添加索引字段
+
+    public String toSqlSnippet() {
+        if (isDate && "BETWEEN".equals(operator)) {
+            return String.format("%s BETWEEN #{conditions[%d].value[0]} AND #{conditions[%d].value[1]}",
+                    fieldName, index, index);
+        }
+        if ("LIKE".equals(operator)) {
+            return String.format("%s LIKE #{conditions[%d].value}", fieldName, index);
+        }
+        return String.format("%s %s #{conditions[%d].value}", fieldName, operator, index);
+    }
+}

+ 29 - 0
src/main/java/com/xjrsoft/module/form/mapper/CustomFormDataMapper.java

@@ -0,0 +1,29 @@
+package com.xjrsoft.module.form.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.xjrsoft.module.form.entity.QueryCondition;
+import com.xjrsoft.module.form.utils.FormDataSqlProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.SelectProvider;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface CustomFormDataMapper {
+
+    @SelectProvider(type = FormDataSqlProvider.class, method = "buildSelectSql")
+    IPage<Map<String, Object>> selectFormDataPage(
+            IPage<Map<String, Object>> page,
+            @Param("tableName") String tableName,
+            @Param("fields") List<String> fields,
+            @Param("conditions") List<QueryCondition> conditions);
+
+    @SelectProvider(type = FormDataSqlProvider.class, method = "buildSelectSql")
+    List<Map<String, Object>> selectFormDataList(
+            @Param("tableName") String tableName,
+            @Param("fields") List<String> fields,
+            @Param("conditions") List<QueryCondition> conditions);
+}

+ 345 - 84
src/main/java/com/xjrsoft/module/form/service/impl/FormExecuteServiceImpl.java

@@ -16,6 +16,7 @@ import cn.hutool.db.sql.Direction;
 import cn.hutool.db.sql.Order;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.xjrsoft.common.constant.GlobalConstant;
@@ -33,10 +34,8 @@ import com.xjrsoft.module.app.entity.AppFuncDesign;
 import com.xjrsoft.module.app.service.IAppFuncDesignService;
 import com.xjrsoft.module.authority.utils.AuthorityUtil;
 import com.xjrsoft.module.form.dto.*;
-import com.xjrsoft.module.form.entity.FormDesignConfig;
-import com.xjrsoft.module.form.entity.FormRelease;
-import com.xjrsoft.module.form.entity.FormReleaseConfig;
-import com.xjrsoft.module.form.entity.FormTemplate;
+import com.xjrsoft.module.form.entity.*;
+import com.xjrsoft.module.form.mapper.CustomFormDataMapper;
 import com.xjrsoft.module.form.mapper.FormReleaseMapper;
 import com.xjrsoft.module.form.mapper.FormTemplateMapper;
 import com.xjrsoft.module.form.service.IFormExecuteService;
@@ -98,6 +97,8 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
 
     private final IFormReleaseService formReleaseService;
 
+    private final CustomFormDataMapper customFormDataMapper;
+
     /**
      * 需要模糊查询的
      */
@@ -139,13 +140,15 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
             String tableName = tableConfig.getTableName();
 
             List<ColumnConfig> columnConfigs = formReleaseConfig.getListConfig().getColumnConfigs();
-            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toList());
+            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).distinct().collect(Collectors.toList());
             // 添加权限所属人字段返回
             if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
                 fieldsList.add(GlobalConstant.AUTH_USER_ID);
             }
 
-            List<Entity> listData = getListDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams());
+//            List<Entity> listData = getListDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams());
+            List<Entity> listData = getListDataByParameterization(tableName, fieldsList, formReleaseConfig, dto.getParams());
+
             if (dto.getIsTrans()) {
                 // 关联数据显示转换
                 FormDataTransUtil.transData(listData, formDesignConfig);
@@ -180,13 +183,14 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
             String tableName = tableConfig.getTableName();
 
             List<ColumnConfig> columnConfigs = formReleaseConfig.getListConfig().getColumnConfigs();
-            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toList());
+            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).distinct().collect(Collectors.toList());
             // 添加权限所属人字段返回
             if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
                 fieldsList.add(GlobalConstant.AUTH_USER_ID);
             }
 
-            List<Entity> listData = getListDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams());
+//            List<Entity> listData = getListDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams());
+            List<Entity> listData = getListDataByParameterization(tableName, fieldsList, formReleaseConfig, dto.getParams());
             if (dto.getIsTrans()) {
                 // 关联数据显示转换
                 FormDataTransUtil.transData(listData, formDesignConfig);
@@ -223,41 +227,63 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
             String tableName = tableConfig.getTableName();
 
             //构建分页参数
-            Page page = new Page(dto.getLimit() - 1, dto.getSize());
-            String field = dto.getField();
-            String orderStr = dto.getOrder();
+//            Page page = new Page(dto.getLimit() - 1, dto.getSize());
+//            String field = dto.getField();
+//            String orderStr = dto.getOrder();
+//            ListConfig listConfig = formReleaseConfig.getListConfig();
+//            if (StrUtil.isBlank(field)) {
+//                field = StrUtil.emptyToDefault(listConfig.getOrderBy(), tableConfig.getPkField());
+//                orderStr = StrUtil.emptyToDefault(listConfig.getOrderType(), "desc");
+//            }
+//            if (StrUtil.isNotBlank(field)) {
+//                Order order = new Order();
+//                order.setDirection(Direction.ASC);
+//                if (orderStr.equals("descend") || orderStr.equals("desc")) {
+//                    order.setDirection(Direction.DESC);
+//                }
+////                order.setDirection(StrUtil.equalsIgnoreCase(orderStr, "descend") ? Direction.DESC : Direction.ASC);
+//                order.setField(field);
+//                page.setOrder(order);
+//            }
+//
+//            List<ColumnConfig> columnConfigs = listConfig.getColumnConfigs();
+//            Set<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toSet());
+//            // 添加权限所属人字段返回
+//            if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
+//                fieldsList.add(GlobalConstant.AUTH_USER_ID);
+//            }
+//
+//            PageOutput<Entity> pageData = getPageDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams(), page);
+
+            IPage<Map<String, Object>> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(dto.getLimit()-1, dto.getSize());
             ListConfig listConfig = formReleaseConfig.getListConfig();
-            if (StrUtil.isBlank(field)) {
-                field = StrUtil.emptyToDefault(listConfig.getOrderBy(), tableConfig.getPkField());
-                orderStr = StrUtil.emptyToDefault(listConfig.getOrderType(), "desc");
-            }
-            if (StrUtil.isNotBlank(field)) {
-                Order order = new Order();
-                order.setDirection(Direction.ASC);
-                if (orderStr.equals("descend") || orderStr.equals("desc")) {
-                    order.setDirection(Direction.DESC);
-                }
-//                order.setDirection(StrUtil.equalsIgnoreCase(orderStr, "descend") ? Direction.DESC : Direction.ASC);
-                order.setField(field);
-                page.setOrder(order);
+            if (StrUtil.isNotBlank(dto.getField())) {
+                boolean asc = !"desc".equalsIgnoreCase(dto.getOrder()) && !"descend".equalsIgnoreCase(dto.getOrder());
+                page.orders().add(new OrderItem(dto.getField(), asc));
+            } else {
+                // 默认排序
+                page.orders().add(new OrderItem(tableConfig.getPkField(), false));
             }
 
             List<ColumnConfig> columnConfigs = listConfig.getColumnConfigs();
-            Set<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toSet());
+            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).distinct().collect(Collectors.toList());
             // 添加权限所属人字段返回
             if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
                 fieldsList.add(GlobalConstant.AUTH_USER_ID);
             }
 
-            PageOutput<Entity> pageData = getPageDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams(), page);
+            PageOutput<Entity> pageData = getPageDataByParameterization(tableName, fieldsList, formReleaseConfig, dto.getParams(), page);
+
             if (dto.getIsTrans()) {
                 // 关联数据显示转换
                 FormDataTransUtil.transData(pageData.getList(), formDesignConfig);
             }
+
             return pageData;
         } else {
             throw new MyException("主表不存在");
         }
+
     }
 
     @Override
@@ -280,30 +306,50 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
             TableConfig tableConfig = mainTable.get();
             String tableName = tableConfig.getTableName();
 
-            //构建分页参数
-            Page page = new Page(dto.getLimit() - 1, dto.getSize());
-            String field = dto.getField();
-            String orderStr = dto.getOrder();
+//            //构建分页参数
+//            Page page = new Page(dto.getLimit() - 1, dto.getSize());
+//            String field = dto.getField();
+//            String orderStr = dto.getOrder();
+//            ListConfig listConfig = formReleaseConfig.getListConfig();
+//            if (StrUtil.isBlank(field)) {
+//                field = StrUtil.emptyToDefault(listConfig.getOrderBy(), tableConfig.getPkField());
+//                orderStr = StrUtil.emptyToDefault(listConfig.getOrderType(), "desc");
+//            }
+//            if (StrUtil.isNotBlank(field)) {
+//                Order order = new Order();
+//                order.setDirection(StrUtil.equalsIgnoreCase(orderStr, "desc") ? Direction.DESC : Direction.ASC);
+//                order.setField(field);
+//                page.setOrder(order);
+//            }
+//
+//            List<ColumnConfig> columnConfigs = listConfig.getColumnConfigs();
+//            Set<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toSet());
+//            // 添加权限所属人字段返回
+//            if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
+//                fieldsList.add(GlobalConstant.AUTH_USER_ID);
+//            }
+//
+//            PageOutput<Entity> pageData = getPageDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams(), page);
+
+            IPage<Map<String, Object>> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
             ListConfig listConfig = formReleaseConfig.getListConfig();
-            if (StrUtil.isBlank(field)) {
-                field = StrUtil.emptyToDefault(listConfig.getOrderBy(), tableConfig.getPkField());
-                orderStr = StrUtil.emptyToDefault(listConfig.getOrderType(), "desc");
-            }
-            if (StrUtil.isNotBlank(field)) {
-                Order order = new Order();
-                order.setDirection(StrUtil.equalsIgnoreCase(orderStr, "desc") ? Direction.DESC : Direction.ASC);
-                order.setField(field);
-                page.setOrder(order);
+            if (StrUtil.isNotBlank(dto.getField())) {
+                boolean asc = !"desc".equalsIgnoreCase(dto.getOrder()) && !"descend".equalsIgnoreCase(dto.getOrder());
+                page.orders().add(new OrderItem(dto.getField(), asc));
+            } else {
+                // 默认排序
+                page.orders().add(new OrderItem(tableConfig.getPkField(), false));
             }
 
             List<ColumnConfig> columnConfigs = listConfig.getColumnConfigs();
-            Set<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).collect(Collectors.toSet());
+            List<String> fieldsList = columnConfigs.stream().map(ColumnConfig::getColumnName).distinct().collect(Collectors.toList());
             // 添加权限所属人字段返回
             if (BooleanUtils.isTrue(formDesignConfig.getIsDataAuth())) {
                 fieldsList.add(GlobalConstant.AUTH_USER_ID);
             }
 
-            PageOutput<Entity> pageData = getPageDataByExpression(tableName, fieldsList, formDesignConfig, formReleaseConfig, dto.getParams(), page);
+            PageOutput<Entity> pageData = getPageDataByParameterization(tableName, fieldsList, formReleaseConfig, dto.getParams(), page);
+
             if (dto.getIsTrans()) {
                 // 关联数据显示转换
                 FormDataTransUtil.transData(pageData.getList(), formDesignConfig);
@@ -568,7 +614,6 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
         return updateFormData(formData, template);
     }
 
-
     @Override
     public Boolean delete(FormExecuteDeleteDto dto) {
 
@@ -866,7 +911,6 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
         }
     }
 
-
     @Transactional
     public Long insertFormData(Map<String, Object> formData, FormTemplate template) {
 //        for (Map.Entry<String, Object> entry : formData.entrySet()) {
@@ -1596,6 +1640,62 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
         return entities;
     }
 
+    @SneakyThrows
+    private List<Entity> getListDataByParameterization(String tableName,
+                                                             List<String> fieldsList,
+                                                             FormReleaseConfig formReleaseConfig,
+                                                             Map<String, Object> params
+    ) {
+        //获取表里所有字段
+        Table tableMeta = SqlRunnerAdapter.db().getTableMeta(tableName);
+        Collection<Column> columns = tableMeta.getColumns();
+
+        Optional<Column> pkOptional = columns.stream().filter(Column::isPk).findFirst();
+        Column pkColumn;
+
+        if (pkOptional.isPresent()) {
+            pkColumn = pkOptional.get();
+            fieldsList.add(0, pkColumn.getName());
+        } else {
+            throw new MyException("主键不存在");
+        }
+
+        List<QueryConfig> queryConfigs = formReleaseConfig.getListConfig().getQueryConfigs();
+
+        //如果有左侧树 需要把所选项目 where 条件加上
+        if (formReleaseConfig.getListConfig().getIsLeftMenu()) {
+            //如果已经包含此字段  就不添加了
+            if (queryConfigs.stream().noneMatch(x -> StrUtil.equals(x.getFieldName(), formReleaseConfig.getListConfig().getLeftMenuConfig().getListFieldName()))) {
+                QueryConfig queryConfig = new QueryConfig();
+                queryConfig.setFieldName(formReleaseConfig.getListConfig().getLeftMenuConfig().getListFieldName());
+                queryConfig.setIsDate(false);
+                queryConfigs.add(queryConfig);
+            }
+        }
+
+        // 构建查询条件
+        List<QueryCondition> conditions = buildQueryConditions(formReleaseConfig, params, columns);
+
+        // 执行分页查询
+        List<Map<String, Object>> pageResult = customFormDataMapper.selectFormDataList(
+                tableName,
+                fieldsList,
+                conditions
+        );
+
+        List<Entity> rData = new ArrayList<>();
+        for (Map<String, Object> item : pageResult) {
+            Entity entity = Entity.create();
+            for (String key : item.keySet()) {
+                entity.set(key, item.get(key));
+            }
+            //将所有查询的数据id 转string
+            entity.set(pkColumn.getName(), entity.get(pkColumn.getName()).toString());
+            rData.add(entity);
+        }
+
+        return rData;
+    }
 
     /**
      * 根据配置信息获取不分页列表数据
@@ -1707,7 +1807,6 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
             throw new MyException("主键不存在");
         }
 
-
         List<net.sf.jsqlparser.schema.Column> jsqlColumn = new ArrayList<>();
         for (String field : fieldsList) {
             jsqlColumn.add(new net.sf.jsqlparser.schema.Column(field));
@@ -1740,56 +1839,70 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
                 String endTime = MapUtil.get(params, fieldName + GlobalConstant.END_TIME_SUFFIX, String.class);
 
                 //如果全都没有数据 则跳过
-                if (startTime == null && endTime == null) {
-                    continue;
-                }
-                Expression startRightExp = null;
-                Expression endRightExp = null;
-                Column queryColumn = columns.stream().filter(c -> StrUtil.equalsIgnoreCase(c.getName(), fieldName)).findFirst().get();
-                JdbcType type = queryColumn.getTypeEnum();
-                if (type == JdbcType.TIME) {
-                    if (StrUtil.isNotEmpty(startTime)) startRightExp = new StringValue(startTime);
-                    if (StrUtil.isNotEmpty(endTime)) endRightExp = new StringValue(endTime);
-                } else if (type == JdbcType.DATE || type == JdbcType.TIMESTAMP) {
-                    if (StrUtil.isNotEmpty(startTime))
-                        startRightExp = new TimestampValue().withValue(Timestamp.valueOf(LocalDateTimeUtil.parseDateByLength(startTime)));
-                    if (StrUtil.isNotEmpty(endTime))
-                        endRightExp = new TimestampValue().withValue(Timestamp.valueOf(LocalDateTimeUtil.parseDateByLength(endTime)));
-                } else if (StrUtil.equalsIgnoreCase(queryColumn.getTypeName(), OracleFieldsType.TIME.getType())) {
-                    // oracle时间字段处理
-                    if (StrUtil.isNotEmpty(startTime))
-                        startRightExp = new StringValue(StringPool.ZERO + StringPool.SPACE + startTime);
-                    if (StrUtil.isNotEmpty(endTime))
-                        endRightExp = new StringValue(StringPool.ZERO + StringPool.SPACE + endTime);
-                }
-                if (startTime != null) {
-                    GreaterThanEquals geq = new GreaterThanEquals(); // ">="
-                    geq.setLeftExpression(new net.sf.jsqlparser.schema.Column(fieldName));
-                    geq.setRightExpression(startRightExp == null ? new StringValue(startTime) : startRightExp);
+                if (StringUtils.isNotEmpty(startTime) || StringUtils.isNotEmpty(endTime)) {
+                    Expression startRightExp = null;
+                    Expression endRightExp = null;
+                    Column queryColumn = columns.stream().filter(c -> StrUtil.equalsIgnoreCase(c.getName(), fieldName)).findFirst().get();
+                    JdbcType type = queryColumn.getTypeEnum();
+                    if (type == JdbcType.TIME) {
+                        if (StrUtil.isNotEmpty(startTime)) startRightExp = new StringValue(startTime);
+                        if (StrUtil.isNotEmpty(endTime)) endRightExp = new StringValue(endTime);
+                    } else if (type == JdbcType.DATE || type == JdbcType.TIMESTAMP) {
+                        if (StrUtil.isNotEmpty(startTime))
+                            startRightExp = new TimestampValue().withValue(Timestamp.valueOf(LocalDateTimeUtil.parseDateByLength(startTime)));
+                        if (StrUtil.isNotEmpty(endTime))
+                            endRightExp = new TimestampValue().withValue(Timestamp.valueOf(LocalDateTimeUtil.parseDateByLength(endTime)));
+                    } else if (StrUtil.equalsIgnoreCase(queryColumn.getTypeName(), OracleFieldsType.TIME.getType())) {
+                        // oracle时间字段处理
+                        if (StrUtil.isNotEmpty(startTime))
+                            startRightExp = new StringValue(StringPool.ZERO + StringPool.SPACE + startTime);
+                        if (StrUtil.isNotEmpty(endTime))
+                            endRightExp = new StringValue(StringPool.ZERO + StringPool.SPACE + endTime);
+                    }
+                    if (startTime != null) {
+                        GreaterThanEquals geq = new GreaterThanEquals(); // ">="
+                        geq.setLeftExpression(new net.sf.jsqlparser.schema.Column(fieldName));
+                        geq.setRightExpression(startRightExp == null ? new StringValue(startTime) : startRightExp);
 
-                    //如果是第一个条件 直接赋值
-                    if (ObjectUtil.isNull(queryExpression)) {
-                        queryExpression = geq;
-                    } else {
-                        queryExpression = new AndExpression(queryExpression, geq);
+                        //如果是第一个条件 直接赋值
+                        if (ObjectUtil.isNull(queryExpression)) {
+                            queryExpression = geq;
+                        } else {
+                            queryExpression = new AndExpression(queryExpression, geq);
+                        }
                     }
-                }
 
-                if (endTime != null) {
-                    MinorThanEquals leq = new MinorThanEquals();// "<="
-                    leq.setLeftExpression(new net.sf.jsqlparser.schema.Column(fieldName));
-                    leq.setRightExpression(endRightExp == null ? new StringValue(endTime) : endRightExp);
+                    if (endTime != null) {
+                        MinorThanEquals leq = new MinorThanEquals();// "<="
+                        leq.setLeftExpression(new net.sf.jsqlparser.schema.Column(fieldName));
+                        leq.setRightExpression(endRightExp == null ? new StringValue(endTime) : endRightExp);
+
+                        //如果是第一个条件 直接赋值
+                        if (ObjectUtil.isNull(queryExpression)) {
+                            queryExpression = leq;
+                        } else {
+                            queryExpression = new AndExpression(queryExpression, leq);
+                        }
+                    }
+                } else {
+                    Object value = MapUtil.get(params, fieldName, Object.class);
+                    //如果没有数据 则跳过
+                    if (value == null || StrUtil.isEmpty(String.valueOf(value))) {
+                        continue;
+                    }
+
+                    EqualsTo eq = new EqualsTo();
+                    eq.setLeftExpression(new net.sf.jsqlparser.schema.Column(fieldName));
+                    eq.setRightExpression(new StringValue(String.valueOf(value)));
 
                     //如果是第一个条件 直接赋值
                     if (ObjectUtil.isNull(queryExpression)) {
-                        queryExpression = leq;
+                        queryExpression = eq;
                     } else {
-                        queryExpression = new AndExpression(queryExpression, leq);
+                        queryExpression = new AndExpression(queryExpression, eq);
                     }
                 }
-
             } else {
-
                 Object value = MapUtil.get(params, fieldName, Object.class);
                 //如果没有数据 则跳过
                 if (value == null || StrUtil.isEmpty(String.valueOf(value))) {
@@ -1928,6 +2041,154 @@ public class FormExecuteServiceImpl implements IFormExecuteService {
         return pageOutput;
     }
 
+    @SneakyThrows
+    private PageOutput<Entity> getPageDataByParameterization(String tableName,
+                                                             List<String> fieldsList,
+                                                             FormReleaseConfig formReleaseConfig,
+                                                             Map<String, Object> params,
+                                                             IPage<Map<String, Object>> page
+    ) {
+        //获取表里所有字段
+        Table tableMeta = SqlRunnerAdapter.db().getTableMeta(tableName);
+        Collection<Column> columns = tableMeta.getColumns();
+
+        Optional<Column> pkOptional = columns.stream().filter(Column::isPk).findFirst();
+        Column pkColumn;
+
+        if (pkOptional.isPresent()) {
+            pkColumn = pkOptional.get();
+            fieldsList.add(0, pkColumn.getName());
+        } else {
+            throw new MyException("主键不存在");
+        }
+
+        List<QueryConfig> queryConfigs = formReleaseConfig.getListConfig().getQueryConfigs();
+
+        //如果有左侧树 需要把所选项目 where 条件加上
+        if (formReleaseConfig.getListConfig().getIsLeftMenu()) {
+            //如果已经包含此字段  就不添加了
+            if (queryConfigs.stream().noneMatch(x -> StrUtil.equals(x.getFieldName(), formReleaseConfig.getListConfig().getLeftMenuConfig().getListFieldName()))) {
+                QueryConfig queryConfig = new QueryConfig();
+                queryConfig.setFieldName(formReleaseConfig.getListConfig().getLeftMenuConfig().getListFieldName());
+                queryConfig.setIsDate(false);
+                queryConfigs.add(queryConfig);
+            }
+        }
+
+        // 构建查询条件
+        List<QueryCondition> conditions = buildQueryConditions(formReleaseConfig, params, columns);
+
+        // 执行分页查询
+        IPage<Map<String, Object>> pageResult = customFormDataMapper.selectFormDataPage(
+                page,
+                tableName,
+                fieldsList,
+                conditions
+        );
+
+        List<Entity> rData = new ArrayList<>();
+        for (Map<String, Object> item : pageResult.getRecords()) {
+            Entity entity = Entity.create();
+            for (String key : item.keySet()) {
+                entity.set(key, item.get(key));
+            }
+            //将所有查询的数据id 转string
+            entity.set(pkColumn.getName(), entity.get(pkColumn.getName()).toString());
+            rData.add(entity);
+        }
+
+        PageOutput<Entity> pageData = new PageOutput<>();
+        pageData.setPageSize((int) pageResult.getSize());
+        pageData.setCurrentPage((int) pageResult.getCurrent());
+        pageData.setTotal((int) pageResult.getTotal());
+        pageData.setList(rData);
+
+        return pageData;
+    }
+
+    private List<QueryCondition> buildQueryConditions(FormReleaseConfig formReleaseConfig,
+                                                      Map<String, Object> params, Collection<Column> columns) {
+        List<QueryCondition> conditions = new ArrayList<>();
+        int index = 0; // 初始化索引计数器
+
+        // 处理日期条件
+        for (QueryConfig queryConfig : formReleaseConfig.getListConfig().getQueryConfigs()) {
+            String fieldName = queryConfig.getFieldName();
+            if (queryConfig.getIsDate()) {
+                String startTime = MapUtil.get(params, fieldName + GlobalConstant.START_TIME_SUFFIX, String.class);
+                String endTime = MapUtil.get(params, fieldName + GlobalConstant.END_TIME_SUFFIX, String.class);
+
+                if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
+                    QueryCondition condition = new QueryCondition();
+                    condition.setFieldName(fieldName);
+                    condition.setValue(new Object[]{startTime, endTime});
+                    condition.setOperator("BETWEEN");
+                    condition.setDate(true);
+                    condition.setIndex(index++); // 设置索引并递增
+                    conditions.add(condition);
+                } else if (StringUtils.isNotEmpty(startTime)) {
+                    QueryCondition condition = new QueryCondition();
+                    condition.setFieldName(fieldName);
+                    condition.setValue(startTime);
+                    condition.setOperator(">=");
+                    condition.setDate(true);
+                    condition.setIndex(index++); // 设置索引并递增
+                    conditions.add(condition);
+                } else if (StringUtils.isNotEmpty(endTime)) {
+                    QueryCondition condition = new QueryCondition();
+                    condition.setFieldName(fieldName);
+                    condition.setValue(endTime);
+                    condition.setOperator("<=");
+                    condition.setDate(true);
+                    condition.setIndex(index++); // 设置索引并递增
+                    conditions.add(condition);
+                }
+            } else {
+                Object value = MapUtil.get(params, fieldName, Object.class);
+                if (value != null && StrUtil.isNotEmpty(String.valueOf(value))) {
+                    QueryCondition condition = new QueryCondition();
+                    condition.setFieldName(fieldName);
+
+                    // 根据字段类型决定操作符
+                    Optional<Column> column = columns.stream()
+                            .filter(c -> StrUtil.equalsIgnoreCase(c.getName(), fieldName))
+                            .findFirst();
+
+                    if (column.isPresent()) {
+                        String className = JdbcToJavaUtil.getClassName(column.get());
+                        if (LIKE_CLASS_NAME.contains(className)) {
+                            condition.setOperator("LIKE");
+                            condition.setValue("%" + value + "%");
+                        } else {
+                            condition.setOperator("=");
+                            condition.setValue(value);
+                        }
+                    } else {
+                        condition.setOperator("=");
+                        condition.setValue(value);
+                    }
+
+                    condition.setIndex(index++); // 设置索引并递增
+                    conditions.add(condition);
+                }
+            }
+        }
+
+        // 添加删除标记条件
+        if (columns.stream().anyMatch(c -> StrUtil.equalsIgnoreCase(GlobalConstant.DELETE_MARK, c.getName()))) {
+            QueryCondition condition = new QueryCondition();
+            condition.setFieldName(GlobalConstant.DELETE_MARK);
+            condition.setValue(DeleteMark.NODELETE.getCode());
+            condition.setOperator("=");
+            condition.setIndex(index++); // 设置索引并递增
+            conditions.add(condition);
+        }
+
+        // TODO 添加数据权限字段
+
+        return conditions;
+    }
+
     /**
      * 根据配置信息获取分页列表数据
      *

+ 37 - 0
src/main/java/com/xjrsoft/module/form/utils/FormDataSqlProvider.java

@@ -0,0 +1,37 @@
+package com.xjrsoft.module.form.utils;
+
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.xjrsoft.module.form.entity.QueryCondition;
+import org.apache.ibatis.jdbc.SQL;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class FormDataSqlProvider {
+
+    public String buildSelectSql(Map<String, Object> params) {
+        String tableName = (String) params.get("tableName");
+        List<String> fields = (List<String>) params.get("fields");
+        @SuppressWarnings("unchecked")
+        List<QueryCondition> conditions = (List<QueryCondition>) params.get("conditions");
+
+        SQL sql = new SQL();
+        sql.SELECT(String.join(", ", fields));
+        sql.FROM(tableName);
+
+        // 添加查询条件
+        if (conditions != null && !conditions.isEmpty()) {
+            for (int i = 0; i < conditions.size(); i++) {
+                QueryCondition condition = conditions.get(i);
+                if (i == 0) {
+                    sql.WHERE(condition.toSqlSnippet());
+                } else {
+                    sql.AND().WHERE(condition.toSqlSnippet());
+                }
+            }
+        }
+
+        return sql.toString();
+    }
+}

+ 7 - 0
src/main/java/com/xjrsoft/module/form/utils/FormDataTransUtil.java

@@ -191,6 +191,13 @@ public final class FormDataTransUtil {
                                     .filter(x -> ObjectUtil.isNotNull(x.get("value")))
                                     .collect(Collectors.toMap(data -> data.get("value").toString(), data -> data.get("label"), (e1, e2) -> e1)));
                         }
+                        if(options.containsKey("multiple") && "multiple".equals(options.get("multiple").toString())){
+                            Map<String, String> multiSettingMap = new HashMap<>();
+                            for (Map<String, Object> objectMap : apiDataList) {
+                                multiSettingMap.put(objectMap.get(options.get("valueField").toString()).toString(), objectMap.get(options.get("labelField").toString()).toString());
+                            }
+                            multiFieldMap.put(bindField, multiSettingMap);
+                        }
                     }
                     fieldValuesMap.put(bindField, apiDataMap.get(apiId));
                 }

+ 5 - 0
src/main/java/com/xjrsoft/module/generator/entity/ListConfig.java

@@ -29,6 +29,11 @@ public class ListConfig {
      */
     private Integer pageSize;
 
+    /**
+     * 导入模版url
+     */
+    private String importTemplateUrl;
+
     /**
      * 导入模版名称
      */

Some files were not shown because too many files changed in this diff