diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java index d3e1e1fbc..1a0f9ddee 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java @@ -33,6 +33,11 @@ public @interface Excel */ public String dateFormat() default ""; + /** + * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) + */ + public String dictType() default ""; + /** * 读取内容转表达式 (如: 0=男,1=女,2=未知) */ @@ -89,6 +94,11 @@ public @interface Excel */ public String[] combo() default {}; + /** + * 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解. + */ + public boolean comboReadDict() default false; + /** * 是否需要纵向合并单元格,应对需求:含有list集合单元格) */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelDictDataConverter​.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelDictDataConverter​.java new file mode 100644 index 000000000..715bcfe1b --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelDictDataConverter​.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.core.utils.poi; + +/** + * Excel字典数据转换 + * + * @author ruoyi + */ +public interface ExcelDictDataConverter​ +{ + /** + * 根据字典类型和字典键值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + String getDictLabel(String dictType, String dictValue, String separator); + + /** + * 根据字典类型和字典标签获取字典键值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典键值 + */ + String getDictValue(String dictType, String dictLabel, String separator); + + /** + * 根据字典类型获取字典标签列表 + * + * @param dictType 字典类型 + * @return 字典标签列表 + */ + String getDictLabels(String dictType); +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java index b6b8df08e..034eff78b 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java @@ -94,6 +94,11 @@ public class ExcelUtil public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + /** + * 用于dictType属性数据存储,避免重复查缓存 + */ + public Map sysDictMap = new HashMap(); + /** * 单元格样式缓存 */ @@ -199,6 +204,11 @@ public class ExcelUtil */ private ExcelImageHandler imageHandler; + /** + * 字典数据转换器 + */ + private ExcelDictDataConverter​ dictDataConverter; + public ExcelUtil(Class clazz) { this.clazz = clazz; @@ -224,6 +234,26 @@ public class ExcelUtil return imageHandler; } + /** + * 获取字典数据转换器 + * + * @return 字典数据转换器 + */ + private ExcelDictDataConverter​ getDictDataConverter() + { + if (dictDataConverter == null) + { + try + { + dictDataConverter = SpringUtils.getBean(ExcelDictDataConverter​.class); + } + catch (Exception e) + { + } + } + return dictDataConverter; + } + /** * 仅在Excel中显示列属性 * @@ -510,6 +540,15 @@ public class ExcelUtil { val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + if (!sysDictMap.containsKey(attr.dictType() + val)) + { + String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + sysDictMap.put(attr.dictType() + val, dictValue); + } + val = sysDictMap.get(attr.dictType() + val); + } else if (!attr.handler().equals(ExcelHandlerAdapter.class)) { val = dataFormatHandlerAdapter(val, attr, null); @@ -1098,13 +1137,12 @@ public class ExcelUtil { return defaultVal; } - ExcelImageHandler imageHandler = getImageHandler(); StringBuilder propertyString = new StringBuilder(); for (PictureData picture : images) { byte[] data = picture.getData(); String extension = FileTypeUtils.getFileExtendName(data).toLowerCase(); - propertyString.append(imageHandler.upload(data, extension)).append(SEPARATOR); + propertyString.append(getImageHandler().upload(data, extension)).append(SEPARATOR); } return StringUtils.stripEnd(propertyString.toString(), SEPARATOR); } @@ -1181,17 +1219,28 @@ public class ExcelUtil // 设置列宽 sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); } - if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict()) { - if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) + String[] comboArray = attr.combo(); + if (attr.comboReadDict()) + { + if (!sysDictMap.containsKey("combo_" + attr.dictType())) + { + String labels = getDictDataConverter().getDictLabels(attr.dictType()); + sysDictMap.put("combo_" + attr.dictType(), labels); + } + String val = sysDictMap.get("combo_" + attr.dictType()); + comboArray = StringUtils.split(val, SEPARATOR); + } + if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255) { // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到 - setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column); } else { // 提示信息或只能选择不能输入的列内容. - setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column); } } } @@ -1226,6 +1275,7 @@ public class ExcelUtil String dateFormat = attr.dateFormat(); String readConverterExp = attr.readConverterExp(); String separator = attr.separator(); + String dictType = attr.dictType(); if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) { cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat)); @@ -1235,6 +1285,15 @@ public class ExcelUtil { cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); } + else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) + { + if (!sysDictMap.containsKey(dictType + value)) + { + String lable = convertDictByExp(Convert.toStr(value), dictType, separator); + sysDictMap.put(dictType + value, lable); + } + cell.setCellValue(sysDictMap.get(dictType + value)); + } else if (value instanceof BigDecimal && -1 != attr.scale()) { cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); @@ -1461,6 +1520,32 @@ public class ExcelUtil return StringUtils.stripEnd(propertyString.toString(), separator); } + /** + * 解析字典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public String convertDictByExp(String dictValue, String dictType, String separator) + { + return getDictDataConverter().getDictLabel(dictType, dictValue, separator); + } + + /** + * 反向解析值字典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return getDictDataConverter().getDictValue(dictType, dictLabel, separator); + } + /** * 数据处理器 * diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java index 2c8d18d6d..d67947d2f 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java @@ -1,7 +1,9 @@ package com.ruoyi.common.security.utils; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.alibaba.fastjson2.JSONArray; import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.utils.SpringUtils; @@ -16,6 +18,68 @@ import com.ruoyi.system.api.domain.SysDictData; */ public class DictUtils { + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue, String separator) + { + List datas = DictUtils.getDictCache(dictType); + if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictValue)) + { + return StringUtils.EMPTY; + } + Map dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictValue(), dict.getDictLabel()), Map::putAll); + if (!StringUtils.contains(dictValue, separator)) + { + return dictMap.getOrDefault(dictValue, StringUtils.EMPTY); + } + StringBuilder labelBuilder = new StringBuilder(); + for (String seperatedValue : dictValue.split(separator)) + { + if (dictMap.containsKey(seperatedValue)) + { + labelBuilder.append(dictMap.get(seperatedValue)).append(separator); + } + } + return StringUtils.removeEnd(labelBuilder.toString(), separator); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel, String separator) + { + List datas = DictUtils.getDictCache(dictType); + if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictLabel)) + { + return StringUtils.EMPTY; + } + Map dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictLabel(), dict.getDictValue()), Map::putAll); + if (!StringUtils.contains(dictLabel, separator)) + { + return dictMap.getOrDefault(dictLabel, StringUtils.EMPTY); + } + StringBuilder valueBuilder = new StringBuilder(); + for (String seperatedValue : dictLabel.split(separator)) + { + if (dictMap.containsKey(seperatedValue)) + { + valueBuilder.append(dictMap.get(seperatedValue)).append(separator); + } + } + return StringUtils.removeEnd(valueBuilder.toString(), separator); + } + /** * 设置字典缓存 * diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/poi/DictDataConverter.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/poi/DictDataConverter.java new file mode 100644 index 000000000..044ee2f2f --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/poi/DictDataConverter.java @@ -0,0 +1,78 @@ +package com.ruoyi.common.security.utils.poi; + +import java.util.List; +import org.springframework.stereotype.Component; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.utils.poi.ExcelDictDataConverter​; +import com.ruoyi.common.security.utils.DictUtils; +import com.ruoyi.system.api.domain.SysDictData; + +/** + * 字典数据转换 + * + * @author ruoyi + */ +@Component +public class DictDataConverter implements ExcelDictDataConverter​ +{ + /** + * 分隔符 + */ + public static final String SEPARATOR = ","; + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @return 字典标签 + */ + @Override + public String getDictLabel(String dictType, String dictValue, String separator) + { + if (StringUtils.isEmpty(dictValue)) + { + return StringUtils.EMPTY; + } + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典值 + */ + @Override + public String getDictValue(String dictType, String dictLabel, String separator) + { + if (StringUtils.isEmpty(dictLabel)) + { + return StringUtils.EMPTY; + } + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * 根据字典类型获取字典所有标签 + * + * @param dictType 字典类型 + * @return 字典值 + */ + @Override + public String getDictLabels(String dictType) + { + StringBuilder propertyString = new StringBuilder(); + List datas = DictUtils.getDictCache(dictType); + if (StringUtils.isNull(datas)) + { + return StringUtils.EMPTY; + } + for (SysDictData dict : datas) + { + propertyString.append(dict.getDictLabel()).append(SEPARATOR); + } + return StringUtils.stripEnd(propertyString.toString(), SEPARATOR); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 38915f2f4..4aa501837 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -3,3 +3,4 @@ com.ruoyi.common.security.service.TokenService com.ruoyi.common.security.aspect.PreAuthorizeAspect com.ruoyi.common.security.aspect.InnerAuthAspect com.ruoyi.common.security.handler.GlobalExceptionHandler +com.ruoyi.common.security.utils.poi.DictDataConverter