Browse Source

update 优化 !pr345 代码结构

疯狂的狮子Li 2 years ago
parent
commit
0f5603aed4

+ 2 - 0
ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelEnumConvert.java

@@ -52,6 +52,8 @@ public class ExcelEnumConvert implements Converter<Object> {
             case BOOLEAN:
                 textValue = cellData.getBooleanValue();
                 break;
+            default:
+                throw new IllegalArgumentException("单元格类型异常!");
         }
         // 如果是空值
         if (ObjectUtil.isNull(textValue)) {

+ 3 - 3
ruoyi-common/src/main/java/com/ruoyi/common/excel/DropDownOptions.java

@@ -63,11 +63,11 @@ public class DropDownOptions {
         StringBuilder stringBuffer = new StringBuilder();
         String regex = "^[\\S\\d\\u4e00-\\u9fa5]+$";
         for (int i = 0; i < vars.length; i++) {
-            Object var = vars[i];
-            if (!var.toString().matches(regex)) {
+            String var = StrUtil.trimToEmpty(String.valueOf(vars[i]));
+            if (!var.matches(regex)) {
                 throw new ServiceException("选项数据不符合规则,仅允许使用中英文字符以及数字");
             }
-            stringBuffer.append(StrUtil.trimToEmpty(var.toString()));
+            stringBuffer.append(var);
             if (i < vars.length - 1) {
                 // 直至最后一个前,都以_作为切割线
                 stringBuffer.append(DELIMITER);

+ 24 - 45
ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelDownHandler.java

@@ -1,5 +1,7 @@
 package com.ruoyi.common.excel;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.EnumUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -11,6 +13,7 @@ import com.ruoyi.common.annotation.ExcelDictFormat;
 import com.ruoyi.common.annotation.ExcelEnumFormat;
 import com.ruoyi.common.core.service.DictService;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StreamUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.usermodel.*;
@@ -20,7 +23,6 @@ import org.apache.poi.xssf.usermodel.XSSFDataValidation;
 
 import java.lang.reflect.Field;
 import java.util.*;
-import java.util.stream.Collectors;
 
 /**
  * <h1>Excel表格下拉选操作</h1>
@@ -90,37 +92,24 @@ public class ExcelDownHandler implements SheetWriteHandler {
             List<String> options = new ArrayList<>();
             if (fields[i].isAnnotationPresent(ExcelDictFormat.class)) {
                 // 如果指定了@ExcelDictFormat,则使用字典的逻辑
-                ExcelDictFormat thisFiledExcelDictFormat = fields[i].getDeclaredAnnotation(ExcelDictFormat.class);
-                String dictType = thisFiledExcelDictFormat.dictType();
-                String converterExp = thisFiledExcelDictFormat.readConverterExp();
+                ExcelDictFormat format = fields[i].getDeclaredAnnotation(ExcelDictFormat.class);
+                String dictType = format.dictType();
+                String converterExp = format.readConverterExp();
                 if (StrUtil.isNotBlank(dictType)) {
                     // 如果传递了字典名,则依据字典建立下拉
-                    options =
-                        new ArrayList<>(
-                            Optional.ofNullable(dictService.getAllDictByDictType(dictType))
-                                .orElseThrow(() -> new ServiceException(String.format("字典 %s 不存在", dictType)))
-                                .values()
-                        );
+                    Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType))
+                        .orElseThrow(() -> new ServiceException(String.format("字典 %s 不存在", dictType)))
+                        .values();
+                    options = new ArrayList<>(values);
                 } else if (StrUtil.isNotBlank(converterExp)) {
                     // 如果指定了确切的值,则直接解析确切的值
-                    options = StrUtil.split(
-                        converterExp,
-                        thisFiledExcelDictFormat.separator(),
-                        true,
-                        true);
+                    options = StrUtil.split(converterExp, format.separator(), true, true);
                 }
             } else if (fields[i].isAnnotationPresent(ExcelEnumFormat.class)) {
                 // 否则如果指定了@ExcelEnumFormat,则使用枚举的逻辑
-                ExcelEnumFormat thisFiledExcelEnumFormat = fields[i].getDeclaredAnnotation(ExcelEnumFormat.class);
-                options =
-                    EnumUtil
-                        .getFieldValues(
-                            thisFiledExcelEnumFormat.enumClass(),
-                            thisFiledExcelEnumFormat.textField()
-                        )
-                        .stream()
-                        .map(String::valueOf)
-                        .collect(Collectors.toList());
+                ExcelEnumFormat format = fields[i].getDeclaredAnnotation(ExcelEnumFormat.class);
+                List<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField());
+                options = StreamUtils.toList(values, String::valueOf);
             }
             if (ObjectUtil.isNotEmpty(options)) {
                 // 仅当下拉可选项不为空时执行
@@ -165,7 +154,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
         if (ObjectUtil.isEmpty(value)) {
             return;
         }
-        this.markOptionsToSheet(helper, sheet, celIndex, helper.createExplicitListConstraint(value.toArray(new String[0])));
+        this.markOptionsToSheet(helper, sheet, celIndex, helper.createExplicitListConstraint(ArrayUtil.toArray(value, String.class)));
     }
 
     /**
@@ -206,9 +195,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
             // 本次循环的一级选项值
             String thisFirstOptionsValue = firstOptions.get(columIndex);
             // 创建第一行的数据
-            Optional
-                // 获取第一行
-                .ofNullable(linkedOptionsDataSheet.getRow(0))
+            Optional.ofNullable(linkedOptionsDataSheet.getRow(0))
                 // 如果不存在则创建第一行
                 .orElseGet(() -> linkedOptionsDataSheet.createRow(finalI))
                 // 第一行当前列
@@ -218,7 +205,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
 
             // 第二行开始,设置第二级别选项参数
             List<String> secondOptions = secoundOptionsMap.get(thisFirstOptionsValue);
-            if (ObjectUtil.isEmpty(secondOptions)) {
+            if (CollUtil.isEmpty(secondOptions)) {
                 // 必须保证至少有一个关联选项,否则将导致Excel解析错误
                 secondOptions = Collections.singletonList("暂无_0");
             }
@@ -251,8 +238,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
                 int finalRowIndex = rowIndex + 1;
                 int finalColumIndex = columIndex;
 
-                Row row = Optional
-                    .ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex))
+                Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex))
                     // 没有则创建
                     .orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex));
                 Optional
@@ -315,9 +301,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
     /**
      * 挂载下拉的列,仅限一级选项
      */
-    private void markOptionsToSheet(DataValidationHelper helper,
-                                    Sheet sheet,
-                                    Integer celIndex,
+    private void markOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer celIndex,
                                     DataValidationConstraint constraint) {
         // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
         CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, celIndex, celIndex);
@@ -327,11 +311,8 @@ public class ExcelDownHandler implements SheetWriteHandler {
     /**
      * 挂载下拉的列,仅限二级选项
      */
-    private void markLinkedOptionsToSheet(DataValidationHelper helper,
-                                          Sheet sheet,
-                                          Integer rowIndex,
-                                          Integer celIndex,
-                                          DataValidationConstraint constraint) {
+    private void markLinkedOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer rowIndex,
+                                          Integer celIndex, DataValidationConstraint constraint) {
         // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
         CellRangeAddressList addressList = new CellRangeAddressList(rowIndex, rowIndex, celIndex, celIndex);
         markDataValidationToSheet(helper, sheet, constraint, addressList);
@@ -340,10 +321,8 @@ public class ExcelDownHandler implements SheetWriteHandler {
     /**
      * 应用数据校验
      */
-    private void markDataValidationToSheet(DataValidationHelper helper,
-                                           Sheet sheet,
-                                           DataValidationConstraint constraint,
-                                           CellRangeAddressList addressList) {
+    private void markDataValidationToSheet(DataValidationHelper helper, Sheet sheet,
+                                           DataValidationConstraint constraint, CellRangeAddressList addressList) {
         // 数据有效性对象
         DataValidation dataValidation = helper.createValidation(constraint, addressList);
         // 处理Excel兼容性问题
@@ -381,7 +360,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
         int thisCircleColumnIndex = columnIndex % 26;
         // 26一循环的次数大于0,则视为栏名至少两位
         String columnPrefix = columnCircleCount == 0
-            ? ""
+            ? StrUtil.EMPTY
             : StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1);
         // 从26一循环内取对应的栏位名
         String columnNext = StrUtil.subWithLength(EXCEL_COLUMN_NAME, thisCircleColumnIndex, 1);

+ 7 - 25
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java

@@ -85,7 +85,7 @@ public class ExcelUtil {
         try {
             resetResponse(sheetName, response);
             ServletOutputStream os = response.getOutputStream();
-            exportExcel(list, sheetName, clazz, false, os);
+            exportExcel(list, sheetName, clazz, false, os, null);
         } catch (IOException e) {
             throw new RuntimeException("导出Excel异常");
         }
@@ -123,7 +123,7 @@ public class ExcelUtil {
         try {
             resetResponse(sheetName, response);
             ServletOutputStream os = response.getOutputStream();
-            exportExcel(list, sheetName, clazz, merge, os);
+            exportExcel(list, sheetName, clazz, merge, os, null);
         } catch (IOException e) {
             throw new RuntimeException("导出Excel异常");
         }
@@ -158,7 +158,7 @@ public class ExcelUtil {
      * @param os        输出流
      */
     public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
-        exportExcel(list, sheetName, clazz, false, os);
+        exportExcel(list, sheetName, clazz, false, os, null);
     }
 
     /**
@@ -183,7 +183,8 @@ public class ExcelUtil {
      * @param merge     是否合并单元格
      * @param os        输出流
      */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) {
+    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge,
+                                       OutputStream os, List<DropDownOptions> options) {
         ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
             .autoCloseStream(false)
             // 自动适配
@@ -195,28 +196,9 @@ public class ExcelUtil {
             // 合并处理器
             builder.registerWriteHandler(new CellMergeStrategy(list, true));
         }
-        builder.doWrite(list);
-    }
-
-    /**
-     * 导出带有下拉框的Excel表格
-     *
-     * @param options 下拉框数据
-     */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz,
-                                       boolean merge, OutputStream os, List<DropDownOptions> options) {
-        ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
-            .autoCloseStream(false)
-            // 自动适配
-            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
-            // 大数值自动转换 防止失真
-            .registerConverter(new ExcelBigNumberConvert())
+        if (CollUtil.isNotEmpty(options)) {
             // 添加下拉框操作
-            .registerWriteHandler(new ExcelDownHandler(options))
-            .sheet(sheetName);
-        if (merge) {
-            // 合并处理器
-            builder.registerWriteHandler(new CellMergeStrategy(list, true));
+            builder.registerWriteHandler(new ExcelDownHandler(options));
         }
         builder.doWrite(list);
     }

+ 0 - 3
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java

@@ -1,6 +1,5 @@
 package com.ruoyi.demo.controller;
 
-import cn.dev33.satoken.annotation.SaIgnore;
 import cn.hutool.core.collection.CollUtil;
 import com.ruoyi.common.excel.ExcelResult;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -90,7 +89,6 @@ public class TestExcelController {
      *
      * @param response /
      */
-    @SaIgnore
     @GetMapping("/exportWithOptions")
     public void exportWithOptions(HttpServletResponse response) {
         exportExcelService.exportWithOptions(response);
@@ -99,7 +97,6 @@ public class TestExcelController {
     /**
      * 导入表格
      */
-    @SaIgnore
     @PostMapping(value = "/importWithOptions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     public List<ExportDemoVo> importWithOptions(@RequestPart("file") MultipartFile file) throws Exception {
         // 处理解析结果

+ 19 - 38
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/ExportExcelServiceImpl.java

@@ -1,7 +1,9 @@
 package com.ruoyi.demo.service.impl;
 
+import cn.hutool.core.util.StrUtil;
 import com.ruoyi.common.enums.UserStatus;
 import com.ruoyi.common.excel.DropDownOptions;
+import com.ruoyi.common.utils.StreamUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.demo.domain.vo.ExportDemoVo;
 import com.ruoyi.demo.service.IExportExcelService;
@@ -55,52 +57,31 @@ public class ExportExcelServiceImpl implements IExportExcelService {
 
         // 把所有的结果提取为规范的下拉选可选项
         // 规范的一级省,用于级联省-市
-        List<String> provinceOptions =
-            provinceList.stream()
-                .map(everyProvince ->
-                    DropDownOptions.createOptionValue(
-                        everyProvince.getName(),
-                        everyProvince.getId()
-                    ))
-                .collect(Collectors.toList());
+        List<String> provinceOptions = StreamUtils.toList(provinceList, everyProvince ->
+                DropDownOptions.createOptionValue(everyProvince.getName(), everyProvince.getId()));
         // 规范的二级市,用于级联省-市
         Map<String, List<String>> provinceToCityOptions = new HashMap<>();
-        cityList.stream()
-            .collect(Collectors.groupingBy(DemoCityData::getPData))
+        StreamUtils.groupByKey(cityList, DemoCityData::getPData)
             .forEach((province, thisProvinceCityList) -> {
                 // 每个省下二级的市可选项
-                provinceToCityOptions.put(
-                    DropDownOptions.createOptionValue(province.getName(), province.getId()),
-                    thisProvinceCityList.stream()
-                        .map(everyCity ->
-                            DropDownOptions.createOptionValue(everyCity.getName(), everyCity.getId())
-                        )
-                        .collect(Collectors.toList())
-                );
+                String optionValue = DropDownOptions.createOptionValue(province.getName(), province.getId());
+                List<String> list = StreamUtils.toList(thisProvinceCityList, everyCity ->
+                    DropDownOptions.createOptionValue(everyCity.getName(), everyCity.getId()));
+                provinceToCityOptions.put(optionValue, list);
             });
 
         // 规范的一级市,用于级联市-县
-        List<String> cityOptions = cityList.stream()
-            .map(everyCity ->
-                DropDownOptions.createOptionValue(
-                    everyCity.getName(),
-                    everyCity.getId()
-                ))
-            .collect(Collectors.toList());
+        List<String> cityOptions = StreamUtils.toList(cityList, everyCity ->
+            DropDownOptions.createOptionValue(everyCity.getName(), everyCity.getId()));
         // 规范的二级县,用于级联市-县
         Map<String, List<String>> cityToAreaOptions = new HashMap<>();
-        areaList.stream()
-            .collect(Collectors.groupingBy(DemoCityData::getPData))
+        StreamUtils.groupByKey(areaList, DemoCityData::getPData)
             .forEach((city, thisCityAreaList) -> {
                 // 每个市下二级的县可选项
-                cityToAreaOptions.put(
-                    DropDownOptions.createOptionValue(city.getName(), city.getId()),
-                    thisCityAreaList.stream()
-                        .map(everyArea ->
-                            DropDownOptions.createOptionValue(everyArea.getName(), everyArea.getId())
-                        )
-                        .collect(Collectors.toList())
-                );
+                String optionValue = DropDownOptions.createOptionValue(city.getName(), city.getId());
+                List<String> list = StreamUtils.toList(thisCityAreaList, everyCity ->
+                    DropDownOptions.createOptionValue(everyCity.getName(), everyCity.getId()));
+                cityToAreaOptions.put(optionValue, list);
             });
 
         // 因为省市县三个都是联动,省级联市,市级联县,因此需要创建两个级联下拉,分别以省和市为判断依据创建
@@ -129,14 +110,14 @@ public class ExportExcelServiceImpl implements IExportExcelService {
         // 到此为止所有的下拉框可选项已全部配置完毕
 
         // 接下来需要将Excel中的展示数据转换为对应的下拉选
-        List<ExportDemoVo> outList = excelDataList.stream().map(everyRowData -> {
+        List<ExportDemoVo> outList = StreamUtils.toList(excelDataList, everyRowData -> {
             // 只需要处理没有使用@ExcelDictFormat注解的下拉框
             // 一般来说,可以直接在数据库查询即查询出省市县信息,这里通过模拟操作赋值
             everyRowData.setProvince(buildOptions(provinceList, everyRowData.getProvinceId()));
             everyRowData.setCity(buildOptions(cityList, everyRowData.getCityId()));
             everyRowData.setArea(buildOptions(areaList, everyRowData.getAreaId()));
             return everyRowData;
-        }).collect(Collectors.toList());
+        });
 
         ExcelUtil.exportExcel(outList, "下拉框示例", ExportDemoVo.class, response, options);
     }
@@ -148,7 +129,7 @@ public class ExportExcelServiceImpl implements IExportExcelService {
             DemoCityData demoCityData = groupByIdMap.get(id).get(0);
             return DropDownOptions.createOptionValue(demoCityData.getName(), demoCityData.getId());
         } else {
-            return "";
+            return StrUtil.EMPTY;
         }
     }
 

+ 2 - 9
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java

@@ -281,14 +281,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
 
     @Override
     public Map<String, String> getAllDictByDictType(String dictType) {
-        List<SysDictData> thisDictTypeDataList = selectDictDataByType(dictType);
-        Map<String, String> dictMap = null;
-        for (SysDictData everyDictData : thisDictTypeDataList) {
-            if (ObjectUtil.isNull(dictMap)) {
-                dictMap = new HashMap<>();
-            }
-            dictMap.put(everyDictData.getDictValue(), everyDictData.getDictLabel());
-        }
-        return dictMap;
+        List<SysDictData> list = selectDictDataByType(dictType);
+        return StreamUtils.toMap(list, SysDictData::getDictValue, SysDictData::getDictLabel);
     }
 }