diff --git a/backend/ruoyi-common/ruoyi-common-excel/pom.xml b/backend/ruoyi-common/ruoyi-common-excel/pom.xml index 47ba5284..11c5477c 100644 --- a/backend/ruoyi-common/ruoyi-common-excel/pom.xml +++ b/backend/ruoyi-common/ruoyi-common-excel/pom.xml @@ -25,6 +25,12 @@ cn.idev.excel fastexcel + + + + org.springframework.boot + spring-boot-starter-jdbc + diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelSqlCacheFormat.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelSqlCacheFormat.java new file mode 100644 index 00000000..7a932900 --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelSqlCacheFormat.java @@ -0,0 +1,44 @@ +package org.dromara.common.excel.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * SQL缓存格式化注解 + * 用于配置SQL查询来加载数据到缓存进行匹配 + * + * @author Lion Li + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelSqlCacheFormat { + + /** + * SQL缓存键,用于标识不同的SQL查询配置 + */ + String sqlKey() default ""; + + /** + * SQL查询语句 + * 支持动态SQL,可以使用参数占位符 + */ + String sql() default ""; + + /** + * 值字段名(用于匹配的字段) + */ + String valueColumn() default "id"; + + /** + * 标签字段名(用于显示的字段) + */ + String labelColumn() default "name"; + + /** + * 分隔符 + */ + String separator() default ","; + +} diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/config/SqlCacheConfigInitializer.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/config/SqlCacheConfigInitializer.java new file mode 100644 index 00000000..2f2ff099 --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/config/SqlCacheConfigInitializer.java @@ -0,0 +1,78 @@ +package org.dromara.common.excel.config; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.excel.service.SqlCacheConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * SQL缓存配置初始化器 + * 在应用启动时注册SQL配置 + * + * @author Lion Li + */ +@Slf4j +@Component +public class SqlCacheConfigInitializer implements CommandLineRunner { + + @Autowired + private SqlCacheConfigService sqlCacheConfigService; + + @Override + public void run(String... args) throws Exception { + log.info("开始初始化SQL缓存配置..."); + + // 注册默认的SQL配置 + registerDefaultSqlConfigs(); + + log.info("SQL缓存配置初始化完成"); + } + + /** + * 注册默认的SQL配置 + */ + private void registerDefaultSqlConfigs() { + Map configs = new HashMap<>(); + + // 示例:学生班级信息查询 + // configs.put("student_class_info", new SqlCacheConfigService.SqlCacheConfig( + // "SELECT class_id as id, class_name as name FROM xg_class WHERE deleted = 0", + // "id", + // "name")); + + // 示例:学院信息查询 + // configs.put("college_info", new SqlCacheConfigService.SqlCacheConfig( + // "SELECT college_id as id, college_name as name FROM xg_college WHERE deleted + // = 0", + // "id", + // "name")); + + // 示例:专业信息查询 + // configs.put("major_info", new SqlCacheConfigService.SqlCacheConfig( + // "SELECT major_id as id, major_name as name FROM xg_major WHERE deleted = 0", + // "id", + // "name")); + + // 示例:班主任信息查询 + // configs.put("class_teacher_info", new SqlCacheConfigService.SqlCacheConfig( + // "SELECT user_id as id, nick_name as name FROM sys_user WHERE deleted = 0 AND + // user_type = '00'", + // "id", + // "name")); + + // 楼栋信息 + configs.put("xg_dorm_building", new SqlCacheConfigService.SqlCacheConfig( + "SELECT id as id, building_name as name FROM xg_dorm_building", + "id", + "name")); + + // 批量注册配置 + sqlCacheConfigService.registerSqlConfigs(configs); + + log.info("注册了 {} 个默认SQL配置", configs.size()); + } +} diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictPreloadConvert.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictPreloadConvert.java new file mode 100644 index 00000000..386379a3 --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictPreloadConvert.java @@ -0,0 +1,150 @@ +package org.dromara.common.excel.convert; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.ReadCellData; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.core.service.DictService; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.excel.utils.ExcelUtil; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 高性能字典格式化转换处理 - 预加载字典数据到内存缓存 + * + * @author Lion Li + */ +@Slf4j +public class ExcelDictPreloadConvert implements Converter { + + // 静态字典缓存,避免重复加载 + private static final Map> DICT_CACHE = new ConcurrentHashMap<>(); + + @Override + public Class supportJavaTypeKey() { + return Object.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + ExcelDictFormat anno = getAnnotation(contentProperty.getField()); + String type = anno.dictType(); + String label = cellData.getStringValue(); + String value; + if (StringUtils.isBlank(type)) { + value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator()); + } else { + value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator()); + } + return Convert.convert(contentProperty.getField().getType(), value); + } + + @Override + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNull(object)) { + return new WriteCellData<>(""); + } + + ExcelDictFormat anno = getAnnotation(contentProperty.getField()); + String dictType = anno.dictType(); + String value = Convert.toStr(object); + + if (StringUtils.isBlank(dictType)) { + // 使用表达式转换 + String label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator()); + return new WriteCellData<>(label); + } else { + // 使用预加载的字典缓存 + String label = getDictLabelFromCache(dictType, value, anno.separator()); + return new WriteCellData<>(label); + } + } + + /** + * 预加载指定字典类型的所有数据 + */ + public static void preloadDict(String dictType) { + if (!DICT_CACHE.containsKey(dictType)) { + try { + DictService dictService = SpringUtils.getBean(DictService.class); + Map dictMap = dictService.getAllDictByDictType(dictType); + DICT_CACHE.put(dictType, dictMap); + log.info("预加载字典类型: {}, 数据量: {}", dictType, dictMap.size()); + } catch (Exception e) { + log.error("预加载字典失败: {}", dictType, e); + } + } + } + + /** + * 批量预加载多个字典类型 + */ + public static void preloadDicts(String... dictTypes) { + for (String dictType : dictTypes) { + preloadDict(dictType); + } + } + + /** + * 从缓存获取字典标签 + */ + private String getDictLabelFromCache(String dictType, String value, String separator) { + Map dictMap = DICT_CACHE.get(dictType); + if (dictMap == null) { + // 缓存未命中,实时加载 + preloadDict(dictType); + dictMap = DICT_CACHE.get(dictType); + } + + final Map finalDictMap = dictMap; + if (StringUtils.containsAny(value, separator)) { + return Arrays.stream(value.split(separator)) + .map(v -> finalDictMap.getOrDefault(v, v)) + .collect(Collectors.joining(separator)); + } else { + return finalDictMap.getOrDefault(value, value); + } + } + + /** + * 清理缓存 + */ + public static void clearCache() { + DICT_CACHE.clear(); + log.info("字典缓存已清理"); + } + + /** + * 获取缓存统计信息 + */ + public static Map getCacheStats() { + return DICT_CACHE.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().size())); + } + + private ExcelDictFormat getAnnotation(Field field) { + return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class); + } +} diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelSqlCacheConvert.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelSqlCacheConvert.java new file mode 100644 index 00000000..d8983059 --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelSqlCacheConvert.java @@ -0,0 +1,200 @@ +package org.dromara.common.excel.convert; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.ReadCellData; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.dromara.common.excel.annotation.ExcelSqlCacheFormat; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.excel.service.SqlCacheConfigService; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * SQL缓存格式化转换处理 - 支持自定义SQL语句加载数据到缓存 + * + * @author Lion Li + */ +@Slf4j +public class ExcelSqlCacheConvert implements Converter { + + // 静态SQL缓存,避免重复加载 + private static final Map> SQL_CACHE = new ConcurrentHashMap<>(); + + @Override + public Class supportJavaTypeKey() { + return Object.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + ExcelSqlCacheFormat anno = getAnnotation(contentProperty.getField()); + String sqlKey = anno.sqlKey(); + String label = cellData.getStringValue(); + String value; + + if (StringUtils.isBlank(sqlKey)) { + value = label; // 如果没有配置SQL,直接返回标签 + } else { + value = getValueFromCache(sqlKey, label, anno.valueColumn(), anno.labelColumn()); + } + return Convert.convert(contentProperty.getField().getType(), value); + } + + @Override + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNull(object)) { + return new WriteCellData<>(""); + } + + ExcelSqlCacheFormat anno = getAnnotation(contentProperty.getField()); + String sqlKey = anno.sqlKey(); + String value = Convert.toStr(object); + + if (StringUtils.isBlank(sqlKey)) { + return new WriteCellData<>(value); + } else { + String label = getLabelFromCache(sqlKey, value, anno.valueColumn(), anno.labelColumn()); + return new WriteCellData<>(label); + } + } + + /** + * 预加载指定SQL查询的数据 + */ + public static void preloadSqlData(String sqlKey, String sql, String valueColumn, String labelColumn) { + if (!SQL_CACHE.containsKey(sqlKey)) { + try { + // 这里可以通过配置获取对应的Mapper来执行SQL + // 暂时使用通用的方式,实际使用时可以根据sqlKey配置对应的Mapper + Map dataMap = executeSqlAndBuildMap(sql, valueColumn, labelColumn); + SQL_CACHE.put(sqlKey, dataMap); + log.info("预加载SQL数据: {}, 数据量: {}", sqlKey, dataMap.size()); + } catch (Exception e) { + log.error("预加载SQL数据失败: {}", sqlKey, e); + } + } + } + + /** + * 批量预加载多个SQL查询 + */ + public static void preloadSqlDataBatch(Map sqlConfigs) { + for (Map.Entry entry : sqlConfigs.entrySet()) { + SqlCacheConfig config = entry.getValue(); + preloadSqlData(entry.getKey(), config.getSql(), config.getValueColumn(), config.getLabelColumn()); + } + } + + /** + * 从缓存获取标签 + */ + private String getLabelFromCache(String sqlKey, String value, String valueColumn, String labelColumn) { + Map dataMap = SQL_CACHE.get(sqlKey); + if (dataMap == null) { + log.warn("SQL缓存未找到: {}", sqlKey); + return value; + } + return dataMap.getOrDefault(value, value); + } + + /** + * 从缓存获取值 + */ + private String getValueFromCache(String sqlKey, String label, String valueColumn, String labelColumn) { + Map dataMap = SQL_CACHE.get(sqlKey); + if (dataMap == null) { + log.warn("SQL缓存未找到: {}", sqlKey); + return label; + } + + // 反向查找:通过标签找值 + for (Map.Entry entry : dataMap.entrySet()) { + if (entry.getValue().equals(label)) { + return entry.getKey(); + } + } + return label; + } + + /** + * 执行SQL并构建映射关系 + */ + private static Map executeSqlAndBuildMap(String sql, String valueColumn, String labelColumn) { + try { + // 使用配置服务来执行SQL + SqlCacheConfigService configService = SpringUtils.getBean(SqlCacheConfigService.class); + return configService.executeSqlAndBuildMap(sql, valueColumn, labelColumn); + } catch (Exception e) { + log.error("执行SQL失败: {}", sql, e); + return new ConcurrentHashMap<>(); + } + } + + /** + * 清理缓存 + */ + public static void clearCache() { + SQL_CACHE.clear(); + log.info("SQL缓存已清理"); + } + + /** + * 获取缓存统计信息 + */ + public static Map getCacheStats() { + return SQL_CACHE.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().size())); + } + + private ExcelSqlCacheFormat getAnnotation(Field field) { + return AnnotationUtil.getAnnotation(field, ExcelSqlCacheFormat.class); + } + + /** + * SQL缓存配置类 + */ + public static class SqlCacheConfig { + private String sql; + private String valueColumn; + private String labelColumn; + + public SqlCacheConfig(String sql, String valueColumn, String labelColumn) { + this.sql = sql; + this.valueColumn = valueColumn; + this.labelColumn = labelColumn; + } + + public String getSql() { + return sql; + } + + public String getValueColumn() { + return valueColumn; + } + + public String getLabelColumn() { + return labelColumn; + } + } +} diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/BaseExportService.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/BaseExportService.java new file mode 100644 index 00000000..ee65fa9c --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/BaseExportService.java @@ -0,0 +1,87 @@ +package org.dromara.common.excel.service; + +import cn.hutool.core.collection.CollUtil; +import org.dromara.common.core.utils.StringUtils; +import cn.hutool.core.util.ReflectUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictPreloadConvert; + +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +/** + * 高性能导出服务基类 + * 提供字典预加载功能,优化导出性能 + * + * @author Lion Li + */ +@Slf4j +public abstract class BaseExportService { + + /** + * 预加载导出所需的字典数据 + */ + protected void preloadExportDicts() { + // 获取导出VO类中所有字典字段 + Set dictTypes = getExportDictTypes(); + if (!dictTypes.isEmpty()) { + ExcelDictPreloadConvert.preloadDicts(dictTypes.toArray(new String[0])); + log.info("预加载导出字典完成,字典类型: {}", dictTypes); + } + } + + /** + * 获取导出VO类中的字典类型 + * 子类可以重写此方法来自定义字典类型 + */ + protected Set getExportDictTypes() { + Set dictTypes = new HashSet<>(); + // 通过反射获取VO类中的@ExcelDictFormat注解 + // 这里可以根据具体需求实现 + return dictTypes; + } + + /** + * 根据VO类获取字典类型 + */ + protected Set getDictTypesFromVoClass(Class voClass) { + Set dictTypes = new HashSet<>(); + if (voClass != null) { + Field[] fields = ReflectUtil.getFields(voClass); + for (Field field : fields) { + ExcelDictFormat annotation = field.getAnnotation(ExcelDictFormat.class); + if (annotation != null && StringUtils.isNotBlank(annotation.dictType())) { + dictTypes.add(annotation.dictType()); + } + } + } + return dictTypes; + } + + /** + * 执行导出前准备 + */ + protected void beforeExport() { + preloadExportDicts(); + } + + /** + * 执行导出后清理 + */ + protected void afterExport() { + // 可选:清理缓存 + // ExcelDictPreloadConvert.clearCache(); + } + + /** + * 获取缓存统计信息 + */ + protected void logCacheStats() { + var stats = ExcelDictPreloadConvert.getCacheStats(); + if (!stats.isEmpty()) { + log.info("字典缓存统计: {}", stats); + } + } +} diff --git a/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/SqlCacheConfigService.java b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/SqlCacheConfigService.java new file mode 100644 index 00000000..f73b83ba --- /dev/null +++ b/backend/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/service/SqlCacheConfigService.java @@ -0,0 +1,146 @@ +package org.dromara.common.excel.service; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.excel.convert.ExcelSqlCacheConvert; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * SQL缓存配置服务 + * 用于管理SQL查询配置和执行 + * + * @author Lion Li + */ +@Slf4j +@Service +public class SqlCacheConfigService { + + // SQL配置缓存 + private static final Map SQL_CONFIGS = new ConcurrentHashMap<>(); + + /** + * 注册SQL配置 + */ + public void registerSqlConfig(String sqlKey, String sql, String valueColumn, String labelColumn) { + SQL_CONFIGS.put(sqlKey, new SqlCacheConfig(sql, valueColumn, labelColumn)); + log.info("注册SQL配置: {} -> {}", sqlKey, sql); + } + + /** + * 批量注册SQL配置 + */ + public void registerSqlConfigs(Map configs) { + SQL_CONFIGS.putAll(configs); + log.info("批量注册SQL配置: {} 个", configs.size()); + } + + /** + * 预加载指定SQL键的数据 + */ + public void preloadSqlData(String sqlKey) { + SqlCacheConfig config = SQL_CONFIGS.get(sqlKey); + if (config != null) { + ExcelSqlCacheConvert.preloadSqlData(sqlKey, config.getSql(), config.getValueColumn(), + config.getLabelColumn()); + } else { + log.warn("未找到SQL配置: {}", sqlKey); + } + } + + /** + * 批量预加载所有SQL数据 + */ + public void preloadAllSqlData() { + for (String sqlKey : SQL_CONFIGS.keySet()) { + preloadSqlData(sqlKey); + } + } + + /** + * 执行SQL并构建映射关系 + */ + public Map executeSqlAndBuildMap(String sql, String valueColumn, String labelColumn) { + try { + JdbcTemplate jdbcTemplate = SpringUtils.getBean(JdbcTemplate.class); + List> results = jdbcTemplate.queryForList(sql); + + return results.stream() + .collect(Collectors.toMap( + row -> String.valueOf(row.get(valueColumn)), + row -> String.valueOf(row.get(labelColumn)), + (existing, replacement) -> existing // 如果有重复键,保留第一个 + )); + } catch (Exception e) { + log.error("执行SQL失败: {}", sql, e); + return new ConcurrentHashMap<>(); + } + } + + /** + * 清理所有缓存 + */ + public void clearAllCache() { + ExcelSqlCacheConvert.clearCache(); + log.info("所有SQL缓存已清理"); + } + + /** + * 获取缓存统计信息 + */ + public Map getCacheStats() { + return ExcelSqlCacheConvert.getCacheStats(); + } + + /** + * 获取SQL配置 + */ + public SqlCacheConfig getSqlConfig(String sqlKey) { + return SQL_CONFIGS.get(sqlKey); + } + + /** + * 获取所有SQL配置 + */ + public Map getAllSqlConfigs() { + return new ConcurrentHashMap<>(SQL_CONFIGS); + } + + /** + * SQL缓存配置类 + */ + public static class SqlCacheConfig { + private final String sql; + private final String valueColumn; + private final String labelColumn; + + public SqlCacheConfig(String sql, String valueColumn, String labelColumn) { + this.sql = sql; + this.valueColumn = valueColumn; + this.labelColumn = labelColumn; + } + + public String getSql() { + return sql; + } + + public String getValueColumn() { + return valueColumn; + } + + public String getLabelColumn() { + return labelColumn; + } + + @Override + public String toString() { + return String.format("SqlCacheConfig{sql='%s', valueColumn='%s', labelColumn='%s'}", + sql, valueColumn, labelColumn); + } + } +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java index f854be9a..141716ab 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java @@ -2,8 +2,10 @@ package org.dromara.xg.controller; import java.util.List; import java.util.Map; +import java.util.HashMap; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; @@ -19,6 +21,11 @@ import org.dromara.common.core.validate.EditGroup; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.core.utils.StringUtils; +import org.dromara.xg.domain.vo.XgStudentMsgExportVo; +import org.dromara.common.excel.service.BaseExportService; +import org.dromara.common.excel.convert.ExcelDictPreloadConvert; +import org.dromara.common.excel.service.SqlCacheConfigService; +import org.dromara.common.core.utils.SpringUtils; import org.dromara.xg.domain.vo.XgStudentMsgVo; import org.dromara.xg.domain.bo.XgStudentMsgBo; import org.dromara.xg.service.IXgStudentMsgService; @@ -38,6 +45,7 @@ import org.dromara.system.domain.bo.SysUserBo; @RequiredArgsConstructor @RestController @RequestMapping("/studentMsg/studentMsg") +@Slf4j public class XgStudentMsgController extends BaseController { private final IXgStudentMsgService xgStudentMsgService; @@ -87,7 +95,18 @@ public class XgStudentMsgController extends BaseController { } // 提取部门ID参数 - Map deptParams = Map.of("dept_id", requestBody.get("dept_id")); + Map deptParams = new HashMap<>(); + // 支持多种参数名称:deptId(驼峰)和 dept_id(下划线) + Object deptIdValue = null; + if (requestBody.containsKey("deptId") && requestBody.get("deptId") != null) { + deptIdValue = requestBody.get("deptId"); + } else if (requestBody.containsKey("dept_id") && requestBody.get("dept_id") != null) { + deptIdValue = requestBody.get("dept_id"); + } + + if (deptIdValue != null) { + deptParams.put("dept_id", deptIdValue); + } return xgStudentMsgService.queryPageListByDeptId(bo, deptParams, pageQuery); } @@ -98,9 +117,116 @@ public class XgStudentMsgController extends BaseController { @SaCheckPermission("studentMsg:studentMsg:export") @Log(title = "学生信息", businessType = BusinessType.EXPORT) @PostMapping("/export") - public void export(XgStudentMsgBo bo, HttpServletResponse response) { - List list = xgStudentMsgService.queryList(bo); - ExcelUtil.exportExcel(list, "学生信息", XgStudentMsgVo.class, response); + public void export(@RequestParam Map requestBody, HttpServletResponse response) { + // 预加载导出所需的字典数据 + preloadExportDicts(); + + // 从请求参数中解析查询条件和部门ID + XgStudentMsgBo bo = new XgStudentMsgBo(); + + // 设置基础查询条件 + if (requestBody.containsKey("name")) { + bo.setName((String) requestBody.get("name")); + } + if (requestBody.containsKey("studentNo")) { + bo.setStudentNo((String) requestBody.get("studentNo")); + } + if (requestBody.containsKey("phone")) { + bo.setPhone((String) requestBody.get("phone")); + } + if (requestBody.containsKey("studentStatus")) { + bo.setStudentStatus((String) requestBody.get("studentStatus")); + } + + // 设置时间范围查询条件 + Map params = bo.getParams(); + if (requestBody.containsKey("beginTime")) { + params.put("beginTime", requestBody.get("beginTime")); + } + if (requestBody.containsKey("endTime")) { + params.put("endTime", requestBody.get("endTime")); + } + + // 提取部门ID参数 + Map deptParams = new HashMap<>(); + // 支持多种参数名称:deptId(驼峰)和 dept_id(下划线) + Object deptIdValue = null; + if (requestBody.containsKey("deptId") && requestBody.get("deptId") != null) { + deptIdValue = requestBody.get("deptId"); + } else if (requestBody.containsKey("dept_id") && requestBody.get("dept_id") != null) { + deptIdValue = requestBody.get("dept_id"); + } + + if (deptIdValue != null) { + deptParams.put("dept_id", deptIdValue); + } + + // 添加调试日志 + log.info("export方法 - requestBody: {}", requestBody); + log.info("export方法 - deptParams: {}", deptParams); + + List list = xgStudentMsgService.queryPageListExportByDeptId(bo, deptParams); + ExcelUtil.exportExcel(list, "学生信息", XgStudentMsgExportVo.class, response); + + // 导出完成后记录缓存统计 + logCacheStats(); + } + + /** + * 预加载导出所需的字典数据 + */ + private void preloadExportDicts() { + // 预加载学生信息导出中使用的所有字典类型 + ExcelDictPreloadConvert.preloadDicts( + "sys_user_sex", // 性别 + "xg_nation", // 民族 + "sys_region", // 行政区划 + "xg_political_status", // 政治面貌 + "sys_yesno", // 是否选项 + "wenhuachengdu", // 文化程度 + "house_hold_register_type", // 户口类型 + "marital_status", // 婚姻状况 + "xg_family_economic", // 家庭经济状况 + "xg_blood_type", // 血型 + "disability_type", // 残疾类型 + "admission_category", // 录取类别 + "student_status", // 学籍状态 + "zsjy_education_level", // 学历层次 + "xg_training_mode" // 培养方式 + ); + log.info("学生信息导出字典预加载完成"); + + // 预加载SQL缓存数据 + preloadExportSqlData(); + } + + /** + * 预加载导出所需的SQL缓存数据 + */ + private void preloadExportSqlData() { + try { + SqlCacheConfigService sqlCacheConfigService = SpringUtils.getBean(SqlCacheConfigService.class); + + // 预加载学生信息导出中使用的SQL配置 + // sqlCacheConfigService.preloadSqlData("student_class_info"); // 班级信息 + // sqlCacheConfigService.preloadSqlData("college_info"); // 学院信息 + // sqlCacheConfigService.preloadSqlData("major_info"); // 专业信息 + // sqlCacheConfigService.preloadSqlData("class_teacher_info"); // 班主任信息 + sqlCacheConfigService.preloadSqlData("xg_dorm_building"); + log.info("学生信息导出SQL缓存预加载完成"); + } catch (Exception e) { + log.warn("SQL缓存预加载失败,将使用默认处理方式", e); + } + } + + /** + * 记录缓存统计信息 + */ + private void logCacheStats() { + var stats = ExcelDictPreloadConvert.getCacheStats(); + if (!stats.isEmpty()) { + log.info("学生信息导出字典缓存统计: {}", stats); + } } /** diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgStudentMsgExportVo.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgStudentMsgExportVo.java new file mode 100644 index 00000000..6b675970 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgStudentMsgExportVo.java @@ -0,0 +1,679 @@ +package org.dromara.xg.domain.vo; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.dromara.xg.domain.XgStudentMsg; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.annotation.ExcelSqlCacheFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.common.excel.convert.ExcelDictPreloadConvert; +import org.dromara.common.excel.convert.ExcelSqlCacheConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 学生信息视图对象 xg_student_msg + * + * @author zlwu + * @date 2025-07-24 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = XgStudentMsg.class) +public class XgStudentMsgExportVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID(雪花ID) + */ + @ExcelProperty(value = "主键ID") + private Long id; + + /** + * 删除标志(0代表存在 1代表删除) + */ + // @ExcelProperty(value = "删除标志") + // private Long deleted; + + /** + * 创建者 + */ + // @ExcelProperty(value = "创建者") + // private Long createBy; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 更新者 + */ + // @ExcelProperty(value = "更新者") + // private Long updateBy; + + /** + * 更新时间 + */ + @ExcelProperty(value = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** + * 学号 + */ + @ExcelProperty(value = "学号") + private String studentNo; + + /** + * 身份证号 + */ + @ExcelProperty(value = "身份证号") + private String idCard; + + /** + * 姓名 + */ + @ExcelProperty(value = "姓名") + private String name; + + /** + * 英文姓名 + */ + @ExcelProperty(value = "英文姓名") + private String nameEnglish; + + /** + * 曾用名 + */ + @ExcelProperty(value = "曾用名") + private String formerName; + + /** + * 性别:0-男,1-女 + */ + @ExcelProperty(value = "性别", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_user_sex") + private String gender; + + /** + * 出生日期 + */ + @ExcelProperty(value = "出生日期") + private Date birthDate; + + /** + * 民族 + */ + @ExcelProperty(value = "民族", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xg_nation") + private String nationality; + + /** + * 籍贯省 + * todo + */ + @ExcelProperty(value = "籍贯省", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String nativePlaceProvice; + + /** + * 籍贯市 + * todo + */ + @ExcelProperty(value = "籍贯市", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String nativePlaceCity; + + /** + * 籍贯区 + * todo + */ + @ExcelProperty(value = "籍贯区", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String nativePlaceTown; + + /** + * 政治面貌 + */ + @ExcelProperty(value = "政治面貌", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xg_political_status") + private String politicalStatus; + + /** + * 户籍所在地 + */ + @ExcelProperty(value = "户籍所在地") + private String hukouLocation; + + /** + * 家庭地址 + */ + @ExcelProperty(value = "家庭地址") + private String homeAddress; + + /** + * 现住址 + */ + @ExcelProperty(value = "现住址") + private String currentAddress; + + /** + * 邮政编码 + */ + @ExcelProperty(value = "邮政编码") + private String postalCode; + + /** + * 照片URL + */ + // @ExcelProperty(value = "照片URL") + private String photoUrl; + + /** + * 学生照片存储路径 + */ + // @ExcelProperty(value = "学生照片存储路径") + private String photoPath; + + /** + * 手机号码 + */ + @ExcelProperty(value = "手机号码") + private String phone; + + /** + * 是否住校:0-否,1-是 + */ + @ExcelProperty(value = "是否住校", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isBoarder; + + /** + * 文化程度 + */ + @ExcelProperty(value = "文化程度", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "wenhuachengdu") + private String educationLevel; + + /** + * 户口类型:农业、非农业 + */ + @ExcelProperty(value = "户口类型", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "house_hold_register_type") + private String householdRegisterType; + + /** + * 宗教信仰 + */ + @ExcelProperty(value = "宗教信仰") + private String religion; + + /** + * 生源地区(省市县) + * todo + */ + @ExcelProperty(value = "生源地区(省)", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String sourceRegionProvince; + + /** + * 生源地区(省市县) + * todo + */ + @ExcelProperty(value = "生源地区(市)", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String sourceRegionCity; + + /** + * 生源地区(省市县) + * todo + */ + @ExcelProperty(value = "生源地区(县)", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_region") + private String sourceRegionTown; + + /** + * 毕业院校 + */ + @ExcelProperty(value = "毕业院校") + private String graduateSchool; + + /** + * 电子邮箱 + */ + @ExcelProperty(value = "电子邮箱") + private String email; + + /** + * QQ号码 + */ + @ExcelProperty(value = "QQ号码") + private String qq; + + /** + * 微信号 + */ + @ExcelProperty(value = "微信号") + private String wechat; + + /** + * 婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶 + */ + @ExcelProperty(value = "婚姻状况", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "marital_status") + private String maritalStatus; + + /** + * 紧急联系人姓名 + */ + @ExcelProperty(value = "紧急联系人姓名") + private String emergencyContactName; + + /** + * 紧急联系人电话 + */ + @ExcelProperty(value = "紧急联系人电话") + private String emergencyContactPhone; + + /** + * 紧急联系人关系 + */ + @ExcelProperty(value = "紧急联系人关系") + private String emergencyContactRelation; + + /** + * 是否贫困生:0-否,1-是 + */ + @ExcelProperty(value = "是否贫困生", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isPoorStudent; + + /** + * 是否少数民族:0-否,1-是 + */ + @ExcelProperty(value = "是否少数民族", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isMinority; + + /** + * 是否残疾:0-否,1-是 + */ + @ExcelProperty(value = "是否残疾", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isDisabled; + + /** + * 是否孤儿:0-否,1-是 + */ + @ExcelProperty(value = "是否孤儿", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isOrphan; + + /** + * 是否留守儿童:0-否,1-是 + */ + @ExcelProperty(value = "是否留守儿童", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isLeftBehindChild; + + /** + * 是否独生子女:0-否,1-是 + */ + @ExcelProperty(value = "是否独生子女", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isSingleChild; + + /** + * 是否低保:0-否,1-是 + */ + @ExcelProperty(value = "是否低保", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long isLowIncome; + + /** + * 是否有助学贷款:0-否,1-是 + */ + @ExcelProperty(value = "是否有助学贷款", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "sys_yesno") + private Long hasLoan; + + /** + * 助学贷款金额 + */ + @ExcelProperty(value = "助学贷款金额(元)") + private Double loanAmount; + + /** + * 特长爱好 + */ + @ExcelProperty(value = "特长爱好") + private String specialties; + + /** + * 获奖情况 + */ + @ExcelProperty(value = "获奖情况") + private String awards; + + /** + * 违纪记录 + */ + @ExcelProperty(value = "违纪记录") + private String violations; + + /** + * 社会活动 + */ + @ExcelProperty(value = "社会活动") + private String socialActivities; + + /** + * 父亲姓名 + */ + @ExcelProperty(value = "父亲姓名") + private String fatherName; + + /** + * 父亲电话 + */ + @ExcelProperty(value = "父亲电话") + private String fatherPhone; + + /** + * 父亲工作单位 + */ + @ExcelProperty(value = "父亲工作单位") + private String fatherWorkUnit; + + /** + * 母亲姓名 + */ + @ExcelProperty(value = "母亲姓名") + private String motherName; + + /** + * 母亲电话 + */ + @ExcelProperty(value = "母亲电话") + private String motherPhone; + + /** + * 母亲工作单位 + */ + @ExcelProperty(value = "母亲工作单位") + private String motherWorkUnit; + + /** + * 监护人姓名 + */ + @ExcelProperty(value = "监护人姓名") + private String guardianName; + + /** + * 监护人电话 + */ + @ExcelProperty(value = "监护人电话") + private String guardianPhone; + + /** + * 监护人关系 + */ + @ExcelProperty(value = "监护人关系") + private String guardianRelation; + + /** + * 家庭年收入 + */ + @ExcelProperty(value = "家庭年收入") + private Double familyIncome; + + /** + * 人均收入 + */ + @ExcelProperty(value = "人均收入") + private Double perCapitaIncome; + + /** + * 收入来源 + */ + @ExcelProperty(value = "收入来源") + private String incomeSource; + + /** + * 家庭经济状况:富裕、一般、困难、特困 + */ + @ExcelProperty(value = "家庭经济状况", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xg_family_economic") + private String familyEconomicStatus; + + /** + * 家庭成员数量 + */ + @ExcelProperty(value = "家庭成员数量") + private Long familyMembers; + + /** + * 身高(cm) + */ + @ExcelProperty(value = "身高(CM)") + private Double height; + + /** + * 体重(kg) + */ + @ExcelProperty(value = "体重(KG)") + private Double weight; + + /** + * 血型 + */ + @ExcelProperty(value = "血型", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xg_blood_type") + private String bloodType; + + /** + * 健康状况 + */ + @ExcelProperty(value = "健康状况") + private String healthStatus; + + /** + * 特殊体质或疾病 + */ + @ExcelProperty(value = "特殊体质或疾病") + private String specialCondition; + + /** + * 病史 + */ + @ExcelProperty(value = "病史") + private String medicalHistory; + + /** + * 过敏史 + */ + @ExcelProperty(value = "过敏史") + private String allergies; + + /** + * 残疾类型 1 - 视力残疾 2 - 听力残疾 3 - 智力残疾 9 - 其他残疾 + */ + @ExcelProperty(value = "残疾类型", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "disability_type") + private String disabilityType; + + /** + * 残疾等级 + */ + @ExcelProperty(value = "残疾等级") + private String disabilityLevel; + + /** + * 录取类别:统招、自主招生、专项计划等 + */ + @ExcelProperty(value = "录取类别", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "admission_category") + private String admissionCategory; + + /** + * 学籍状态:1-在籍,2-休学,3-复学,4-退学,5-毕业 + */ + @ExcelProperty(value = "学籍状态", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "student_status") + private String studentStatus; + + /** + * 入学年份 + */ + @ExcelProperty(value = "入学年份") + private Long enrollmentYear; + + /** + * 入学日期 + */ + @ExcelProperty(value = "入学日期") + private Date enrollmentDate; + + /** + * 银行卡号 + */ + @ExcelProperty(value = "银行卡号") + private String bankCardNo; + + /** + * 开户银行 + */ + @ExcelProperty(value = "开户银行") + private String bankName; + + /** + * 开户支行 + */ + @ExcelProperty(value = "开户支行") + private String bankBranch; + + /** + * 持卡人姓名 + */ + @ExcelProperty(value = "持卡人姓名") + private String cardHolderName; + + /** + * 信息状态:1-正常,2-待审核,3-审核中,4-已驳回,5-已锁定 + */ + @ExcelProperty(value = "信息状态", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "info_status") + private String infoStatus; + + /** + * 数据来源:manual-手工录入,import-批量导入,sync-系统同步 + */ + @ExcelProperty(value = "数据来源", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xs_data_source") + private String dataSource; + + /** + * 学制(年)- 预留,数据从班级表关联 + */ + @ExcelProperty(value = "学制(年)") + private Long schoolSystem; + + /** + * 学历层次 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "学历层次", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "zsjy_education_level") + private String academicLevel; + + /** + * 培养方式:全日制、在职、函授、夜大等 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "培养方式", converter = ExcelDictPreloadConvert.class) + @ExcelDictFormat(dictType = "xg_training_mode") + private String trainingType; + + /** + * 专业id - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "专业id") + private String majorId; + + /** + * 专业名称 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "专业名称") + private String majorName; + + /** + * 班级id - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "班级id") + private String classId; + + /** + * 班级名称 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "班级名称") + private String className; + + /** + * 年级 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "年级") + private String grade; + + /** + * 学院id - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "学院id") + private String collegeId; + + /** + * 学院名称 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "学院名称") + private String collegeName; + + /** + * 班主任ID - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "班主任ID") + private Long classTeacherId; + + /** + * 班主任姓名 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "班主任姓名") + private String classTeacherName; + + /** + * 宿舍楼栋 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "宿舍楼栋", converter = ExcelSqlCacheConvert.class) + @ExcelSqlCacheFormat(sqlKey = "xg_dorm_building", valueColumn = "id", labelColumn = "name") + private String dormitoryBuilding; + + /** + * 宿舍房间号 - 预留,数据从班级表关联 + */ + @ExcelProperty(value = "宿舍房间号") + private String dormitoryRoom; + + /** + * 备注信息 + */ + @ExcelProperty(value = "备注信息") + private String remark; + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgMapper.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgMapper.java index 5b804095..e8222b40 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgMapper.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgMapper.java @@ -1,6 +1,7 @@ package org.dromara.xg.mapper; import org.dromara.xg.domain.XgStudentMsg; +import org.dromara.xg.domain.vo.XgStudentMsgExportVo; import org.dromara.xg.domain.vo.XgStudentMsgVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -17,6 +18,18 @@ import java.util.List; */ public interface XgStudentMsgMapper extends BaseMapperPlus { + /** + * 根据组织ID列表分页查询学生信息 用于导出 + * + * @param page 分页参数 + * @param queryWrapper 查询条件 + * @param deptIds 组织ID列表 + * @return 学生信息分页结果 + */ + List queryPageListExportByDeptId( + @Param("ew") LambdaQueryWrapper queryWrapper, + @Param("deptIds") List deptIds); + /** * 根据组织ID列表分页查询学生信息 * diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgService.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgService.java index 42e1c78f..685f2b33 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgService.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgService.java @@ -1,5 +1,6 @@ package org.dromara.xg.service; +import org.dromara.xg.domain.vo.XgStudentMsgExportVo; import org.dromara.xg.domain.vo.XgStudentMsgVo; import org.dromara.xg.domain.bo.XgStudentMsgBo; import org.dromara.common.mybatis.core.page.TableDataInfo; @@ -42,6 +43,16 @@ public interface IXgStudentMsgService { */ List queryList(XgStudentMsgBo bo); + /** + * 根据组织ID分页查询学生信息列表 用于导出数据 + * + * @param bo 查询条件 + * @param params 包含dept_id的参数Map + * @param pageQuery 分页参数 + * @return 学生信息分页列表 + */ + List queryPageListExportByDeptId(XgStudentMsgBo bo, Map params); + /** * 根据组织ID分页查询学生信息列表 * diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgServiceImpl.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgServiceImpl.java index f9255f36..de75cd52 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgServiceImpl.java @@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.dromara.xg.domain.bo.XgStudentMsgBo; +import org.dromara.xg.domain.vo.XgStudentMsgExportVo; import org.dromara.xg.domain.vo.XgStudentMsgVo; import org.dromara.xg.domain.XgStudentMsg; import org.dromara.xg.mapper.XgStudentMsgMapper; @@ -105,6 +106,42 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService { return baseMapper.selectVoList(lqw); } + /** + * 根据组织ID分页查询学生信息列表 用于导出数据 + * + * @param bo 查询条件 + * @param params 包含dept_id的参数Map + * @param pageQuery 分页参数 + * @return 学生信息分页列表 + */ + @Override + public List queryPageListExportByDeptId(XgStudentMsgBo bo, + Map params) { + + log.info("params: {}", params); + log.info("bo: {}", bo); + // 第一步:调用权限过滤方法,获取过滤后的deptIds + List deptIds = new ArrayList<>(); + Object deptIdObj = params.get("dept_id"); + Long deptId = null; + if (ObjectUtil.isNotNull(deptIdObj)) { + deptId = Long.valueOf(deptIdObj.toString()); + } + + // 调用权限过滤方法,获取过滤后的deptIds + List filteredDeptIds = filterDeptIdsByPermission(deptId); + + log.info("权限过滤后的部门ID列表: {}", filteredDeptIds); + + // 第二步:构建查询条件 + LambdaQueryWrapper lqw = buildQueryWrapperForDeptQuery(bo); + + // 第三步:分页查询学生信息 + List result = baseMapper.queryPageListExportByDeptId(lqw, + filteredDeptIds); + return result; + } + /** * 根据组织ID分页查询学生信息列表 * diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsg/XgStudentMsgMapper.xml b/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsg/XgStudentMsgMapper.xml index cf627d4f..840bdba3 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsg/XgStudentMsgMapper.xml +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsg/XgStudentMsgMapper.xml @@ -4,6 +4,72 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + +