Kaynağa Gözat

fix(导入导出模块):
完善导入导出模块

18339543638 2 yıl önce
ebeveyn
işleme
8a95fd65be
67 değiştirilmiş dosya ile 1251 ekleme ve 1343 silme
  1. 6 18
      tr-dependencies/pom.xml
  2. 5 0
      tr-framework/pom.xml
  3. 7 1
      tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/annotation/ExcelPropertySupport.java
  4. 33 0
      tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/handler/AbstractDataHandler.java
  5. 17 0
      tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/handler/DataHandler.java
  6. 6 0
      tr-modules-api/tr-module-system-api/src/main/java/cn/tr/module/api/sys/storage/SysStorageApi.java
  7. 5 6
      tr-modules/tr-module-export/pom.xml
  8. 20 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/constant/ExportConstant.java
  9. 1 1
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/BooleanConverter.java
  10. 3 3
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/DictCodeConverter.java
  11. 43 7
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/DictItemConverter.java
  12. 62 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelRowDataDTO.java
  13. 32 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelSheetCallBackDTO.java
  14. 10 10
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelSheetDataDTO.java
  15. 3 3
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelTemplateDescDTO.java
  16. 42 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/exception/SheetException.java
  17. 123 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/read/CustomerReadListener.java
  18. 184 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/write/CustomCellWriteHandler.java
  19. 29 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/write/CustomSheetWriteHandler.java
  20. 43 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/service/ExcelDataHandlerContext.java
  21. 130 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/service/ExcelService.java
  22. 4 4
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/utils/ExcelTemplateDescUtil.java
  23. 107 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/utils/StyleUtils.java
  24. 0 43
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/row/config/StdRowHandlerListener.java
  25. 101 16
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/row/service/impl/SysExportRowServiceImpl.java
  26. 0 37
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/config/HandleSheetConfig.java
  27. 6 27
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/controller/SysExportSheetController.java
  28. 11 5
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/dto/SysExportSheetDTO.java
  29. 36 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/enums/SheetImportStatus.java
  30. 9 3
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/po/SysExportSheetPO.java
  31. 0 20
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/IExcelService.java
  32. 15 0
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/ISysExportSheetService.java
  33. 0 35
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/impl/ExcelServiceImpl.java
  34. 75 15
      tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/impl/SysExportSheetServiceImpl.java
  35. 12 2
      tr-modules/tr-module-system/pom.xml
  36. 0 1
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/log/aspect/OperateLogAspect.java
  37. 7 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/storage/provider/SysStorageApiProvider.java
  38. 2 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/tenant/dto/SysTenantAddDTO.java
  39. 3 2
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/tenant/service/impl/SysTenantServiceImpl.java
  40. 2 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserDTO.java
  41. 0 2
      tr-plugins/pom.xml
  42. 0 23
      tr-plugins/tr-spring-boot-starter-plugin-biz-bean-mapper/pom.xml
  43. 2 10
      tr-plugins/tr-spring-boot-starter-plugin-biz-tenant/src/main/java/cn/tr/plugin/biz/tenant/config/db/TenantDatabaseInterceptor.java
  44. 1 1
      tr-plugins/tr-spring-boot-starter-plugin-biz-tenant/src/main/java/cn/tr/plugin/biz/tenant/context/TenantContextHolder.java
  45. 0 43
      tr-plugins/tr-spring-boot-starter-plugin-import-export/pom.xml
  46. 0 37
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/CompositeExcelTemplateFacade.java
  47. 0 17
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/TrImExportAutoConfiguration.java
  48. 0 187
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/annatation/Excel.java
  49. 0 19
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/annatation/ExcelHandlerAdapter.java
  50. 0 46
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/config/ExcelThreadFactory.java
  51. 0 21
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/constant/ImportConstant.java
  52. 0 44
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/RowData.java
  53. 0 37
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/RowResult.java
  54. 0 24
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/SheetResult.java
  55. 0 52
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/StdExcelImportComposite.java
  56. 0 31
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/StdExcelImportCompositeRegister.java
  57. 0 86
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/handler/AbstractExcelImportHandler.java
  58. 0 30
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/handler/ExcelImportHandler.java
  59. 0 20
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/listener/RowHandlerListener.java
  60. 0 21
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/validate/ExcelImportValidate.java
  61. 0 18
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/validate/StdExcelImportValidate.java
  62. 0 25
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/strategy/ExcelHandleSheetStrategy.java
  63. 0 183
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/utils/ExcelUtils.java
  64. 0 1
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  65. 0 60
      tr-plugins/tr-spring-boot-starter-plugin-import-export/src/test/java/cn/tr/plugin/excel/utils/ExcelImportUtilTest.java
  66. 1 0
      tr-test/src/main/resources/application-doc.yml
  67. 53 46
      tr-test/src/test/java/cn/tr/module/excel/CompositeExcelTemplateFacadeTest.java

+ 6 - 18
tr-dependencies/pom.xml

@@ -244,12 +244,12 @@
                 <version>${oshi.core.version}</version>
             </dependency>
 
-            <!-- excel导入导出工具 -->
-            <dependency>
-                <groupId>org.apache.poi</groupId>
-                <artifactId>poi-ooxml</artifactId>
-                <version>${poi.version}</version>
-            </dependency>
+            <!--&lt;!&ndash; excel导入导出工具 &ndash;&gt;-->
+            <!--<dependency>-->
+                <!--<groupId>org.apache.poi</groupId>-->
+                <!--<artifactId>poi-ooxml</artifactId>-->
+                <!--<version>${poi.version}</version>-->
+            <!--</dependency>-->
 
             <!--websocket-->
             <dependency>
@@ -359,14 +359,6 @@
                 <version>${revision}</version>
             </dependency>
 
-
-            <!--对象转换插件-->
-            <dependency>
-                <groupId>cn.tr</groupId>
-                <artifactId>tr-spring-boot-starter-plugin-biz-bean-mapper</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
             <!--在线文档插件-->
             <dependency>
                 <groupId>cn.tr</groupId>
@@ -471,10 +463,6 @@
                 <version>${bus-rabbit.version}</version>
             </dependency>
 
-
-
-
-
             <dependency>
                 <groupId>com.alibaba</groupId>
                 <artifactId>easyexcel</artifactId>

+ 5 - 0
tr-framework/pom.xml

@@ -31,6 +31,11 @@
             <artifactId>hutool-all</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>

+ 7 - 1
tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/annotation/ExcelDict.java → tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/annotation/ExcelPropertySupport.java

@@ -11,11 +11,17 @@ import java.lang.annotation.*;
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
 @Inherited
-public @interface ExcelDict {
+public @interface ExcelPropertySupport {
     /**
      * 字典码
      * 1、导出时会根据字典码自动生成下拉菜单
      * 2、导出时会根据字段值自动返回字典值
      */
     String dictCode() default "";
+
+
+    /**
+     * 导出模板批注
+     */
+    String comment() default "";
 }

+ 33 - 0
tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/handler/AbstractDataHandler.java

@@ -0,0 +1,33 @@
+package cn.tr.module.api.export.handler;
+
+
+import cn.tr.core.utils.ValidationUtils;
+import lombok.Getter;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+/**
+ * @ClassName : AbstractDataHandler
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月23日
+ */
+
+public abstract class AbstractDataHandler<T> implements DataHandler<T> {
+    private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+    @Getter
+    private Class<T> aClass;
+
+    public AbstractDataHandler(Class<T> aClass) {
+        this.aClass = aClass;
+    }
+
+    @Override
+    public void handle(T obj) {
+        ValidationUtils.validate(validator,obj);
+        doHandle(obj);
+    }
+
+    public abstract void doHandle(T obj);
+}

+ 17 - 0
tr-modules-api/tr-module-export-api/src/main/java/cn/tr/module/api/export/handler/DataHandler.java

@@ -0,0 +1,17 @@
+package cn.tr.module.api.export.handler;
+
+/**
+ * @ClassName : DataHandler
+ * @Description : 导入数据的处理器
+ * @Author : LF
+ * @Date: 2023年05月23日
+ */
+
+public interface DataHandler<T> {
+
+    /**
+     * 对导入对象进行处理
+     * @param obj
+     */
+    void handle(T obj);
+}

+ 6 - 0
tr-modules-api/tr-module-system-api/src/main/java/cn/tr/module/api/sys/storage/SysStorageApi.java

@@ -16,6 +16,12 @@ public interface SysStorageApi {
      */
     String upload(byte[] content,String filename) throws Exception;
 
+    /**
+     * 删除文件
+     * @param fileId
+     */
+    void removeById(String fileId);
+
     /**
      * 获取文件
      * @param recordId 文件记录id

+ 5 - 6
tr-modules/tr-module-export/pom.xml

@@ -16,6 +16,11 @@
 
     <dependencies>
 
+        <dependency>
+            <groupId>cn.tr</groupId>
+            <artifactId>tr-spring-boot-starter-plugin-biz-tenant</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>cn.tr</groupId>
             <artifactId>tr-spring-boot-starter-plugin-eventbus</artifactId>
@@ -41,12 +46,6 @@
             <artifactId>tr-spring-boot-starter-plugin-web</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-import-export</artifactId>
-            <version>0.0.9</version>
-        </dependency>
-
         <dependency>
             <groupId>cn.tr</groupId>
             <artifactId>tr-module-export-api</artifactId>

+ 20 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/constant/ExportConstant.java

@@ -0,0 +1,20 @@
+package cn.tr.module.excel.core.constant;
+
+/**
+ * @ClassName : ExportConstant
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月20日
+ */
+
+public interface ExportConstant {
+    /**
+     * 表格最大行数
+     */
+    Integer MAX_ROW=65535;
+
+
+    String ROW_PARSE_TOPIC="/export/biz/excel";
+
+    String SHEET_FINISH_TOPIC="/export/biz/excel/callback";
+}

+ 1 - 1
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/BooleanConverter.java

@@ -20,7 +20,7 @@ public class BooleanConverter implements Converter<Boolean> {
 
     @Override
     public WriteCellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
-        WriteCellData<Object> cellData = new WriteCellData<>();
+        WriteCellData<Object> cellData = new WriteCellData<>("");
         cellData.setStringValue(Boolean.TRUE.equals(value)?"是":"否");
         return cellData;
     }

+ 3 - 3
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/DictCodeConverter.java

@@ -31,8 +31,8 @@ public class DictCodeConverter implements Converter<String> {
 
     @Override
     public WriteCellData<?> convertToExcelData(String dictCode, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
-        WriteCellData<String> cellData = new WriteCellData<>();
-        if(StrUtil.isNotEmpty(dictCode)){
+        WriteCellData<String> cellData = new WriteCellData<>("");
+        if(StrUtil.isEmpty(dictCode)){
             return cellData;
         }
         List<Pair<String, String>> items = dictApi.findAllDictItemsByCode(dictCode);
@@ -43,7 +43,7 @@ public class DictCodeConverter implements Converter<String> {
     private String buildString(List<Pair<String, String>> items){
         StringBuilder result = new StringBuilder();
         for (Pair<String, String> item : items) {
-            result.append("-").append(item.getKey()).append("(").append(item.getValue()).append(")").append("\n");
+            result.append(item.getKey()).append("(").append(item.getValue()).append(");").append("\n");
         }
         return result.toString();
     }

+ 43 - 7
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/converter/DictItemConverter.java

@@ -1,18 +1,24 @@
 package cn.tr.module.excel.core.converter;
 
+import cn.hutool.core.lang.Pair;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
-import cn.tr.module.api.export.annotation.ExcelDict;
+import cn.tr.module.api.export.annotation.ExcelPropertySupport;
 import cn.tr.module.api.sys.dict.SysDictApi;
 import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.converters.ReadConverterContext;
 import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.data.ReadCellData;
 import com.alibaba.excel.metadata.data.WriteCellData;
 import com.alibaba.excel.metadata.property.ExcelContentProperty;
 
+import java.lang.reflect.Field;
+import java.util.List;
+
 /**
  * @ClassName : DictItemConverter
  * @Description : 字典值转换器
- *                与{@link cn.tr.module.api.export.annotation.ExcelDict }一起结合使用
+ *                与{@link ExcelPropertySupport }一起结合使用
  * @Author : LF
  * @Date: 2023年05月19日
  */
@@ -27,17 +33,47 @@ public class DictItemConverter  implements Converter<String> {
         return String.class;
     }
 
+    @Override
+    public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        ExcelPropertySupport excelPropertySupport = contentProperty.getField().getAnnotation(ExcelPropertySupport.class);
+        if(excelPropertySupport ==null||StrUtil.isEmpty(excelPropertySupport.dictCode())){
+            return null;
+        }
+        List<Pair<String, String>> items = dictApi.findAllDictItemsByCode(excelPropertySupport.dictCode());
+        for (Pair<String, String> item : items) {
+            if(StrUtil.equals(item.getValue(),cellData.getStringValue())){
+                return item.getKey();
+            }
+        }
+        return null;
+    }
+
     @Override
     public WriteCellData<?> convertToExcelData(String itemKey, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
-        WriteCellData<String> cellData = new WriteCellData<>();
-        if(StrUtil.isNotEmpty(itemKey)){
+        WriteCellData<String> cellData = new WriteCellData<>("");
+        if(StrUtil.isEmpty(itemKey)){
             return cellData;
         }
-        ExcelDict excelDict = contentProperty.getField().getAnnotation(ExcelDict.class);
-        if(excelDict==null||StrUtil.isEmpty(excelDict.dictCode())){
+        ExcelPropertySupport excelPropertySupport = contentProperty.getField().getAnnotation(ExcelPropertySupport.class);
+        if(excelPropertySupport ==null||StrUtil.isEmpty(excelPropertySupport.dictCode())){
             return cellData;
         }
-        cellData.setStringValue(dictApi.findDictItem(excelDict.dictCode(), itemKey));
+        cellData.setStringValue(dictApi.findDictItem(excelPropertySupport.dictCode(), itemKey));
         return cellData;
     }
+
+    @Override
+    public String convertToJavaData(ReadConverterContext<?> context) throws Exception {
+        Field field = context.getContentProperty().getField();
+        ExcelPropertySupport excelPropertySupport = field.getAnnotation(ExcelPropertySupport.class);
+        if(excelPropertySupport !=null){
+            List<Pair<String, String>> items = dictApi.findAllDictItemsByCode(excelPropertySupport.dictCode());
+            for (Pair<String, String> item : items) {
+                if(StrUtil.equals(item.getValue(),context.getReadCellData().getStringValue())){
+                    return item.getKey();
+                }
+            }
+        }
+        return null;
+    }
 }

+ 62 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelRowDataDTO.java

@@ -0,0 +1,62 @@
+package cn.tr.module.excel.core.dto;
+
+import cn.tr.plugin.security.bo.UserLoginInfoBO;
+import cn.tr.plugin.security.context.LoginUserContextHolder;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName : RowDataDTO
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月20日
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ExcelRowDataDTO<T> implements Serializable {
+
+    private static final long serialVersionUID = -2984188555791128202L;
+    /**
+     * 数据解析结果
+     */
+    private Boolean success;
+
+    private String errorMsg;
+    /**
+     * 数据解析对象
+     */
+    private T obj;
+
+    private Class<T> aClass;
+
+    /**
+     * 工作簿id
+     */
+    private String sheetId;
+
+    /**
+     * 解析行数
+     */
+    private int rowIndex;
+
+    /**
+     * 导入用户
+     */
+    private UserLoginInfoBO importUser;
+
+    private int columnSize;
+
+    public static <T> ExcelRowDataDTO success(T obj,Class<T> aClass,String sheetId,int rowIndex,int columnSize){
+        UserLoginInfoBO user = LoginUserContextHolder.getUser();
+        return new ExcelRowDataDTO<T>(true,null,obj,aClass,sheetId,rowIndex,user,columnSize);
+    }
+
+    public static <T> ExcelRowDataDTO fail(String errorMsg,String sheetId,int rowIndex,int columnSize){
+        UserLoginInfoBO user = LoginUserContextHolder.getUser();
+        return new ExcelRowDataDTO<T>(false,errorMsg,null,null,sheetId,rowIndex,user,columnSize);
+    }
+}

+ 32 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelSheetCallBackDTO.java

@@ -0,0 +1,32 @@
+package cn.tr.module.excel.core.dto;
+
+import cn.tr.plugin.security.bo.UserLoginInfoBO;
+import cn.tr.plugin.security.context.LoginUserContextHolder;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName : ExcelSheetCallBackDTO
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月21日
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ExcelSheetCallBackDTO implements Serializable {
+    private static final long serialVersionUID = -3362916292323476272L;
+    private String sheetId;
+
+    private int totalCount;
+
+    private UserLoginInfoBO importUser;
+
+    public static ExcelSheetCallBackDTO of(String sheetId, int totalCount) {
+        UserLoginInfoBO user = LoginUserContextHolder.getUser();
+        return new ExcelSheetCallBackDTO(sheetId,totalCount,user);
+    }
+}

+ 10 - 10
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/SheetData.java → tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelSheetDataDTO.java

@@ -1,31 +1,30 @@
-package cn.tr.plugin.excel.im;
+package cn.tr.module.excel.core.dto;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import org.apache.poi.ss.usermodel.Sheet;
 
 import java.io.Serializable;
 
 /**
- * @ClassName : SheetImportBO
+ * @ClassName : ExcelSheetDataDTO
  * @Description :
  * @Author : LF
- * @Date: 2023年05月15
+ * @Date: 2023年05月21日
  */
+@Data
 @AllArgsConstructor
 @NoArgsConstructor
-@Data
-public class SheetData implements Serializable {
+public class ExcelSheetDataDTO implements Serializable {
     private static final long serialVersionUID = 6508600428191086611L;
     /**
      * 文件上传后的记录id
      */
     private String fileRecordId;
     /**
-     * 工作簿
+     * 唯一id
      */
-    private transient Sheet sheet;
+    private String uniqueId;
     /**
      * 上传文件名称
      */
@@ -35,7 +34,8 @@ public class SheetData implements Serializable {
      * 全部行数
      */
     private int totalNum;
-    public static SheetData of(String fileRecordId, Sheet sheet, String filename) {
-        return new SheetData(fileRecordId, sheet, filename, 0);
+
+    public static ExcelSheetDataDTO of(String fileRecordId, String uniqueId, String filename) {
+        return new ExcelSheetDataDTO(fileRecordId, uniqueId, filename, 0);
     }
 }

+ 3 - 3
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/dto/ExcelTemplateDescDTO.java

@@ -18,12 +18,12 @@ public class ExcelTemplateDescDTO {
     @ExcelProperty("字段名")
     private String fieldName;
 
-    @ExcelProperty(value = "是否为字典值",converter = BooleanConverter.class)
-    private Boolean dict;
-
     @ExcelProperty(value = "是否必输",converter = BooleanConverter.class)
     private Boolean addNeed;
 
+    @ExcelProperty(value = "是否为字典值",converter = BooleanConverter.class)
+    private Boolean dict;
+
     @ExcelProperty("字典值")
     private String dictCode;
 

+ 42 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/exception/SheetException.java

@@ -0,0 +1,42 @@
+package cn.tr.module.excel.core.exception;
+
+import cn.tr.core.exception.TRExcCode;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 工作簿导入异常 Exception
+ * @author JR
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public final class SheetException extends RuntimeException {
+
+    private static final long serialVersionUID = 7657422049507503668L;
+    /**
+     * 业务错误码
+     *
+     */
+    private TRExcCode code=TRExcCode.SYSTEM_ERROR_B0001;
+
+    /**
+     * 错误提示
+     */
+    private String message;
+
+    /**
+     * 空构造方法,避免反序列化问题
+     */
+    private SheetException() {
+    }
+
+
+    public SheetException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+}

+ 123 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/read/CustomerReadListener.java

@@ -0,0 +1,123 @@
+package cn.tr.module.excel.core.handler.read;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.tr.core.exception.ServiceException;
+import cn.tr.core.exception.TRExcCode;
+import cn.tr.module.excel.core.constant.ExportConstant;
+import cn.tr.module.excel.core.dto.ExcelRowDataDTO;
+import cn.tr.module.excel.core.dto.ExcelSheetCallBackDTO;
+import cn.tr.module.excel.core.exception.SheetException;
+import cn.tr.plugin.eventbus.config.EventBus;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.metadata.data.ReadCellData;
+import com.alibaba.excel.read.listener.ReadListener;
+import lombok.extern.slf4j.Slf4j;
+import org.omg.CORBA.SystemException;
+import org.springframework.util.ReflectionUtils;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 自定义解析列数据监听器
+ */
+@Slf4j
+public class CustomerReadListener<T> implements ReadListener<T> {
+    private Class<T> aClass;
+    private EventBus eventBus;
+    private Map<String, ExcelProperty> fieldMap;
+    private String sheetId;
+    private AtomicInteger totalCount=new AtomicInteger(0);
+    private Integer headIndex=-1;
+    public CustomerReadListener(Class<T> aClass, EventBus eventBus,String sheetId) {
+        this.aClass=aClass;
+        this.eventBus=eventBus;
+        this.fieldMap=getExcelPropertyFieldMap(aClass);
+        this.sheetId=sheetId;
+    }
+
+    @Override
+    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
+        //对sheet的表头进行校验
+        validateExcelHead(fieldMap,headMap);
+        headIndex = context.readRowHolder().getRowIndex();
+    }
+
+    @Override
+    public void invoke(T data, AnalysisContext context) {
+        Integer rowIndex = context.readRowHolder().getRowIndex();
+        if(headIndex.equals(rowIndex)){
+            return;
+        }
+        ExcelRowDataDTO rowData = ExcelRowDataDTO.success(data, aClass, sheetId, rowIndex,CollectionUtil.size(fieldMap));
+        publishMsg(rowData);
+    }
+
+    /**
+     * 所有数据解析完成了 都会来调用
+     *
+     * @param context
+     */
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        //记录导入数据条数
+        eventBus.publishEx(ExportConstant.SHEET_FINISH_TOPIC, ExcelSheetCallBackDTO.of(sheetId,totalCount.get()));
+    }
+
+    @Override
+    public void onException(Exception exception, AnalysisContext context) throws Exception {
+        if(exception instanceof SheetException){
+            throw exception;
+        }
+        Integer rowIndex = context.readRowHolder().getRowIndex();
+        ExcelRowDataDTO rowData = ExcelRowDataDTO.fail(exception.getMessage(), sheetId, rowIndex,CollectionUtil.size(fieldMap));
+        publishMsg(rowData);
+    }
+
+
+    private void publishMsg(ExcelRowDataDTO source){
+        eventBus.publishEx(ExportConstant.ROW_PARSE_TOPIC,source);
+        totalCount.incrementAndGet();
+    }
+
+
+    private Map<String,ExcelProperty> getExcelPropertyFieldMap(Class aClass){
+        HashMap<String,ExcelProperty> result = new HashMap<>();
+        ReflectionUtils.doWithFields(aClass,field -> {
+            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+            if(excelProperty==null){
+                return;
+            }
+            result.put(field.getName(),excelProperty);
+        });
+        return result;
+    }
+
+    /**
+     * 对导入的Excel的表头进行校验
+     * @param excelPropertyMap
+     * @param headMap
+     */
+    private void validateExcelHead(Map<String,ExcelProperty> excelPropertyMap,Map<Integer, ReadCellData<?>> headMap){
+        if (CollectionUtil.size(excelPropertyMap) != CollectionUtil.size(headMap)) {
+            throw new SheetException("模板错误,请重新下载导入模板");
+        }
+        Set<String> headNameSet = new HashSet<>();
+        headMap.forEach((index,cell)->{
+            headNameSet.add(cell.getStringValue());
+        });
+
+        //进行校验
+        excelPropertyMap.forEach((fieldName,excelProperty)->{
+            String excelName = excelProperty.value()[0];
+            if(!CollectionUtil.contains(headNameSet,excelName)){
+                throw new SheetException("模板错误,请重新下载导入模板");
+            }
+        });
+    }
+}

+ 184 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/write/CustomCellWriteHandler.java

@@ -0,0 +1,184 @@
+package cn.tr.module.excel.core.handler.write;
+
+import cn.hutool.core.lang.Pair;
+import cn.hutool.core.util.ClassUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.tr.module.api.export.annotation.ExcelPropertySupport;
+import cn.tr.module.api.sys.dict.SysDictApi;
+import cn.tr.module.excel.core.constant.ExportConstant;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+
+import javax.validation.constraints.NotNull;
+import java.lang.reflect.Field;
+import java.time.temporal.Temporal;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName : CustomSheetWriteHandler
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月19日
+ */
+
+public class CustomCellWriteHandler implements CellWriteHandler {
+    private final SysDictApi dictApi;
+    public CustomCellWriteHandler() {
+        this.dictApi= SpringUtil.getBean(SysDictApi.class);
+    }
+
+    @Override
+    public void afterCellDispose(CellWriteHandlerContext context) {
+        Sheet sheet = context.getWriteSheetHolder().getSheet();
+        Cell cell = context.getCell();
+        boolean head = Boolean.TRUE.equals(context.getHead());
+        //冻结表头
+        if(head){
+            Field field = context.getExcelContentProperty().getField();
+            markNotNull(field,cell);
+            //进行数字校验
+            createNumColumn(field,cell);
+            //进行字典校验
+            createDictColumn(field,cell);
+            //进行日期格式校验
+            createDateColumn(field,cell);
+        }
+    }
+
+    /**
+     * 锁定表头单元格
+     * @param sheet
+     */
+    private void clockHead(CellWriteHandlerContext context,Sheet sheet,Cell cell,boolean head){
+        if(head){
+            CellStyle clockStyle =sheet.getWorkbook().createCellStyle();
+            clockStyle.setLocked(true);
+            CellStyle unClockStyle =sheet.getWorkbook().createCellStyle();
+            unClockStyle.setLocked(false);
+
+            sheet.setDefaultColumnStyle(cell.getColumnIndex(),unClockStyle);
+            cell.setCellStyle(clockStyle);
+        }else {
+            WriteCellData<?> cellData = context.getFirstCellData();
+            WriteCellStyle style = cellData.getOrCreateStyle();
+            style.setLocked(false);
+            cellData.setWriteCellStyle(style);
+        }
+    }
+
+    private void createDateColumn(Field field,Cell cell){
+        if(ClassUtil.isAssignable(Date.class,field.getType())
+                ||ClassUtil.isAssignable(java.sql.Date.class,field.getType())
+                ||ClassUtil.isAssignable(Temporal.class,field.getType())
+        ){
+            NotNull notNull = field.getAnnotation(NotNull.class);
+            DataValidationHelper helper = cell.getSheet().getDataValidationHelper();
+            //DVConstraint constrain1 = DVConstraint.CreateDateConstraint(条件,"最小时间","最大时间","时间格式"); //这是检查时间的方法
+            addValidateData(cell.getSheet(),
+                    cell,
+                    helper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,"Date(1900, 1, 1)","Date(2099, 12, 31)","yyyy-MM-dd"),
+                    cell.getColumnIndex(),
+                    "请输入[yyyy-MM-dd]格式的日期",
+                    "请输入[yyyy-MM-dd]格式的日期",notNull==null);
+        }
+    }
+
+    /**
+     * 字典列校验
+     * @param field
+     * @param cell
+     */
+    private void createDictColumn(Field field,Cell cell){
+        Sheet sheet = cell.getSheet();
+        ExcelPropertySupport excelPropertySupport = field.getAnnotation(ExcelPropertySupport.class);
+        if(excelPropertySupport !=null){
+            List<Pair<String, String>> items = dictApi.findAllDictItemsByCode(excelPropertySupport.dictCode());
+            List<String> values = items.stream()
+                    .map(Pair::getValue)
+                    .distinct()
+                    .collect(Collectors.toList());
+            NotNull notNull = field.getAnnotation(NotNull.class);
+            addValidateData(cell.getSheet(),
+                    cell,
+                    new XSSFDataValidationConstraint(
+                            DataValidationConstraint.ValidationType.INTEGER,
+                            DataValidationConstraint.OperatorType.BETWEEN, String.valueOf(Integer.MIN_VALUE),  String.valueOf(Integer.MAX_VALUE)),
+                    cell.getColumnIndex(),
+                    "请输入"+values.toString()+"中的任意一个",
+                    "请输入"+values.toString()+"中的任意一个",
+                    notNull==null);
+        }
+    }
+
+    /**
+     * 对必输字段进行标记
+     * @param field
+     * @param cell
+     */
+    private void markNotNull(Field field,Cell cell){
+        NotNull notNull = field.getAnnotation(NotNull.class);
+        if(notNull!=null){
+            String cellValue = cell.getStringCellValue();
+            cell.setCellValue("*"+cellValue);
+        }
+    }
+
+
+    /**
+     * 数字列进行校验
+     * @param field
+     * @param cell
+     */
+    private void createNumColumn(Field field,Cell cell){
+        if(ClassUtil.isAssignable(Number.class,field.getType())){
+            NotNull notNull = field.getAnnotation(NotNull.class);
+            addValidateData(cell.getSheet(),
+                    cell,
+                    new XSSFDataValidationConstraint(
+                            DataValidationConstraint.ValidationType.INTEGER,
+                            DataValidationConstraint.OperatorType.BETWEEN, String.valueOf(Integer.MIN_VALUE),  String.valueOf(Integer.MAX_VALUE)),
+                    cell.getColumnIndex(),
+                    "请输入"+Integer.MIN_VALUE+"-"+Integer.MAX_VALUE+"之间的数字",
+                    "请输入"+Integer.MIN_VALUE+"-"+Integer.MAX_VALUE+"之间的数字",
+                    notNull==null);
+        }
+    }
+
+
+    private void addValidateData(Sheet sheet,Cell cell,DataValidationConstraint constraint,int columnIndex,String promptMsg,String errorMsg,boolean allowEmpty){
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        CellRangeAddressList cellRange = createColumnCellRange(columnIndex);
+        DataValidation dataValidation = helper.createValidation(constraint, cellRange);
+        //输入错误提示
+        dataValidation.createErrorBox("输入值错误", errorMsg);
+        dataValidation.setShowErrorBox(true);
+        dataValidation.setEmptyCellAllowed(allowEmpty);
+        dataValidation.setSuppressDropDownArrow(true);
+        sheet.addValidationData(dataValidation);
+
+        Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
+        // 在第一行 第二列创建一个批注
+        Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, columnIndex, 0, columnIndex, 0));
+        // 输入批注信息
+        comment.setString(new XSSFRichTextString(promptMsg));
+        // 将批注添加到单元格对象中
+        cell.setCellComment(comment);
+    }
+
+    private CellRangeAddressList createHeadCellRange(int column){
+        return new CellRangeAddressList(0, 0,column,column);
+    }
+
+    private CellRangeAddressList createColumnCellRange(int column){
+        return new CellRangeAddressList(1, ExportConstant.MAX_ROW,column,column);
+    }
+}

+ 29 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/handler/write/CustomSheetWriteHandler.java

@@ -0,0 +1,29 @@
+package cn.tr.module.excel.core.handler.write;
+
+import com.alibaba.excel.write.handler.SheetWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
+import org.apache.poi.ss.usermodel.Sheet;
+
+
+/**
+ * 固定表头和添加过滤
+ */
+public class CustomSheetWriteHandler implements SheetWriteHandler {
+
+    public int colSplit = 0, rowSplit = 1, leftmostColumn = 0, topRow = 1;
+
+    @Override
+
+    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+
+    }
+
+    @Override
+    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+        Sheet sheet = writeSheetHolder.getSheet();
+        sheet.createFreezePane(colSplit, rowSplit, leftmostColumn, topRow);
+//        sheet.protectSheet("123456");
+    }
+
+}

+ 43 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/service/ExcelDataHandlerContext.java

@@ -0,0 +1,43 @@
+package cn.tr.module.excel.core.service;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.tr.module.api.export.handler.AbstractDataHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.util.*;
+/**
+ * @ClassName : ExcelDataHandlerContext
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月23日
+ */
+@Component
+@Slf4j
+public class ExcelDataHandlerContext {
+
+    private Map<Class,AbstractDataHandler> handlerMap=new HashMap<>();
+
+    @Autowired(required = false)
+    public ExcelDataHandlerContext(List<AbstractDataHandler> dataHandlerList) {
+        if(CollectionUtil.isEmpty(dataHandlerList)){
+            return;
+        }
+        for (AbstractDataHandler abstractDataHandler : dataHandlerList) {
+            Class handlerAClass = abstractDataHandler.getAClass();
+            AbstractDataHandler dataHandler = handlerMap.get(handlerAClass);
+            if(dataHandler!=null){
+                throw new UnsupportedOperationException("[ExcelDataHandlerContext] Class:{"+abstractDataHandler.getAClass()+"} dataHandler has exist");
+            }
+            handlerMap.put(handlerAClass,abstractDataHandler);
+        }
+    }
+
+    public <T> void dataHandle(T obj){
+        AbstractDataHandler dataHandler = handlerMap.get(obj.getClass());
+        if(dataHandler==null){
+            throw new UnsupportedOperationException("[dataHandle] 找不到响应的数据处理器");
+        }
+        dataHandler.handle(obj);
+    }
+}

+ 130 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/service/ExcelService.java

@@ -0,0 +1,130 @@
+package cn.tr.module.excel.core.service;
+
+import cn.hutool.core.io.IoUtil;
+import cn.tr.module.api.sys.storage.SysStorageApi;
+import cn.tr.module.excel.core.dto.ExcelTemplateDescDTO;
+import cn.tr.module.excel.core.handler.read.CustomerReadListener;
+import cn.tr.module.excel.core.handler.write.CustomCellWriteHandler;
+import cn.tr.module.excel.core.handler.write.CustomSheetWriteHandler;
+import cn.tr.module.excel.core.utils.ExcelTemplateDescUtil;
+import cn.tr.module.excel.core.utils.StyleUtils;
+import cn.tr.module.excel.sheet.dto.SysExportSheetDTO;
+import cn.tr.module.excel.sheet.enums.SheetImportStatus;
+import cn.tr.module.excel.sheet.service.ISysExportSheetService;
+import cn.tr.plugin.eventbus.config.EventBus;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
+import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
+import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ReflectionUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @ClassName : ExcelUtil
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月20日
+ */
+@Component
+public class ExcelService {
+    private static HorizontalCellStyleStrategy horizontalCellStyleStrategy =
+            new HorizontalCellStyleStrategy(StyleUtils.getHeadStyle(), StyleUtils.getContentStyle());
+
+    @Autowired
+    private ISysExportSheetService exportSheetService;
+
+    @Autowired
+    private SysStorageApi storageApi;
+
+    @Autowired
+    private EventBus eventBus;
+    /**
+     * 导出execl
+     * @param aClass 导出类型
+     * @param data   导出数据
+     * @param <T>    导出类
+     * @return
+     */
+    public  <T> byte[] exportExcel(Class<T> aClass, Collection<T> data){
+        ByteArrayOutputStream outputStream =new ByteArrayOutputStream();
+        ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
+        createSheet(excelWriter,0,"导入(导出)模板",aClass,data);
+        List<ExcelTemplateDescDTO> exportTemplate = ExcelTemplateDescUtil.createExportTemplate(aClass);
+        createSheet(excelWriter,1,"模板注释",ExcelTemplateDescDTO.class,exportTemplate);
+        excelWriter.finish();
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 导入excel
+     * @param filename    文件名称
+     * @param inputStream  数据流
+     * @param aClass
+     * @return  返回SheetId
+     */
+    public <T> String importExcel(String filename,InputStream inputStream, Class<T> aClass) throws Exception {
+        byte[] content = IoUtil.readBytes(inputStream);
+        String fileId = storageApi.upload(content,filename);
+        //新增sheet导入记录
+        SysExportSheetDTO sheet = new SysExportSheetDTO();
+        sheet.setFileName(filename);
+        sheet.setImportFileId(fileId);
+        sheet.setTotalCount(0);
+        sheet.setSuccessCount(0);
+        sheet.setFailCount(0);
+        sheet.setStartTime(new Date());
+        sheet.setColumnCount(countColumn(aClass));
+        sheet.setStatus(SheetImportStatus.parsing.getValue());
+        String sheetId = exportSheetService.insertSysExportSheetReturnId(sheet);
+        try {
+            EasyExcel
+                    .read(IoUtil.toStream(content),aClass,new CustomerReadListener<T>(aClass,eventBus,sheetId))
+                    .sheet(0)
+                    .doRead();
+        }catch (Exception e){
+            //删除导入记录
+            exportSheetService.removeSysExportSheetByIds(Collections.singleton(sheetId));
+            //删除导入文件
+            storageApi.removeById(fileId);
+            throw e;
+        }
+
+        return sheetId;
+    }
+
+    private <T> void createSheet(ExcelWriter excelWriter,int sheetNo,String sheetName,Class<T> aClass, Collection<T> data){
+        WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo, sheetName)
+                .registerWriteHandler(horizontalCellStyleStrategy)
+                .registerWriteHandler(new SimpleColumnWidthStyleStrategy(30))
+                .registerWriteHandler(new SimpleRowHeightStyleStrategy((short) 30, (short) 30))
+                .registerWriteHandler(new CustomCellWriteHandler())
+                .registerWriteHandler(new CustomSheetWriteHandler())
+                .head(aClass).build();
+        excelWriter.write(data,writeSheet);
+    }
+
+
+    private int countColumn(Class aClass){
+        AtomicInteger result = new AtomicInteger(0);
+        ReflectionUtils.doWithFields(aClass,field -> {
+            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+            if(excelProperty!=null){
+                result.incrementAndGet();
+            }
+        });
+        return result.get();
+    }
+
+}

+ 4 - 4
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/utils/ExcelTemplateDescUtil.java

@@ -1,7 +1,7 @@
 package cn.tr.module.excel.core.utils;
 
 import cn.hutool.core.collection.CollectionUtil;
-import cn.tr.module.api.export.annotation.ExcelDict;
+import cn.tr.module.api.export.annotation.ExcelPropertySupport;
 import cn.tr.module.excel.core.dto.ExcelTemplateDescDTO;
 import com.alibaba.excel.annotation.ExcelProperty;
 import org.springframework.util.ReflectionUtils;
@@ -26,12 +26,12 @@ public class ExcelTemplateDescUtil {
                 return;
             }
             ExcelTemplateDescDTO desc = new ExcelTemplateDescDTO();
-            ExcelDict excelDict = field.getAnnotation(ExcelDict.class);
+            ExcelPropertySupport excelPropertySupport = field.getAnnotation(ExcelPropertySupport.class);
             NotNull notNull = field.getAnnotation(NotNull.class);
             desc.setTitle(CollectionUtil.getLast(Stream.of(excelProperty.value()).collect(Collectors.toList())));
             desc.setFieldName(field.getName());
-            desc.setDict(excelDict!=null);
-            desc.setDictCode(excelDict!=null?excelDict.dictCode():null);
+            desc.setDict(excelPropertySupport !=null);
+            desc.setDictCode(excelPropertySupport !=null? excelPropertySupport.dictCode():null);
             desc.setAddNeed(notNull!=null);
             result.add(desc);
         });

+ 107 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/core/utils/StyleUtils.java

@@ -0,0 +1,107 @@
+package cn.tr.module.excel.core.utils;
+
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
+import com.alibaba.excel.write.metadata.style.WriteFont;
+import org.apache.poi.ss.usermodel.*;
+
+/**
+ * @ClassName : StyleUtils
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年05月19日
+ */
+
+public class StyleUtils {
+    public static WriteCellStyle getHeadStyle(){
+        // 头的策略
+        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
+        // 背景颜色
+        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+        headWriteCellStyle.setLocked(true);
+
+        // 字体
+        WriteFont headWriteFont = new WriteFont();
+        //设置字体名字
+        headWriteFont.setFontName("黑体");
+        //斜体
+        headWriteFont.setItalic(true);
+        //设置字体大小
+        headWriteFont.setFontHeightInPoints((short)12);
+        //字体加粗
+        headWriteFont.setBold(true);
+
+        //在样式用应用设置的字体
+        headWriteCellStyle.setWriteFont(headWriteFont); ;
+
+        // 样式
+        //设置底边框
+        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
+        //设置底边框颜色
+        headWriteCellStyle.setBottomBorderColor((short) 0);
+        //设置左边框
+        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
+        //设置左边框颜色
+        headWriteCellStyle.setLeftBorderColor((short) 0);
+        //设置右边框
+        headWriteCellStyle.setBorderRight(BorderStyle.THIN);
+        //设置右边框颜色
+        headWriteCellStyle.setRightBorderColor((short) 0);
+        //设置顶边框
+        headWriteCellStyle.setBorderTop(BorderStyle.THIN);
+        //设置顶边框颜色
+        headWriteCellStyle.setTopBorderColor((short) 0);
+
+
+        //设置自动换行
+        headWriteCellStyle.setWrapped(true);
+
+
+        //设置水平对齐的样式为居中对齐
+        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
+        //设置垂直对齐的样式为居中对齐
+        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+
+
+        //设置文本收缩至合适
+        headWriteCellStyle.setShrinkToFit(true);
+
+        return headWriteCellStyle;
+    }
+
+
+    public static WriteCellStyle getContentStyle(){
+        // 内容的策略
+        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
+
+        // 背景绿色
+        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
+        contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+
+        // 设置字体
+        WriteFont contentWriteFont = new WriteFont();
+        contentWriteFont.setFontHeightInPoints((short) 9);//设置字体大小
+        contentWriteFont.setFontName("宋体"); //设置字体名字
+        contentWriteCellStyle.setWriteFont(contentWriteFont);//在样式用应用设置的字体;
+
+        //设置样式;
+        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置底边框;
+        contentWriteCellStyle.setBottomBorderColor((short) 0);//设置底边框颜色;
+        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);  //设置左边框;
+        contentWriteCellStyle.setLeftBorderColor((short) 0);//设置左边框颜色;
+        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);//设置右边框;
+        contentWriteCellStyle.setRightBorderColor((short) 0);//设置右边框颜色;
+        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);//设置顶边框;
+        contentWriteCellStyle.setTopBorderColor((short) 0); ///设置顶边框颜色;
+
+        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 水平居中
+        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
+        contentWriteCellStyle.setWrapped(true); //设置自动换行;
+
+        // contentWriteCellStyle.setShrinkToFit(true);//设置文本收缩至合适
+
+        return contentWriteCellStyle;
+    }
+
+}

+ 0 - 43
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/row/config/StdRowHandlerListener.java

@@ -1,43 +0,0 @@
-package cn.tr.module.excel.row.config;
-
-import cn.tr.core.annotation.TenantIgnore;
-import cn.tr.module.excel.row.dto.SysExportRowDTO;
-import cn.tr.module.excel.row.service.ISysExportRowService;
-import cn.tr.module.excel.sheet.service.ISysExportSheetService;
-import cn.tr.plugin.excel.im.RowData;
-import cn.tr.plugin.excel.im.RowResult;
-import cn.tr.plugin.excel.im.listener.RowHandlerListener;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * @ClassName : StdRowHandlerListener
- * @Description :
- * @Author : LF
- * @Date: 2023年05月17日
- */
-@Component
-@AllArgsConstructor
-public class StdRowHandlerListener implements RowHandlerListener {
-    private final ISysExportRowService exportRowService;
-    private final ISysExportSheetService exportSheetService;
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TenantIgnore
-    public void afterHandleRow(RowData data, RowResult result) throws Exception{
-        SysExportRowDTO source= new SysExportRowDTO();
-        source.setRowIndex(data.getRowNum());
-        source.setSuccess(result.isSuccess());
-        source.setErrorMsg(result.getErrorMsg());
-        source.setSheetId(result.getSheetId());
-        source.setOpTime(result.getOpTime());
-        source.setMaxColumnIndex(data.getMaxColumnIndex());
-        //记录行导入结果
-        exportRowService.insertSysExportRow(source);
-
-        //更新工作簿导入结果
-        exportSheetService.updateRowResult(result.getSheetId(),result.isSuccess());
-
-    }
-}

+ 101 - 16
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/row/service/impl/SysExportRowServiceImpl.java

@@ -1,7 +1,19 @@
 package cn.tr.module.excel.row.service.impl;
 
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.tr.core.utils.JsonUtils;
+import cn.tr.module.excel.core.constant.ExportConstant;
+import cn.tr.module.excel.core.dto.ExcelRowDataDTO;
+import cn.tr.module.excel.core.dto.ExcelSheetCallBackDTO;
+import cn.tr.module.excel.core.service.ExcelDataHandlerContext;
 import cn.tr.module.excel.row.po.SysExportRowPO;
+import cn.tr.module.excel.sheet.service.ISysExportSheetService;
+import cn.tr.plugin.biz.tenant.utils.TenantUtils;
+import cn.tr.plugin.eventbus.annotation.Subscribe;
+import cn.tr.plugin.security.bo.UserLoginInfoBO;
+import cn.tr.plugin.security.context.LoginUserContextHolder;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -17,33 +29,39 @@ import cn.tr.module.excel.mapper.SysExportRowMapper;
  * @date  2023/05/15 21:48
  **/
 @Service
+@Slf4j
 public class SysExportRowServiceImpl implements ISysExportRowService {
     @Autowired
     private SysExportRowRepository baseRepository;
 
+    @Autowired
+    private ISysExportSheetService exportSheetService;
+
+    @Autowired
+    private ExcelDataHandlerContext dataHandlerContext;
     @Override
     public List<SysExportRowDTO> selectSysExportRowBySheetId(String sheetId) {
         return SysExportRowMapper.INSTANCE.convertDtoList(baseRepository.selectList(new LambdaQueryWrapper<SysExportRowPO>()
-        .eq(SysExportRowPO::getSheetId,sheetId)));
+                .eq(SysExportRowPO::getSheetId,sheetId)));
     }
 
     /**
-    * 根据id查询导入行记录
-    * @param    id 主键id
-    * @author   lf
-    * @date      2023/05/15 21:48
-    */
+     * 根据id查询导入行记录
+     * @param    id 主键id
+     * @author   lf
+     * @date      2023/05/15 21:48
+     */
     @Override
     public SysExportRowDTO selectSysExportRowById(String id){
         return SysExportRowMapper.INSTANCE.convertDto(baseRepository.selectById(id));
     };
 
     /**
-    * 新增导入行记录
-    * @param   source 新增实体类
-    * @author lf
-    * @date  2023/05/15 21:48
-    */
+     * 新增导入行记录
+     * @param   source 新增实体类
+     * @author lf
+     * @date  2023/05/15 21:48
+     */
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean insertSysExportRow(SysExportRowDTO source){
@@ -51,14 +69,81 @@ public class SysExportRowServiceImpl implements ISysExportRowService {
     };
 
     /**
-    * 删除导入行记录详情
-    * @param  ids 删除主键集合
-    * @author lf
-    * @date    2023/05/15 21:48
-    */
+     * 删除导入行记录详情
+     * @param  ids 删除主键集合
+     * @author lf
+     * @date    2023/05/15 21:48
+     */
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int removeSysExportRowByIds(Collection<String> ids){
         return baseRepository.deleteBatchIds(ids);
     };
+
+
+    /**
+     * 真正处理列数据的方法
+     * @param rowData
+     * @throws Exception
+     */
+    @Subscribe(ExportConstant.ROW_PARSE_TOPIC)
+    @Transactional(rollbackFor = Exception.class)
+    public void doHandleRow(ExcelRowDataDTO rowData) throws Exception {
+        UserLoginInfoBO user = rowData.getImportUser();
+        LoginUserContextHolder.setUser(user);
+        TenantUtils.execute(user.getTenantId(),()->{
+            SysExportRowDTO source= new SysExportRowDTO();
+            source.setRowIndex(rowData.getRowIndex());
+            source.setSheetId(rowData.getSheetId());
+            source.setMaxColumnIndex(rowData.getColumnSize());
+
+            if(Boolean.TRUE.equals(rowData.getSuccess())){
+                //数据解析成功进行处理
+                Object obj = JsonUtils
+                        .parseObject(JsonUtils.toJsonString(rowData.getObj()), rowData.getAClass());
+                try {
+                    dataHandlerContext.dataHandle(obj);
+                    source.setSuccess(true);
+                }catch (Exception e){
+                    source.setSuccess(false);
+                    source.setErrorMsg(ExceptionUtil.getMessage(e));
+                }
+            }else {
+                source.setSuccess(rowData.getSuccess());
+                source.setErrorMsg(rowData.getErrorMsg());
+            }
+            //记录行导入结果
+            this.insertSysExportRow(source);
+            //更新工作簿导入结果
+            try {
+                exportSheetService.updateRowResult(rowData.getSheetId(),rowData.getSuccess());
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error("[doHandleRow] excel导入数据失败,rowData:{},e:{}", JsonUtils.toJsonString(rowData),e);
+            }
+        });
+    }
+
+    /**
+     * 数据解析完成后的的方法
+     * @param callBackDTO 解析完成的实体类
+     * @throws Exception
+     */
+    @Subscribe(ExportConstant.SHEET_FINISH_TOPIC)
+    @Transactional(rollbackFor = Exception.class)
+    public void doHandleSheetCallBack(ExcelSheetCallBackDTO callBackDTO) throws Exception {
+        UserLoginInfoBO user = callBackDTO.getImportUser();
+        LoginUserContextHolder.setUser(user);
+        //更新工作簿导入结果
+        TenantUtils.execute(user.getTenantId(),()->{
+            try {
+                exportSheetService.doSheetCallback(callBackDTO.getSheetId(),callBackDTO.getTotalCount());
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error("[doHandleSheetCallBack] excel数据解析完成后更新失败,callBackDTO:{},e:{}", JsonUtils.toJsonString(callBackDTO),e);
+            }
+        });
+
+
+    }
 }

+ 0 - 37
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/config/HandleSheetConfig.java

@@ -1,37 +0,0 @@
-package cn.tr.module.excel.sheet.config;
-
-import cn.tr.module.excel.sheet.dto.SysExportSheetDTO;
-import cn.tr.module.excel.sheet.service.ISysExportSheetService;
-import cn.tr.plugin.excel.strategy.ExcelHandleSheetStrategy;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-
-import javax.annotation.PostConstruct;
-import java.util.Date;
-
-/**
- * @ClassName : HandleSheetConfig
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Configuration
-public class HandleSheetConfig {
-    @Autowired
-    private ISysExportSheetService sysExportSheetService;
-    @PostConstruct
-    public void init(){
-        ExcelHandleSheetStrategy.tr.handleSheetFunction=sheetData -> {
-            SysExportSheetDTO source = new SysExportSheetDTO();
-            source.setFileName(sheetData.getFilename());
-            source.setImportFileId(sheetData.getFileRecordId());
-            source.setTotalCount(sheetData.getTotalNum());
-            source.setSuccessCount(0);
-            source.setFailCount(0);
-            source.setStartTime(new Date());
-            source.setFinish(false);
-            return sysExportSheetService.insertSysExportSheetReturnId(source);
-        };
-    }
-}

+ 6 - 27
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/controller/SysExportSheetController.java

@@ -1,26 +1,16 @@
 package cn.tr.module.excel.sheet.controller;
 
-import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.ExcelWriter;
-import com.alibaba.excel.annotation.ExcelProperty;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import cn.tr.core.pojo.CommonResult;
 import lombok.AllArgsConstructor;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import lombok.Data;
-import lombok.NoArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 import cn.tr.module.excel.sheet.dto.SysExportSheetDTO;
 import cn.tr.module.excel.sheet.service.ISysExportSheetService;
 import cn.tr.plugin.mybatis.base.BaseController;
 import org.springframework.web.bind.annotation.*;
-
-import java.io.ByteArrayOutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collections;
-
 /**
  * 导入工作簿记录表控制器
  *
@@ -42,23 +32,12 @@ public class SysExportSheetController extends BaseController{
         return CommonResult.success(sysExportSheetService.selectSysExportSheetById(id));
     }
 
-    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        ExcelWriter build = EasyExcel.write(out).build();
-        EasyExcel.write("C:\\Users\\JR\\Desktop\\test1.xls", User.class).inMemory(true).sheet(0,"模板")
-                .doWrite(Collections.singleton(User.class));
-    }
-
 
-    @AllArgsConstructor(staticName = "of")
-    @Data
-    @NoArgsConstructor
-    static class User{
-        @ExcelProperty("姓名")
-        private String name;
-        @ExcelProperty("生日")
-        private String  birthday;
-        @ExcelProperty("年龄")
-        private Integer age;
+    @ApiOperationSupport(author = "lf",order = 2)
+    @ApiOperation(value = "取消所给id的数据导入",notes = "权限: 无")
+    @GetMapping("/cancel/{id}")
+    public CommonResult<Boolean> cancel(@PathVariable("id") String id){
+        sysExportSheetService.selectSysExportSheetById(id);
+        return CommonResult.success(true);
     }
 }

+ 11 - 5
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/dto/SysExportSheetDTO.java

@@ -1,9 +1,9 @@
 package cn.tr.module.excel.sheet.dto;
 
+import cn.tr.module.excel.sheet.enums.SheetImportStatus;
 import cn.tr.plugin.mybatis.pojo.BaseDTO;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
-import cn.tr.core.validation.Insert;
 import cn.tr.core.validation.Update;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -46,10 +46,16 @@ public class SysExportSheetDTO extends BaseDTO  {
 
     @ApiModelProperty(value = "开始处理时间", position = 8)
     private Date startTime;
+    /**
+     * {@link SheetImportStatus#getValue()}
+     */
+    @ApiModelProperty(value = "工作簿处理状态", position = 9)
+    private String status;
+
+    @ApiModelProperty(value = "列数", position = 10)
+    private Integer columnCount;
 
-    @ApiModelProperty(value = "结束处理时间", position = 9)
-    private Date endTime;
 
-    @ApiModelProperty(value = "是否处理完成", position = 10)
-    private Boolean finish;
+    @ApiModelProperty(value = "结束处理时间", position = 11)
+    private Date endTime;
 }

+ 36 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/enums/SheetImportStatus.java

@@ -0,0 +1,36 @@
+package cn.tr.module.excel.sheet.enums;
+
+import cn.tr.core.enums.IEnum;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @ClassName : SheetImportStatus
+ * @Description : 工作簿导入状态
+ * @Author : LF
+ * @Date: 2023年05月22日
+ */
+@AllArgsConstructor
+@Getter
+public enum  SheetImportStatus implements IEnum<String> {
+
+    parsing("parsing","解析中"),
+
+    importing("importing","导入中"),
+
+    parsingSuccess("parsingSuccess","解析成功"),
+
+    importSuccess("importSuccess","导入成功"),
+
+    importCancel("importFail","取消导入")
+    ;
+    /**
+     * 状态
+     */
+    private final String value;
+    /**
+     * 描述
+     */
+    private final String label;
+
+}

+ 9 - 3
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/po/SysExportSheetPO.java

@@ -1,6 +1,7 @@
 package cn.tr.module.excel.sheet.po;
 
 
+import cn.tr.module.excel.sheet.enums.SheetImportStatus;
 import cn.tr.plugin.mybatis.pojo.BasePO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -57,7 +58,12 @@ public class SysExportSheetPO extends BasePO {
     @ApiModelProperty(value = "结束处理时间", position = 8)
     private Date endTime;
 
-    /** 是否处理完成 */
-    @ApiModelProperty(value = "是否处理完成", position = 9)
-    private Boolean finish;
+    @ApiModelProperty(value = "列数", position = 9)
+    private Integer columnCount;
+
+    /**
+     * {@link SheetImportStatus#getValue()}
+     */
+    @ApiModelProperty(value = "工作簿处理状态", position = 10)
+    private String status;
 }

+ 0 - 20
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/IExcelService.java

@@ -1,20 +0,0 @@
-package cn.tr.module.excel.sheet.service;
-
-import cn.tr.plugin.excel.im.SheetResult;
-
-/**
- * @ClassName : IExcelService
- * @Description :
- * @Author : LF
- * @Date: 2023年05月18日
- */
-public interface IExcelService {
-    /**
-     * 导入数据流
-     * @param code         导入类型编码
-     * @param content      文件内容
-     * @param filename     文件名称
-     * @return 导入结果
-     */
-    SheetResult importStream(String code,byte[] content,String filename) throws Exception;
-}

+ 15 - 0
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/ISysExportSheetService.java

@@ -19,6 +19,14 @@ public interface ISysExportSheetService{
      */
     SysExportSheetDTO selectSysExportSheetById(String id);
 
+
+    /**
+     * 取消工作簿导入
+     * @param id 工作簿id
+     * @return
+     */
+    boolean cancelImport(String id)  throws Exception;
+
     /**
      * 新增导入工作簿记录表
      * @param   source 新增实体类
@@ -49,4 +57,11 @@ public interface ISysExportSheetService{
      * @param success
      */
     void updateRowResult(String rowId, boolean success) throws Exception;
+
+    /**
+     * 工作簿解析完成后的回调
+     * @param sheetId
+     * @param totalCount
+     */
+    void doSheetCallback(String sheetId,int totalCount) throws Exception;
 }

+ 0 - 35
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/impl/ExcelServiceImpl.java

@@ -1,35 +0,0 @@
-package cn.tr.module.excel.sheet.service.impl;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.poi.excel.ExcelUtil;
-import cn.tr.module.api.sys.storage.SysStorageApi;
-import cn.tr.module.excel.sheet.service.IExcelService;
-import cn.tr.plugin.excel.CompositeExcelTemplateFacade;
-import cn.tr.plugin.excel.im.SheetData;
-import cn.tr.plugin.excel.im.SheetResult;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-/**
- * @ClassName : ExcelServiceImpl
- * @Description :
- * @Author : LF
- * @Date: 2023年05月18日
- */
-@Component
-public class ExcelServiceImpl implements IExcelService {
-
-    @Autowired
-    private CompositeExcelTemplateFacade templateFacade;
-
-    @Autowired
-    private SysStorageApi sysStorageApi;
-    @Override
-    public SheetResult importStream(String code, byte[] content, String filename) throws Exception {
-        Sheet sheet = ExcelUtil.getReader(IoUtil.toStream(content)).getSheet();
-        String recordId = sysStorageApi.upload(content, filename);
-        SheetData sheetData = SheetData.of(recordId, sheet, filename);
-        return templateFacade.importSheet(code,sheetData);
-    }
-}

+ 75 - 15
tr-modules/tr-module-export/src/main/java/cn/tr/module/excel/sheet/service/impl/SysExportSheetServiceImpl.java

@@ -9,9 +9,10 @@ import cn.hutool.poi.excel.cell.CellUtil;
 import cn.tr.module.api.sys.storage.SysStorageApi;
 import cn.tr.module.excel.row.dto.SysExportRowDTO;
 import cn.tr.module.excel.row.service.ISysExportRowService;
-import org.apache.commons.io.IOUtils;
+import cn.tr.module.excel.sheet.enums.SheetImportStatus;
 import org.apache.poi.ss.usermodel.*;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import cn.tr.module.excel.sheet.repository.SysExportSheetRepository;
@@ -21,6 +22,8 @@ import cn.tr.module.excel.sheet.dto.SysExportSheetDTO;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.util.*;
+import java.util.stream.Collectors;
+
 import cn.tr.module.excel.sheet.service.ISysExportSheetService;
 import cn.tr.module.excel.mapper.SysExportSheetMapper;
 /**
@@ -32,12 +35,15 @@ import cn.tr.module.excel.mapper.SysExportSheetMapper;
 @Service
 public class SysExportSheetServiceImpl implements ISysExportSheetService {
     @Autowired
+    @Lazy
     private SysExportSheetRepository baseRepository;
 
     @Autowired
+    @Lazy
     private SysStorageApi sysStorageApi;
 
     @Autowired
+    @Lazy
     private ISysExportRowService rowService;
 
     /**
@@ -49,7 +55,16 @@ public class SysExportSheetServiceImpl implements ISysExportSheetService {
     @Override
     public SysExportSheetDTO selectSysExportSheetById(String id){
         return SysExportSheetMapper.INSTANCE.convertDto(baseRepository.selectById(id));
-    };
+    }
+
+    @Override
+    public boolean cancelImport(String id) throws Exception{
+        SysExportSheetPO exportSheet = baseRepository.selectById(id);
+        exportSheet.setStatus(SheetImportStatus.importCancel.getValue());
+        //取消导入生成导入excel
+        exportSheet.setExportFileId(createImportFile(exportSheet));
+        return true;
+    }
 
     /**
      * 新增导入工作簿记录表
@@ -86,7 +101,8 @@ public class SysExportSheetServiceImpl implements ISysExportSheetService {
     @Transactional(rollbackFor = Exception.class)
     public void updateRowResult(String sheetId, boolean success) throws Exception {
         SysExportSheetPO sheet = baseRepository.selectById(sheetId);
-        if(sheet==null){
+        if(sheet==null||SheetImportStatus.importCancel.getValue().equals(sheet.getStatus())){
+            //导入记录不存在或导入已取消
             return;
         }
         if(success){
@@ -95,12 +111,36 @@ public class SysExportSheetServiceImpl implements ISysExportSheetService {
             sheet.setFailCount(sheet.getFailCount()+1);
         }
         int importCount=sheet.getSuccessCount()+sheet.getFailCount();
-        sheet.setFinish(importCount==sheet.getTotalCount());
-        if(Boolean.TRUE.equals(sheet.getFinish())){
+        if(importCount==sheet.getTotalCount()&&
+                //解析完成并且导入数目相同
+                SheetImportStatus.parsingSuccess.getValue().equals(sheet.getStatus())){
+            //导入完成
+            sheet.setStatus(SheetImportStatus.importSuccess.getValue());
+            sheet.setEndTime(new Date());
+            //生成导出文件
+            sheet.setExportFileId(createImportFile(sheet));
+        }
+        baseRepository.updateById(sheet);
+    }
+
+    @Override
+    public void doSheetCallback(String sheetId, int totalCount) throws Exception {
+        SysExportSheetPO sheet = baseRepository.selectById(sheetId);
+        if(sheet==null){
+            return;
+        }
+        int importCount=sheet.getSuccessCount()+sheet.getFailCount();
+        if(importCount==totalCount){
+            //导入成功
+            sheet.setStatus(SheetImportStatus.importSuccess.getValue());
             sheet.setEndTime(new Date());
             //生成导出文件
             sheet.setExportFileId(createImportFile(sheet));
+        }else if(!SheetImportStatus.importCancel.getValue().equals(sheet.getStatus())){
+            //没有导入成功且导入未取消
+            sheet.setStatus(SheetImportStatus.parsingSuccess.getValue());
         }
+        sheet.setTotalCount(totalCount);
         baseRepository.updateById(sheet);
     }
 
@@ -108,29 +148,49 @@ public class SysExportSheetServiceImpl implements ISysExportSheetService {
         String sheetId = sheetPO.getId();
         byte[] fileContent = sysStorageApi.obtainContent(sheetPO.getImportFileId());
         List<SysExportRowDTO> rowRecords = rowService.selectSysExportRowBySheetId(sheetId);
+        //导入的行结果映射
+        Map<Integer, SysExportRowDTO> rowIndexMap = rowRecords.stream()
+                .collect(Collectors.groupingBy(SysExportRowDTO::getRowIndex, Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst)));
+
         File tempFile = FileUtil.createTempFile();
+
         IoUtil.write(FileUtil.getOutputStream(tempFile),true,fileContent);
         ExcelWriter excelWriter = ExcelUtil.getReader(tempFile).getWriter();
+        excelWriter.getWorkbook().removeSheetAt(1);
+        excelWriter.renameSheet(0,"导入结果");
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         byte[] content=null;
         try {
-            rowRecords.forEach(rowRecord->{
+            Sheet sheet = excelWriter.getSheet();
+            int lastRowNum =sheet.getLastRowNum();
+            int maxRowCount=lastRowNum;
+            while (lastRowNum>0){
                 String value="";
-                if(Boolean.TRUE.equals(rowRecord.getSuccess())){
-                    value="导入成功";
-                }else {
-                    value="失败原因:{"+rowRecord.getErrorMsg()+"}";
+                SysExportRowDTO rowRecord = rowIndexMap.get(lastRowNum);
+                if(rowRecord==null||!Boolean.TRUE.equals(rowRecord.getSuccess())){
+                    value="失败原因:{"+
+                            (Objects.isNull(rowRecord)?"导入中断":rowRecord.getErrorMsg())
+                            +"}";
+                    Cell cell = excelWriter.getOrCreateCell(sheetPO.getColumnCount() + 3, lastRowNum);
+                    CellUtil.setCellValue(cell,value);
+                    cell.setCellStyle(createFailCellStyle(excelWriter,false));
+                }else if(Boolean.TRUE.equals(rowRecord.getSuccess())){
+                    if(lastRowNum==maxRowCount){
+                        sheet.removeRow(sheet.getRow(lastRowNum));
+                    }else {
+                        sheet.shiftRows(lastRowNum+1,maxRowCount,-1);
+                    }
+
                 }
-                Cell cell = excelWriter.getOrCreateCell(rowRecord.getMaxColumnIndex() + 3, rowRecord.getRowIndex());
-                CellUtil.setCellValue(cell,value);
-                cell.setCellStyle(createFailCellStyle(excelWriter,Boolean.TRUE.equals(rowRecord.getSuccess())));
-            });
+                --lastRowNum;
+            }
             excelWriter.autoSizeColumn(CollectionUtil.getFirst(rowRecords).getMaxColumnIndex() + 3);
         }finally {
             excelWriter.flush(out);
             out.flush();
             content = out.toByteArray();
-            IOUtils.close(out,excelWriter);
+            IoUtil.close(out);
+            IoUtil.close(excelWriter);
         }
         if(content!=null){
             return sysStorageApi.upload(content,sheetPO.getFileName());

+ 12 - 2
tr-modules/tr-module-system/pom.xml

@@ -44,6 +44,11 @@
             <artifactId>tr-spring-boot-starter-plugin-satoken</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cn.tr</groupId>
+            <artifactId>tr-spring-boot-starter-plugin-doc</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.github.oshi</groupId>
             <artifactId>oshi-core</artifactId>
@@ -51,12 +56,12 @@
 
         <dependency>
             <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-biz-tenant</artifactId>
+            <artifactId>tr-spring-boot-starter-plugin-web</artifactId>
         </dependency>
 
         <dependency>
             <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-biz-bean-mapper</artifactId>
+            <artifactId>tr-spring-boot-starter-plugin-biz-tenant</artifactId>
         </dependency>
 
         <dependency>
@@ -94,5 +99,10 @@
             <artifactId>easy-captcha</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cn.tr</groupId>
+            <artifactId>tr-spring-boot-starter-plugin-cache</artifactId>
+        </dependency>
+
     </dependencies>
 </project>

+ 0 - 1
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/log/aspect/OperateLogAspect.java

@@ -16,7 +16,6 @@ import cn.tr.module.api.sys.log.bo.OperateLogBO;
 import cn.tr.module.api.sys.log.enums.LoginType;
 import cn.tr.module.sys.log.mapper.SysLogMapper;
 import cn.tr.module.sys.log.service.ISysLogService;
-import cn.tr.plugin.operatelog.strategy.OperateStrategy;
 import cn.tr.plugin.web.context.RequestContextHolder;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;

+ 7 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/storage/provider/SysStorageApiProvider.java

@@ -5,6 +5,8 @@ import cn.tr.module.sys.storage.service.IStorageFileService;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Component;
 
+import java.util.Collections;
+
 /**
  * @ClassName : SysStorageApiProvider
  * @Description :
@@ -20,6 +22,11 @@ public class SysStorageApiProvider implements SysStorageApi {
         return  storageFileService.upload(null,null,filename,content).getId();
     }
 
+    @Override
+    public void removeById(String fileId) {
+        storageFileService.remove(Collections.singleton(fileId));
+    }
+
     @Override
     public byte[] obtainContent(String recordId) throws Exception {
         return storageFileService.obtainContent(recordId);

+ 2 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/tenant/dto/SysTenantAddDTO.java

@@ -5,6 +5,7 @@ import cn.tr.core.validation.Update;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
@@ -37,6 +38,7 @@ public class SysTenantAddDTO implements Serializable {
 
     @ApiModelProperty(value = "管理账号",required = true)
     @NotEmpty(message = "管理账号不能为空",groups = {Integer.class, Update.class})
+    @Length(min = 4,max = 16,message = "管理账号长度在4~16之间")
     private String username;
 
     @ApiModelProperty("联系人电话")

+ 3 - 2
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/tenant/service/impl/SysTenantServiceImpl.java

@@ -105,7 +105,7 @@ public class SysTenantServiceImpl implements ISysTenantService {
             //创建角色
             roleService.insertInnerSysRole(buildRole(roleId));
             //创建租户用户
-            userService.insertSysUser(buildUser(userId,roleId,orgId,source.
+            userService.insertSysUser(buildUser(userId,portalId,roleId,orgId,source.
                     getUsername(),configManager.getCurrent().getDefaultPsw(),source.getName()));
             //关联用户和门户
             userPortalService.assignUserPortal(userId,Collections.singleton(portalId));
@@ -173,10 +173,11 @@ public class SysTenantServiceImpl implements ISysTenantService {
         return role;
     }
 
-    private SysUserDTO buildUser(String userId,String roleId,String orgId,String username,String password,String tenantName){
+    private SysUserDTO buildUser(String userId,String portalId,String roleId,String orgId,String username,String password,String tenantName){
         SysUserDTO user = new SysUserDTO();
         user.setId(userId);
         user.setOrgId(orgId);
+        user.setPortalIds(Collections.singleton(portalId));
         user.setUsername(username);
         user.setPassword(password);
         user.setNickname(tenantName);

+ 2 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserDTO.java

@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
@@ -34,6 +35,7 @@ public class SysUserDTO extends BaseDTO {
      * 用户名
      */
     @ApiModelProperty(value = "用户名",required = true)
+    @Length(min = 4,max = 16,message = "管理账号长度在4~16之间",groups = {Insert.class,Update.class})
     private String username;
 
     /**

+ 0 - 2
tr-plugins/pom.xml

@@ -29,10 +29,8 @@
         <module>tr-spring-boot-starter-plugin-desensitize</module>
         <module>tr-spring-boot-starter-plugin-doc</module>
         <module>tr-spring-boot-starter-plugin-mp-enhance-actable</module>
-        <module>tr-spring-boot-starter-plugin-biz-bean-mapper</module>
         <module>tr-spring-boot-starter-plugin-biz-constant</module>
         <module>tr-spring-boot-starter-plugin-numbering-strategy</module>
-        <module>tr-spring-boot-starter-plugin-import-export</module>
     </modules>
 
 </project>

+ 0 - 23
tr-plugins/tr-spring-boot-starter-plugin-biz-bean-mapper/pom.xml

@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>tr-plugins</artifactId>
-        <groupId>cn.tr</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <version>${revision}</version>
-    <artifactId>tr-spring-boot-starter-plugin-biz-bean-mapper</artifactId>
-
-
-    <dependencies>
-        <dependency>
-            <groupId>org.mapstruct</groupId>
-            <artifactId>mapstruct</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>

+ 2 - 10
tr-plugins/tr-spring-boot-starter-plugin-biz-tenant/src/main/java/cn/tr/plugin/biz/tenant/config/db/TenantDatabaseInterceptor.java

@@ -2,15 +2,11 @@ package cn.tr.plugin.biz.tenant.config.db;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.tr.core.strategy.LoginUserStrategy;
-import cn.tr.core.utils.ServletUtils;
 import cn.tr.plugin.biz.tenant.context.TenantContextHolder;
 import cn.tr.plugin.biz.tenant.properties.TenantProperties;
 import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.StringValue;
-
-import javax.servlet.http.HttpServletRequest;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -35,12 +31,8 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
 
     @Override
     public Expression getTenantId() {
-        HttpServletRequest request = ServletUtils.getRequest();
-        Boolean ignore = Boolean.TRUE.equals(TenantContextHolder.isIgnore());
-        if(request==null){
-            ignore=true;
-        }
-        return ignore?new StringValue(""):new StringValue(TenantContextHolder.getTenantId());
+        String tenantId = TenantContextHolder.getTenantId();
+        return new StringValue(tenantId);
     }
 
     @Override

+ 1 - 1
tr-plugins/tr-spring-boot-starter-plugin-biz-tenant/src/main/java/cn/tr/plugin/biz/tenant/context/TenantContextHolder.java

@@ -46,7 +46,7 @@ public class TenantContextHolder {
      * @return 是否忽略
      */
     public static Boolean isIgnore() {
-        return SecurityContextHolder.get(TenantConstant.TENANT_IGNORE,Boolean.class);
+        return Boolean.TRUE.equals(SecurityContextHolder.get(TenantConstant.TENANT_IGNORE,Boolean.class));
     }
 
 }

+ 0 - 43
tr-plugins/tr-spring-boot-starter-plugin-import-export/pom.xml

@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>tr-plugins</artifactId>
-        <groupId>cn.tr</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <version>${revision}</version>
-    <artifactId>tr-spring-boot-starter-plugin-import-export</artifactId>
-
-
-    <description>导入导出插件</description>
-    <dependencies>
-        <dependency>
-            <groupId>cn.tr</groupId>
-            <artifactId>tr-framework</artifactId>
-        </dependency>
-        <!-- excel工具 -->
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-ooxml</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-eventbus</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-test</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.tr</groupId>
-            <artifactId>tr-spring-boot-starter-plugin-satoken</artifactId>
-        </dependency>
-    </dependencies>
-</project>

+ 0 - 37
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/CompositeExcelTemplateFacade.java

@@ -1,37 +0,0 @@
-package cn.tr.plugin.excel;
-
-import cn.tr.core.context.SecurityContextHolder;
-import cn.tr.plugin.eventbus.annotation.Subscribe;
-import cn.tr.plugin.excel.im.*;
-import cn.tr.plugin.security.context.LoginUserContextHolder;
-import lombok.AllArgsConstructor;
-
-/**
- * @ClassName : CompositeExcelTemplateFacade
- * @Description : excel模板综合处理门面
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@AllArgsConstructor
-public class CompositeExcelTemplateFacade {
-    private final StdExcelImportCompositeRegister register;
-    public void register(StdExcelImportComposite composite){
-        register.register(composite);
-    }
-
-    public SheetResult importSheet(String code, SheetData source) throws Exception {
-        StdExcelImportComposite composite = register.get(code);
-        if(composite==null){
-            throw new UnsupportedOperationException("不支持在线导入当前文档");
-        }
-        return composite.importSheet(source);
-    }
-
-    @Subscribe("excel-import")
-    public void doImportSheet(RowData rowData) throws Exception {
-        LoginUserContextHolder.setUser(rowData.getImportUser());
-        StdExcelImportComposite importComposite = register.get(rowData.getCode());
-        importComposite.doImportSheet(rowData);
-        SecurityContextHolder.remove();
-    }
-}

+ 0 - 17
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/TrImExportAutoConfiguration.java

@@ -1,17 +0,0 @@
-package cn.tr.plugin.excel;
-
-import cn.tr.plugin.excel.im.StdExcelImportCompositeRegister;
-import org.springframework.context.annotation.Bean;
-/**
- * @ClassName : TrImExportAutoConfiguration
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public class TrImExportAutoConfiguration {
-    @Bean
-    public CompositeExcelTemplateFacade excelTemplateFacade(){
-        return new CompositeExcelTemplateFacade(new StdExcelImportCompositeRegister());
-    }
-}

+ 0 - 187
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/annatation/Excel.java

@@ -1,187 +0,0 @@
-package cn.tr.plugin.excel.annatation;
-
-import cn.hutool.core.date.DatePattern;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.math.BigDecimal;
-
-/**
- * 自定义导出Excel数据注解
- * 
- * @author ruoyi
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Excel {
-    /**
-     * 导出时在excel中排序
-     */
-    public int sort() default Integer.MAX_VALUE;
-
-    /**
-     * 导出到Excel中的名字.
-     */
-    public String name();
-
-    /**
-     * 日期格式, 如: yyyy-MM-dd
-     */
-    public String dateFormat() default DatePattern.CHINESE_DATE_TIME_PATTERN;
-
-    /**
-     * 当后边紧跟的单元格为空时,是否合并
-     */
-    public boolean mergeBlank() default false;
-
-    /**
-     * 当行数据一致时,合并行数据
-     */
-    public boolean mergeRowWhenSame() default false;
-
-    /**
-     * 字典码
-     */
-    public String dictCode() default "";
-
-    /**
-     * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
-     */
-    public int scale() default -1;
-
-    /**
-     * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
-     */
-    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
-
-    /**
-     * 导出时在excel中每个列的高度 单位为字符
-     */
-    public double height() default 14;
-
-    /**
-     * 导出时在excel中每个列的宽 单位为字符
-     */
-    public double width() default 16;
-
-    /**
-     * 文字后缀,如% 90 变成90%
-     */
-    public String suffix() default "";
-
-    /**
-     * 当值为空时,字段的默认值
-     */
-    public String defaultValue() default "";
-
-    /**
-     * 提示信息
-     */
-    public String prompt() default "";
-
-    /**
-     * 设置只能选择不能输入的列内容.默认 与{@link Excel#dictCode()} 保持一致
-     */
-    public String[] combo() default {};
-
-    /**
-     * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
-     */
-    public boolean needMerge() default false;
-
-    /**
-     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
-     */
-    public boolean isExport() default true;
-
-    /**
-     * 另一个类中的属性名称,支持多级获取,以小数点隔开
-     */
-    public String targetAttr() default "";
-
-    /**
-     * 是否自动统计数据,在最后追加一行统计数据总和
-     */
-    public boolean isStatistics() default false;
-
-    /**
-     * 导出类型(0数字 1字符串)
-     */
-    public ColumnType cellType() default ColumnType.STRING;
-
-    /**
-     * 导出列头背景色
-     */
-    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
-
-    /**
-     * 导出列头字体颜色
-     */
-    public IndexedColors headerColor() default IndexedColors.WHITE;
-
-    /**
-     * 导出单元格背景色
-     */
-    public IndexedColors backgroundColor() default IndexedColors.WHITE;
-
-    /**
-     * 导出单元格字体颜色
-     */
-    public IndexedColors color() default IndexedColors.BLACK;
-
-    /**
-     * 导出字段对齐方式
-     */
-    public HorizontalAlignment align() default HorizontalAlignment.CENTER;
-
-    /**
-     * 自定义数据处理器
-     */
-    public Class<?> handler() default ExcelHandlerAdapter.class;
-
-    /**
-     * 自定义数据处理器参数
-     */
-    public String[] args() default {};
-
-    /**
-     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
-     */
-    Type type() default Type.ALL;
-
-    public enum Type
-    {
-        ALL(0), EXPORT(1), IMPORT(2);
-        private final int value;
-
-        Type(int value)
-        {
-            this.value = value;
-        }
-
-        public int value()
-        {
-            return this.value;
-        }
-    }
-
-    public enum ColumnType
-    {
-        NUMERIC(0), STRING(1), IMAGE(2),HYPERLINKS(3);
-        private final int value;
-
-        ColumnType(int value)
-        {
-            this.value = value;
-        }
-
-        public int value()
-        {
-            return this.value;
-        }
-    }
-}

+ 0 - 19
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/annatation/ExcelHandlerAdapter.java

@@ -1,19 +0,0 @@
-package cn.tr.plugin.excel.annatation;
-
-/**
- * Excel数据格式处理适配器
- * 
- * @author ruoyi
- */
-public interface
-ExcelHandlerAdapter {
-    /**
-     * 格式化
-     * 
-     * @param value 单元格数据值
-     * @param args excel注解args参数组
-     *
-     * @return 处理后的值
-     */
-    Object format(Object value, String[] args);
-}

+ 0 - 46
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/config/ExcelThreadFactory.java

@@ -1,46 +0,0 @@
-package cn.tr.module.excel.core.config;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @ClassName : ExcelThreadFactory
- * @Description :
- * @Author : LF
- * @Date: 2023年03月15日
- */
-public class ExcelThreadFactory implements ThreadFactory {
-    private static final AtomicInteger poolNumber = new AtomicInteger(1);
-    private final ThreadGroup group;
-    private final AtomicInteger threadNumber = new AtomicInteger(1);
-    private final String namePrefix;
-
-    public ExcelThreadFactory() {
-
-        SecurityManager s = System.getSecurityManager();
-        group = (s != null) ? s.getThreadGroup() :
-                Thread.currentThread().getThreadGroup();
-        namePrefix = "excel-export-" +
-                poolNumber.getAndIncrement() +
-                "-thread-";
-    }
-
-
-    @Override
-    public Thread newThread(@NotNull Runnable r) {
-        Thread t = new Thread(group, r,
-                namePrefix + threadNumber.getAndIncrement(),
-                0);
-        if (t.isDaemon()){
-            t.setDaemon(false);
-        }
-        if (t.getPriority() != Thread.NORM_PRIORITY){
-            t.setPriority(Thread.NORM_PRIORITY);
-        }
-        return t;
-    }
-
-
-}

+ 0 - 21
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/constant/ImportConstant.java

@@ -1,21 +0,0 @@
-package cn.tr.plugin.excel.constant;
-
-/**
- * @ClassName : ImportConstant
- * @Description :导入常量
- * @Author : LF
- * @Date: 2023年05月18日
- */
-
-public interface ImportConstant {
-     String DEFAULT_SHEET_NAME="模板工作簿(请勿改动)";
-    /**
-     * 一次性导入最大数量
-     */
-     int IMPORT_MAX_COUNT=500;
-
-    /**
-     * 标题行数
-     */
-     int TITLE_NUM=0;
-}

+ 0 - 44
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/RowData.java

@@ -1,44 +0,0 @@
-package cn.tr.plugin.excel.im;
-
-import cn.tr.plugin.security.bo.UserLoginInfoBO;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.*;
-import java.io.Serializable;
-
-/**
- * @ClassName : RowData
- * @Description : 行数据内容
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Data
-@AllArgsConstructor(staticName = "of")
-@NoArgsConstructor
-public class RowData implements Serializable {
-    /**
-     * {@link StdExcelImportComposite#getCode()}
-     */
-    private String code;
-
-    private String sheetId;
-
-    private int rowNum;
-
-    private List<CellData> cells;
-
-    private UserLoginInfoBO importUser;
-
-    private Integer maxColumnIndex;
-
-    @AllArgsConstructor(staticName = "of")
-    @NoArgsConstructor
-    @Data
-    public static class CellData implements Serializable{
-        private int columnIndex;
-        private Object data;
-        private String fieldName;
-    }
-}

+ 0 - 37
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/RowResult.java

@@ -1,37 +0,0 @@
-package cn.tr.plugin.excel.im;
-
-import lombok.Data;
-
-/**
- * @ClassName : RowResult
- * @Description : 对行数据处理完成的结果
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Data
-public class RowResult {
-    /**
-     * 数据是否处理成功
-     */
-    private boolean success;
-
-    /**
-     * 数据处理错误信息
-     */
-    private String errorMsg;
-
-    /**
-     * 行数据所对应的工作簿id
-     */
-    private String sheetId;
-
-    /**
-     * 行数
-     */
-    private int rowIndex;
-
-    /**
-     * 处理时间 单位:毫秒
-     */
-    private int opTime;
-}

+ 0 - 24
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/SheetResult.java

@@ -1,24 +0,0 @@
-package cn.tr.plugin.excel.im;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * @ClassName : SheetResult
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Data
-@AllArgsConstructor(staticName = "of")
-public class SheetResult {
-    /**
-     * 工作簿id
-     */
-    private String sheetId;
-
-
-    private SheetResult(){
-
-    }
-}

+ 0 - 52
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/StdExcelImportComposite.java

@@ -1,52 +0,0 @@
-package cn.tr.plugin.excel.im;
-
-import cn.tr.plugin.eventbus.config.EventBus;
-import cn.tr.plugin.excel.im.handler.ExcelImportHandler;
-import cn.tr.plugin.excel.im.validate.ExcelImportValidate;
-import cn.tr.plugin.excel.im.validate.StdExcelImportValidate;
-import cn.tr.plugin.excel.utils.ExcelUtils;
-import lombok.Getter;
-
-import java.util.List;
-
-/**
- * @ClassName : StdExcelImportComposite
- * @Description : execl导入综合处理
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Getter
-public class StdExcelImportComposite<T> {
-    private Class<T> aClass;
-    private ExcelImportValidate<T> validate;
-    private ExcelImportHandler<T> handler;
-    private EventBus eventBus;
-    private String code;
-    public StdExcelImportComposite(String code,Class<T> aClass, ExcelImportHandler<T> handler,EventBus eventBus) {
-        this.aClass = aClass;
-        this.handler = handler;
-        this.validate = new StdExcelImportValidate<T>();
-        this.eventBus=eventBus;
-        this.code=code;
-    }
-
-    public StdExcelImportComposite(String code,Class<T> aClass, ExcelImportValidate<T> validate, ExcelImportHandler<T> handler) {
-        this.aClass = aClass;
-        this.validate = validate;
-        this.handler = handler;
-    }
-
-    public SheetResult importSheet(SheetData source) throws Exception {
-        validate.validateSheet(aClass,source.getSheet());
-        SheetResult sheetResult = handler.handleSheet(aClass, source);
-        List<RowData> rowData = ExcelUtils.importConvertRowData(code,aClass, sheetResult.getSheetId(), source.getSheet());
-        for (RowData rowDatum : rowData) {
-            eventBus.publishEx("excel-import",rowDatum);
-        }
-        return sheetResult;
-    }
-
-    public void doImportSheet(RowData rowData) throws Exception{
-        handler.handleRow(aClass,rowData);
-    }
-}

+ 0 - 31
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/StdExcelImportCompositeRegister.java

@@ -1,31 +0,0 @@
-package cn.tr.plugin.excel.im;
-
-import cn.tr.plugin.eventbus.annotation.Subscribe;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @ClassName : StdExcelImportCompositeRegister
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public class StdExcelImportCompositeRegister {
-    private Map<String,StdExcelImportComposite>  registerMap=new HashMap<>();
-
-    public void register(StdExcelImportComposite composite) throws UnsupportedOperationException{
-        String code = composite.getCode();
-        if(registerMap.containsKey(code)){
-            throw new UnsupportedOperationException("[register] key:"+code+" has exist");
-        }
-         registerMap.put(code,composite);
-    }
-
-    public StdExcelImportComposite get(String code) throws UnsupportedOperationException{
-        return registerMap.get(code);
-    }
-
-
-}

+ 0 - 86
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/handler/AbstractExcelImportHandler.java

@@ -1,86 +0,0 @@
-package cn.tr.plugin.excel.im.handler;
-
-
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.util.ReflectUtil;
-import cn.tr.plugin.excel.constant.ImportConstant;
-import cn.tr.plugin.excel.im.RowData;
-import cn.tr.plugin.excel.im.RowResult;
-import cn.tr.plugin.excel.im.SheetData;
-import cn.tr.plugin.excel.im.SheetResult;
-import cn.tr.plugin.excel.im.listener.RowHandlerListener;
-import cn.tr.plugin.excel.strategy.ExcelHandleSheetStrategy;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.springframework.util.ReflectionUtils;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * @Interface : ExcelImportHandler
- * @Description : execl导人数据处理接口
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public abstract class AbstractExcelImportHandler<T> implements ExcelImportHandler<T>{
-    private final List<RowHandlerListener> listeners=new ArrayList<>();
-
-    public AbstractExcelImportHandler(List<RowHandlerListener> listeners) {
-        if(CollectionUtil.isNotEmpty(listeners)){
-            this.listeners.addAll(listeners);
-        }
-    }
-
-    @Override
-    public SheetResult handleSheet(Class<T> clazz, SheetData sheetData) {
-        Sheet sheet = sheetData.getSheet();
-        sheetData.setTotalNum(sheet.getLastRowNum()- ImportConstant.TITLE_NUM);
-        String sheetId = ExcelHandleSheetStrategy.tr.handleSheet(sheetData);
-        return SheetResult.of(sheetId);
-    }
-
-    @Override
-    public RowResult handleRow(Class<T> clazz, RowData rowData) throws Exception{
-        RowResult rowResult=new RowResult();
-        rowResult.setSheetId(rowData.getSheetId());
-        rowResult.setRowIndex(rowData.getRowNum());
-        long startTime = System.currentTimeMillis();
-        try {
-             doHandleRow(buildObj(clazz, rowData),rowData.getSheetId(),rowData.getRowNum());
-             rowResult.setSuccess(true);
-        }catch (Exception e){
-            rowResult.setSuccess(false);
-            rowResult.setErrorMsg(ExceptionUtil.getMessage(e));
-        }
-        rowResult.setOpTime(Long.valueOf(System.currentTimeMillis()-startTime).intValue());
-
-        for (RowHandlerListener listener : listeners) {
-            listener.afterHandleRow(rowData,rowResult);
-        }
-        return rowResult;
-    }
-
-    public abstract void doHandleRow(T obj,String sheetId,int rowIndex);
-
-
-    private T buildObj(Class<T> clazz, RowData rowData){
-        List<RowData.CellData> cells = rowData.getCells();
-        Map<String, RowData.CellData> fieldNameMap = cells.stream()
-                .collect(Collectors.groupingBy(RowData.CellData::getFieldName, Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst)));
-        T obj= ReflectUtil.newInstance(clazz);
-        ReflectionUtils.doWithFields(clazz,field -> {
-            field.setAccessible(true);
-            RowData.CellData cellData = fieldNameMap.get(field.getName());
-            if(Objects.nonNull(cellData)){
-                Object data = cellData.getData();
-                Class<?> type = field.getType();
-                field.set(obj, Convert.convert(type, data));
-            }
-        });
-        return obj;
-    }
-
-}

+ 0 - 30
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/handler/ExcelImportHandler.java

@@ -1,30 +0,0 @@
-package cn.tr.plugin.excel.im.handler;
-
-import cn.tr.plugin.excel.im.RowData;
-import cn.tr.plugin.excel.im.RowResult;
-import cn.tr.plugin.excel.im.SheetData;
-import cn.tr.plugin.excel.im.SheetResult;
-/**
- * @Interface : ExcelImportHandler
- * @Description : execl导人数据处理接口
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public interface ExcelImportHandler<T> {
-    /**
-     * 行数据处理
-     * @param clazz   逻辑处理实体类
-     * @param rowData 行数据
-     * @return
-     */
-    RowResult handleRow(Class<T> clazz, RowData rowData) throws Exception;
-
-    /**
-     * 行数据处理
-     * @param clazz   逻辑处理实体类
-     * @param sheetData 工作簿数据
-     * @return
-     */
-    SheetResult handleSheet(Class<T> clazz, SheetData sheetData);
-}

+ 0 - 20
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/listener/RowHandlerListener.java

@@ -1,20 +0,0 @@
-package cn.tr.plugin.excel.im.listener;
-
-import cn.tr.plugin.excel.im.RowData;
-import cn.tr.plugin.excel.im.RowResult;
-
-/**
- * @ClassName : RowHandlerListener
- * @Description : 行数据处理监听器
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public interface RowHandlerListener {
-    /**
-     * 行数据处理完成后的监听器
-     * @param data   行数据
-     * @param result 处理结果
-     */
-    void afterHandleRow(RowData data, RowResult result) throws Exception;
-}

+ 0 - 21
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/validate/ExcelImportValidate.java

@@ -1,21 +0,0 @@
-package cn.tr.plugin.excel.im.validate;
-
-import org.apache.poi.ss.usermodel.Sheet;
-
-/**
- * @Interface : ExcelValidateHandler
- * @Description : excel导入数据校验接口
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public interface ExcelImportValidate<T> {
-    /**
-     * 对工作簿进行校验
-     * @param clazz 逻辑处理实体类
-     * @param sheet  工作簿
-     * @throws  Exception
-     * @return
-     */
-    void validateSheet(Class<T> clazz,Sheet sheet) throws Exception;
-}

+ 0 - 18
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/im/validate/StdExcelImportValidate.java

@@ -1,18 +0,0 @@
-package cn.tr.plugin.excel.im.validate;
-
-import cn.tr.plugin.excel.utils.ExcelUtils;
-import org.apache.poi.ss.usermodel.Sheet;
-
-/**
- * @ClassName : StdExcelImportValidate
- * @Description : 标准excel工作簿校验
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public class StdExcelImportValidate<T> implements ExcelImportValidate<T>{
-    @Override
-    public void validateSheet(Class<T> clazz, Sheet sheet) throws Exception {
-        ExcelUtils.validateSheetFormat(clazz,sheet);
-    }
-}

+ 0 - 25
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/strategy/ExcelHandleSheetStrategy.java

@@ -1,25 +0,0 @@
-package cn.tr.plugin.excel.strategy;
-
-import cn.tr.plugin.excel.im.SheetData;
-
-import java.util.function.Function;
-
-/**
- * @ClassName : ExcelHandleSheetStrategy
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public class ExcelHandleSheetStrategy {
-    private ExcelHandleSheetStrategy(){
-
-    }
-    public Function<SheetData,String> handleSheetFunction=sheet -> "";
-
-    public static ExcelHandleSheetStrategy tr=new ExcelHandleSheetStrategy();
-
-    public String handleSheet(SheetData sheet){
-        return handleSheetFunction.apply(sheet);
-    }
-}

+ 0 - 183
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/java/cn/tr/plugin/excel/utils/ExcelUtils.java

@@ -1,183 +0,0 @@
-package cn.tr.plugin.excel.utils;
-
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.ClassUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.tr.plugin.excel.annatation.Excel;
-import cn.tr.plugin.excel.constant.ImportConstant;
-import cn.tr.plugin.excel.im.RowData;
-import cn.tr.plugin.security.context.LoginUserContextHolder;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.text.DecimalFormat;
-import java.util.*;
-
-/**
- * @ClassName : ExcelUtils
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-@Slf4j
-public class ExcelUtils {
-
-    /**
-     * 对工作簿格式进行校验
-     * @param sheet
-     */
-    public static void validateSheetFormat(Class aClass,Sheet sheet){
-        String sheetName = sheet.getSheetName();
-        if(!StrUtil.equals(sheetName, ImportConstant.DEFAULT_SHEET_NAME)){
-            throw new UnsupportedOperationException("工作簿名称错误,导入失败");
-        }
-        Map<Integer, String> headIndexMap = createHeadIndexMap(sheet);
-        Map<String, String> fields = getFields(aClass);
-        if(CollectionUtil.size(headIndexMap.keySet())!=CollectionUtil.size(fields.keySet())){
-            throw new UnsupportedOperationException("工作簿列数错误,导入失败");
-        }
-        int lastRowNum = sheet.getLastRowNum();
-        if(lastRowNum>ImportConstant.IMPORT_MAX_COUNT){
-            throw new UnsupportedOperationException("一次性导入最大数量最大为"+ImportConstant.IMPORT_MAX_COUNT+"条");
-        }
-    }
-
-    public static List<RowData> importConvertRowData(String compositeCode,Class aClass, String sheetId, Sheet sheet){
-        List<RowData> result = new ArrayList<>();
-        // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
-        int rows = sheet.getLastRowNum();
-        if(rows>0){
-            // 定义一个map用于存放excel列的序号和表头.
-            Map<Integer, String> headIndexMap = createHeadIndexMap(sheet);
-            //对字段进行解析,将字段与表头对应
-            Map<String, String> excelNameMap = getFields(aClass);
-            // 从第2行开始取数据,默认第一行是表头.
-            for (int i =ImportConstant.TITLE_NUM + 1; i <= rows; i++){
-                Row row = sheet.getRow(i);
-                List<RowData.CellData> cells=createCellData(row,headIndexMap,excelNameMap);
-                result.add(RowData.of(compositeCode,sheetId,i,cells,LoginUserContextHolder.getUser(),CollectionUtil.size(cells)));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * 创建一个map用于存放excel列的序号和表头.
-     * @param sheet
-     * <pre>
-     * map.put(1,"姓名")
-     * map.put(2,"年龄")
-     * <pre/>
-     * @return
-     */
-    private static  Map<Integer, String> createHeadIndexMap(Sheet sheet){
-        Map<Integer, String> result = new HashMap<Integer, String>();
-        // 获取表头
-        Row head = sheet.getRow(ImportConstant.TITLE_NUM);
-        //对表头进行解析,将表头与列数进行对应
-        for (int i = 0; i < head.getPhysicalNumberOfCells(); i++) {
-            Cell cell = head.getCell(i);
-            if (ObjectUtil.isNotNull(cell)) {
-                //放入表头
-                result.put(i,cell.getStringCellValue());
-            }
-        }
-        return result;
-    }
-    /**
-     * 将cell转化为cellData,便于序列化传输
-     * @param row
-     * @return
-     */
-    private static List<RowData.CellData> createCellData(Row row,Map<Integer, String>  headNameMap,Map<String,String> excelNameMap){
-        List<RowData.CellData> result = new ArrayList<>();
-        headNameMap.forEach((index,headName)->{
-            Cell rowCell = row.getCell(index);
-            if(rowCell==null){
-                return;
-            }
-            String fieldName = excelNameMap.get(headName);
-            RowData.CellData cellData = RowData.CellData.of(index, getCellValue(rowCell), fieldName);
-            result.add(cellData);
-        });
-        return result;
-    }
-    /**
-     * 获取字段注解信息
-     * @return  map
-     * <pre>
-     *     map.put("用户名","username")
-     *     map.put("密码","psw")
-     * <pre/>
-     */
-    private static Map<String, String> getFields(Class aClazz) {
-        Map<String, String> map = new HashMap<>();
-        Field[] fields = ClassUtil.getDeclaredFields(aClazz);
-        for (Field field : fields) {
-            Excel excel = field.getAnnotation(Excel.class);
-            if(excel==null){
-                continue;
-            }
-            //字段名称
-            String fieldName = field.getName();
-            //表头名称
-            String excelName = excel.name();
-            if (map.containsKey(excelName)) {
-                log.warn("[getFields] class:{},excelName:{},重复存在",aClazz.getName(),excelName);
-            }else {
-                map.put(excelName,fieldName);
-            }
-        }
-        return map;
-    }
-
-    /**
-     * 获取单元格值
-     *
-     * @param cell 单元格
-     * @return 单元格值
-     */
-    private static Object getCellValue(Cell cell) {
-        if(cell==null){
-            return null;
-        }
-        Object val=null;
-        try {
-            if (ObjectUtil.isNotNull(cell)) {
-                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) {
-                    val = cell.getNumericCellValue();
-                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
-                        val = org.apache.poi.ss.usermodel.DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
-                    }
-                    else {
-                        if ((Double) val % 1 != 0) {
-                            val = new BigDecimal(val.toString());
-                        }
-                        else {
-                            val = new DecimalFormat("0").format(val);
-                        }
-                    }
-                }
-                else if (cell.getCellType() == CellType.STRING) {
-                    val = cell.getStringCellValue();
-                }
-                else if (cell.getCellType() == CellType.BOOLEAN) {
-                    val = cell.getBooleanCellValue();
-                }
-                else if (cell.getCellType() == CellType.ERROR) {
-                    val = cell.getErrorCellValue();
-                }
-
-            }
-        }
-        catch (Exception e) {
-            return val;
-        }
-        return val;
-    }
-}

+ 0 - 1
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1 +0,0 @@
-cn.tr.plugin.excel.TrImExportAutoConfiguration

+ 0 - 60
tr-plugins/tr-spring-boot-starter-plugin-import-export/src/test/java/cn/tr/plugin/excel/utils/ExcelImportUtilTest.java

@@ -1,60 +0,0 @@
-package cn.tr.plugin.excel.utils;
-
-import cn.hutool.core.date.DateUtil;
-import cn.tr.plugin.excel.annatation.Excel;
-import cn.tr.plugin.excel.im.RowData;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import org.apache.poi.ss.usermodel.*;
-import org.junit.jupiter.api.Test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @ClassName : ExcelImportUtilTest
- * @Description :
- * @Author : LF
- * @Date: 2023年05月15日
- */
-
-public class ExcelImportUtilTest {
-    @Test
-    public void convertRowData() throws IOException {
-        Workbook sheets = WorkbookFactory.create(true);
-        Sheet sheet = sheets.createSheet("test");
-        Row row = sheet.createRow(1);
-        row.createCell(0).setCellValue("姓名");
-        row.createCell(1).setCellValue("生日");
-        row.createCell(2).setCellValue("年龄");
-        ArrayList<User> users = new ArrayList<>();
-        users.add( User.of("测试1", DateUtil.now(), 20));
-        users.add( User.of("测试2",DateUtil.now(), 21));
-        users.add( User.of("测试3", DateUtil.now(), 22));
-
-        for (int i = 2; i < 5; i++) {
-            Row r = sheet.createRow(i);
-            User user = users.get(i - 2);
-            r.createCell(0).setCellValue(user.getName());
-            r.createCell(1).setCellValue(user.getBirthday());
-            r.createCell(2).setCellValue(user.getAge());
-        }
-        List<RowData> rowData = ExcelUtils.importConvertRowData("123",User.class, "123", sheet);
-        System.out.println(rowData);
-    }
-
-
-
-    @AllArgsConstructor(staticName = "of")
-    @Data
-    static class User{
-        @Excel(name = "姓名")
-        private String name;
-        @Excel(name = "生日")
-        private String  birthday;
-        @Excel(name = "年龄")
-        private Integer age;
-    }
-
-}

+ 1 - 0
tr-test/src/main/resources/application-doc.yml

@@ -14,6 +14,7 @@ knife4j:
         api-rule-resources:
           - cn.tr.module.sys
           - cn.tr.module.file
+          - cn.tr.module.excel
       gen:
         group-name: 代码生成器
         api-rule: package

+ 53 - 46
tr-test/src/test/java/cn/tr/module/excel/CompositeExcelTemplateFacadeTest.java

@@ -1,36 +1,39 @@
 package cn.tr.module.excel;
 
+import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.poi.excel.ExcelUtil;
 import cn.tr.core.utils.JsonUtils;
-import cn.tr.module.excel.sheet.service.IExcelService;
+import cn.tr.core.validation.Insert;
+import cn.tr.module.api.export.annotation.ExcelPropertySupport;
+import cn.tr.module.api.export.handler.AbstractDataHandler;
+import cn.tr.module.excel.core.converter.DictItemConverter;
+import cn.tr.module.excel.core.service.ExcelService;
+import cn.tr.plugin.biz.tenant.context.TenantContextHolder;
 import cn.tr.plugin.eventbus.config.EventBus;
-import cn.tr.plugin.excel.CompositeExcelTemplateFacade;
-import cn.tr.plugin.excel.annatation.Excel;
-import cn.tr.plugin.excel.im.RowResult;
-import cn.tr.plugin.excel.im.StdExcelImportComposite;
-import cn.tr.plugin.excel.im.handler.AbstractExcelImportHandler;
-import cn.tr.plugin.excel.im.listener.RowHandlerListener;
 import cn.tr.plugin.security.bo.UserLoginInfoBO;
 import cn.tr.plugin.security.context.LoginUserContextHolder;
 import cn.tr.test.WebApplication;
-import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.ExcelWriter;
 import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
-import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
 import org.springframework.test.context.ActiveProfiles;
 
-import java.util.List;
+import javax.validation.constraints.NotNull;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @ClassName : CompositeExcelTemplateFacadeTest
@@ -40,67 +43,71 @@ import java.util.List;
  */
 @Slf4j
 @SpringBootTest(classes = WebApplication.class)
+@Import(CompositeExcelTemplateFacadeTest.UserEx.class)
 @ActiveProfiles // 设置使用 application-unit-test 配置文件
 public class CompositeExcelTemplateFacadeTest {
-    @Autowired
-    private CompositeExcelTemplateFacade templateFacade;
-
-    @Autowired(required = false)
-    private List<RowHandlerListener> listeners;
 
     @Autowired
     private EventBus eventBus;
 
     @Autowired
-    private IExcelService excelService;
+    private ExcelService excelService;
     @Test
     public void importTest() throws Exception {
         LoginUserContextHolder.setUser(UserLoginInfoBO.builder()
                 .userId("1")
                 .username("admin")
                 .tenantId("1")
-        .build());
-        StdExcelImportComposite importComposite = new StdExcelImportComposite("test", User.class, new CompositeExcelTemplateTest(listeners), eventBus);
-        templateFacade.register(importComposite);
-        byte[] content = FileUtil.readBytes("C:\\Users\\JR\\Desktop\\test.xls");
-        excelService.importStream("test",content,"test.xls");
-        while (true){
-
-        }
-    }
-
-    static class CompositeExcelTemplateTest extends AbstractExcelImportHandler<User> {
+                .build());
+        TenantContextHolder.setTenantId("1");
+        TenantContextHolder.setIgnore(false);
+        FileInputStream fileInputStream = new FileInputStream(FileUtil.touch("C:\\Users\\JR\\Desktop\\test1.xlsx"));
+        String sss = excelService.importExcel("test.xlsx", fileInputStream, User.class);
+        System.out.println(sss);
 
-        public CompositeExcelTemplateTest(List<RowHandlerListener> list) {
-            super(list);
-        }
+//        excelService.importStream("test",content,"test.xls");
+        while (true){
 
-        @Override
-        public void doHandleRow(User obj, String sheetId, int rowIndex) {
-            log.info("接收到导入消息,", JsonUtils.toJsonString(obj));
-            int i = RandomUtil.randomInt(-1, 1);
-            System.out.println(1 / i);
         }
     }
 
     @Test
-    public void exportTemplate(){
-
-        ExcelWriter build = EasyExcel.write("C:\\Users\\JR\\Desktop\\test1.xls", User.class)
-                .build();
+    public void exportTemplate() throws IOException {
+        BufferedOutputStream outputStream = FileUtil.getOutputStream(FileUtil.file("C:\\Users\\JR\\Desktop\\test1.xls"));
+        byte[] bytes = excelService.exportExcel(User.class, Stream.of(User.of("测试", new Date(), 18, "1"), User.of("测试2", new Date(), 18, "2")).collect(Collectors.toList()));
+        outputStream.write(bytes);
+        outputStream.flush();
+        while (true){
 
+        }
     }
 
     @AllArgsConstructor(staticName = "of")
     @Data
     @NoArgsConstructor
-    static class User{
+    public static class User implements Serializable {
         @ExcelProperty("姓名")
         private String name;
         @ExcelProperty("生日")
-        private String  birthday;
+        @DateTimeFormat(DatePattern.CHINESE_DATE_TIME_PATTERN)
+        private Date  birthday;
         @ExcelProperty("年龄")
         private Integer age;
+        @ExcelProperty(value = "性别",converter = DictItemConverter.class)
+        @ExcelPropertySupport(dictCode = "sys_sex")
+        @NotNull(message = "性别不能为空")
+        private String sex;
     }
 
+    public static class UserEx extends AbstractDataHandler<User>{
+
+        public UserEx() {
+            super(User.class);
+        }
+
+        @Override
+        public void doHandle(User obj) {
+            System.out.println("接收到数据>>>>>>>>>>>>>:" + JsonUtils.toJsonString(obj));
+        }
+    }
 }