ソースを参照

开票预设—easyExcel导入导出

ZhangWenQiang 3 年 前
コミット
9ac05d5c0d
39 ファイル変更1935 行追加38 行削除
  1. 20 0
      happy-cloud-system/happy-cloud-system-api/src/main/java/org/jeecg/modules/api/SysBaseRemoteApi.java
  2. 13 0
      happy-cloud-system/happy-cloud-system-api/src/main/java/org/jeecg/modules/api/fallback/SysBaseRemoteApiFallbackImpl.java
  3. 25 0
      happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java
  4. 2 0
      happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java
  5. 7 0
      happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml
  6. 1 0
      happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/service/ISysDictService.java
  7. 6 0
      happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.java
  8. 34 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
  9. 96 30
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/controller/HlwInvoiceCategoryController.java
  10. 13 5
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/entity/HlwInvoiceCategory.java
  11. 5 1
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/mapper/HlwInvoiceCategoryMapper.java
  12. 15 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/mapper/xml/HlwInvoiceCategoryMapper.xml
  13. 9 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/service/IHlwInvoiceCategoryService.java
  14. 34 1
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/service/impl/HlwInvoiceCategoryServiceImpl.java
  15. 81 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/DictUtils.java
  16. 303 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/ExcelUtil.java
  17. 212 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/ImportDataListener.java
  18. 147 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/JsonUtils.java
  19. 64 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/converter/ExcelDateConverter.java
  20. 87 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/converter/ExcelDictConverter.java
  21. 147 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/match/ExcelImportMapUtil.java
  22. 43 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/match/ExcelMatch.java
  23. 17 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/properties/ExportProperties.java
  24. 21 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/properties/ImportProperties.java
  25. 38 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/BankCard.java
  26. 42 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/BankCardValidator.java
  27. 40 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/DateTimeFormat.java
  28. 42 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/DateTimeFormatValidator.java
  29. 37 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/IdCard.java
  30. 55 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/IdCardValidator.java
  31. 37 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/Phone.java
  32. 40 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/PhoneValidator.java
  33. 11 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Delete.java
  34. 10 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/ExcelImport.java
  35. 11 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Get.java
  36. 12 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Save.java
  37. 12 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Update.java
  38. 137 0
      happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/ValidList.java
  39. 9 1
      pom.xml

+ 20 - 0
happy-cloud-system/happy-cloud-system-api/src/main/java/org/jeecg/modules/api/SysBaseRemoteApi.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.api;
 import com.alibaba.fastjson.JSONObject;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.constant.ServiceNameConstants;
+import org.jeecg.common.system.vo.DictModel;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.api.factory.SysBaseRemoteApiFallbackFactory;
 import org.jeecg.modules.api.fallback.SysBaseRemoteApiFallbackImpl;
@@ -10,6 +11,8 @@ import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * @Description: TODO
  * @author: scott
@@ -39,6 +42,23 @@ public interface SysBaseRemoteApi {
     String queryDictTextByKey(@RequestParam("code") String code, @RequestParam("key") String key);
 
     /**
+     * 通过编码和存储的text查询字典value、
+     *
+     * @return
+     */
+    @GetMapping("/sys/user/queryDictKeyByText")
+    Integer queryDictKeyByText(@RequestParam("code") String code, @RequestParam("text") String text);
+
+    /**
+     * 通过查询指定code 获取字典
+     *
+     * @param code
+     * @return
+     */
+    @GetMapping("/sys/user/queryDictItemsByCode")
+    List<DictModel> queryDictItemsByCode(@RequestParam("code") String code);
+
+    /**
      * 通过编码和存储的value查询表字典的text
      *
      * @param table 表名

+ 13 - 0
happy-cloud-system/happy-cloud-system-api/src/main/java/org/jeecg/modules/api/fallback/SysBaseRemoteApiFallbackImpl.java

@@ -4,10 +4,13 @@ import com.alibaba.fastjson.JSONObject;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.vo.DictModel;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.api.SysBaseRemoteApi;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
+
 /**
  * @author scott
  * @date 2020/05/22
@@ -37,6 +40,16 @@ public class SysBaseRemoteApiFallbackImpl implements SysBaseRemoteApi {
     }
 
     @Override
+    public Integer queryDictKeyByText(String code, String text) {
+        return null;
+    }
+
+    @Override
+    public List<DictModel> queryDictItemsByCode(String code) {
+        return null;
+    }
+
+    @Override
     public String queryTableDictTextByKey(String table, String text, String code, String key) {
         log.info("--查询表字典信息异常, table:" + table + ", text:" + text + ", code:" + code + ", key:" + key, cause);
         return null;

+ 25 - 0
happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java

@@ -20,6 +20,7 @@ import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.system.util.JwtUtil;
+import org.jeecg.common.system.vo.DictModel;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.system.vo.SysUserCacheInfo;
 import org.jeecg.common.util.PasswordUtil;
@@ -1251,6 +1252,30 @@ public class SysUserController {
         return sysDictService.queryDictTextByKey(code, key);
     }
 
+
+    /**
+     * 通过编码和存储的text查询字典value
+     *
+     * @param code
+     * @param text
+     * @return
+     */
+    @GetMapping(value = "/queryDictKeyByText")
+    public Integer queryDictKeyByText(@RequestParam(name = "code") String code, @RequestParam(name = "text") String text) {
+        return sysDictService.queryDictKeyByText(code, text);
+    }
+
+    /**
+     * 通过查询指定code 获取字典
+     *
+     * @param code
+     * @return
+     */
+    @GetMapping(value = "/queryDictItemsByCode")
+    public List<DictModel> queryDictItemsByCode(@RequestParam(name = "code") String code) {
+        return sysDictService.queryDictItemsByCode(code);
+    }
+
     /**
      * 通过编码和存储的value查询表字典的text
      *

+ 2 - 0
happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDictMapper.java

@@ -115,4 +115,6 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
 	 */
 	@Deprecated
 	public Page<DictModel> queryDictTablePageList(Page page, @Param("query") DictQuery query);
+
+    Integer queryDictKeyByText(@Param("code")String code,@Param("text") String text);
 }

+ 7 - 0
happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml

@@ -106,4 +106,11 @@
 		</if>
 	</select>
 
+	<!-- 通过字典code获取字典数据 -->
+	<select id="queryDictKeyByText"   resultType="Integer">
+		   select s.item_value from sys_dict_item s
+		   where s.dict_id = (select id from sys_dict where dict_code = #{code})
+		   and s.item_text = #{text}
+	</select>
+
 </mapper>

+ 1 - 0
happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/service/ISysDictService.java

@@ -116,4 +116,5 @@ public interface ISysDictService extends IService<SysDict> {
 	@Deprecated
 	public List<DictModel> queryDictTablePageList(DictQuery query,int pageSize, int pageNo);
 
+    Integer queryDictKeyByText(String code, String text);
 }

+ 6 - 0
happy-cloud-system/happy-cloud-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.java

@@ -90,6 +90,12 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
 		return sysDictMapper.queryDictTextByKey(code, key);
 	}
 
+	@Override
+	public Integer queryDictKeyByText(String code, String text) {
+		return sysDictMapper.queryDictKeyByText(code, text);
+	}
+
+
 	/**
 	 * 通过查询指定table的 text code 获取字典
 	 * dictTableCache采用redis缓存有效期10分钟

+ 34 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java

@@ -0,0 +1,34 @@
+package com.alibaba.excel.annotation;
+
+import com.alibaba.excel.converters.AutoConverter;
+import com.alibaba.excel.converters.Converter;
+
+import java.lang.annotation.*;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2021/12/3 17:28
+ * @Description:
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface ExcelProperty {
+    String[] value() default {""};
+
+    int index() default -1;
+
+    int order() default 2147483647;
+
+    Class<? extends Converter<?>> converter() default AutoConverter.class;
+
+    String dictTable() default "";
+
+    String dictCode() default "";
+
+    String dicText() default "";
+
+    /** @deprecated */
+    @Deprecated
+    String format() default "";
+}

+ 96 - 30
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/controller/HlwInvoiceCategoryController.java

@@ -1,41 +1,33 @@
 package org.jeecg.modules.hlwinvoice.controller;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jeecg.common.api.vo.Result;
-import org.jeecg.common.system.query.QueryGenerator;
-import org.jeecg.common.util.oConvertUtils;
-import org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory;
-import org.jeecg.modules.hlwinvoice.service.IHlwInvoiceCategoryService;
-
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-
-import org.jeecgframework.poi.excel.ExcelImportUtil;
-import org.jeecgframework.poi.excel.def.NormalExcelConstants;
-import org.jeecgframework.poi.excel.entity.ExportParams;
-import org.jeecgframework.poi.excel.entity.ImportParams;
-import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.jeecg.boot.starter.lock.client.RedissonLockClient;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory;
+import org.jeecg.modules.hlwinvoice.service.IHlwInvoiceCategoryService;
+import org.jeecg.modules.hlwsubcontractor.entity.HlwSubcontractorInvoiceCategory;
+import org.jeecg.modules.hlwsubcontractor.service.IHlwSubcontractorInvoiceCategoryService;
+import org.jeecg.modules.utils.excel.ExcelUtil;
+import org.jeecg.modules.utils.excel.properties.ImportProperties;
+import org.redisson.api.RLock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
-import com.alibaba.fastjson.JSON;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.jeecg.common.aspect.annotation.AutoLog;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
 
 /**
  * @Description: hlw_invoice_category
@@ -50,6 +42,12 @@ import org.jeecg.common.aspect.annotation.AutoLog;
 public class HlwInvoiceCategoryController extends JeecgController<HlwInvoiceCategory, IHlwInvoiceCategoryService> {
     @Autowired
     private IHlwInvoiceCategoryService hlwInvoiceCategoryService;
+    @Autowired
+    private IHlwSubcontractorInvoiceCategoryService hlwSubcontractorInvoiceCategoryService;
+    @Autowired
+    private ImportProperties importProperties;
+    @Resource
+    private RedissonLockClient redissonLockClient;
 
     /**
      * 分页列表查询
@@ -67,9 +65,9 @@ public class HlwInvoiceCategoryController extends JeecgController<HlwInvoiceCate
                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                    HttpServletRequest req) {
-        QueryWrapper<HlwInvoiceCategory> queryWrapper = QueryGenerator.initQueryWrapper(hlwInvoiceCategory, req.getParameterMap());
+        QueryWrapper<HlwInvoiceCategory> queryWrapper = QueryGenerator.initQueryWrapperForRule(hlwInvoiceCategory, req.getParameterMap());
         Page<HlwInvoiceCategory> page = new Page<HlwInvoiceCategory>(pageNo, pageSize);
-        IPage<HlwInvoiceCategory> pageList = hlwInvoiceCategoryService.page(page, queryWrapper);
+        Page<HlwInvoiceCategory> pageList = hlwInvoiceCategoryService.pageList(page, hlwInvoiceCategory, queryWrapper);
         return Result.ok(pageList);
     }
 
@@ -124,6 +122,12 @@ public class HlwInvoiceCategoryController extends JeecgController<HlwInvoiceCate
     @ApiOperation(value = "hlw_invoice_category-通过id删除", notes = "hlw_invoice_category-通过id删除")
     @DeleteMapping(value = "/delete")
     public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
+        QueryWrapper<HlwSubcontractorInvoiceCategory> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("invoice_category_id", id);
+        int count = hlwSubcontractorInvoiceCategoryService.count(queryWrapper);
+        if (count > 0) {
+            return Result.error("该开票内容已应用到服务商配置,无法删除!");
+        }
         hlwInvoiceCategoryService.removeById(id);
         return Result.ok("删除成功!");
     }
@@ -171,6 +175,33 @@ public class HlwInvoiceCategoryController extends JeecgController<HlwInvoiceCate
     }
 
     /**
+     * 导出excel(根据模板导出使用)
+     *
+     * @param request
+     * @param hlwInvoiceCategory
+     */
+    @ResponseBody
+    @RequestMapping(value = "/exportDataXls")
+    public void exportDataXls(HttpServletRequest request, HttpServletResponse response, HlwInvoiceCategory hlwInvoiceCategory) {
+        // Step.1 组装查询条件
+        QueryWrapper<HlwInvoiceCategory> queryWrapper = QueryGenerator.initQueryWrapperForRule(hlwInvoiceCategory, request.getParameterMap());
+        // Step.2 获取导出数据
+        List<HlwInvoiceCategory> exportList = new ArrayList<HlwInvoiceCategory>();
+        //开始查询数据时间
+        long start = System.currentTimeMillis();
+        log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
+        //结束查询数据时间
+        log.info("开始写入");
+        // Step.3 EasyExcel 导出Excel
+        try {
+            ExcelUtil.exportExcelByTemplateWeb(response, "开票内容表模板", importProperties.getInvoiceCategory(), new HashMap(), exportList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.info("导出报错===" + e.getMessage());
+        }
+    }
+
+    /**
      * 通过excel导入数据
      *
      * @param request
@@ -179,7 +210,42 @@ public class HlwInvoiceCategoryController extends JeecgController<HlwInvoiceCate
      */
     @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
     public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
-        return super.importExcel(request, response, HlwInvoiceCategory.class);
+        Result<?> result = new Result<>();
+        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
+        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
+            MultipartFile file = entity.getValue();// 获取上传文件对象
+            boolean getLock = false;
+            String lockName = "invoiceCategoryExcel";
+            try {
+                getLock = redissonLockClient.tryLock(lockName, 0, 60);
+                if (getLock) {
+                    result = hlwInvoiceCategoryService.importExcelGeneral(file);
+                    return result;
+                } else {
+                    return Result.error("排队中,请稍后重试!");
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error(e.getMessage(), e);
+                return Result.error("文件导入失败: " + e.getMessage());
+            } finally {
+                try {
+                    file.getInputStream().close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                /**
+                 * 解锁时,加了lock.isHeldByCurrentThread(),它的意思是查询当前线程是否持有此锁定,
+                 * 如果还持有,则释放,如果未持有,则说明已被释放;
+                 */
+                RLock rLock = redissonLockClient.getLock(lockName);
+                if (getLock && rLock.isHeldByCurrentThread()) {
+                    redissonLockClient.unlock(lockName);
+                }
+            }
+        }
+        return Result.error("文件导入失败!");
     }
 
 }

+ 13 - 5
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/entity/HlwInvoiceCategory.java

@@ -5,6 +5,8 @@ import java.io.UnsupportedEncodingException;
 import java.util.Date;
 import java.math.BigDecimal;
 
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -18,15 +20,17 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import javax.validation.constraints.NotBlank;
+
 /**
  * @Description: hlw_invoice_category
  * @Author: jeecg-boot
  * @Date: 2022-10-26
  * @Version: V1.0
  */
+@ExcelIgnoreUnannotated
 @Data
 @TableName("hlw_invoice_category")
-@Accessors(chain = true)
 @EqualsAndHashCode(callSuper = false)
 @ApiModel(value = "hlw_invoice_category对象", description = "hlw_invoice_category")
 public class HlwInvoiceCategory implements Serializable {
@@ -41,25 +45,29 @@ public class HlwInvoiceCategory implements Serializable {
     /**
      * 开票内容代码
      */
-    @Excel(name = "开票内容代码", width = 15)
+    @NotBlank(message = "开票内容代码不允许为空")
+    @ExcelProperty(index = 0)
     @ApiModelProperty(value = "开票内容代码")
     private java.lang.String invoiceCategoryCode;
     /**
      * 开票内容
      */
-    @Excel(name = "开票内容", width = 15)
+    @NotBlank(message = "开票内容不允许为空")
+    @ExcelProperty(index = 1)
     @ApiModelProperty(value = "开票内容")
     private java.lang.String invoiceCategoryName;
     /**
      * 税收分类代码
      */
-    @Excel(name = "税收分类代码", width = 15)
+    @NotBlank(message = "税收分类代码不允许为空")
+    @ExcelProperty(index = 2)
     @ApiModelProperty(value = "税收分类代码")
     private java.lang.String taxCategoryCode;
     /**
      * 税收分类名称
      */
-    @Excel(name = "税收分类名称", width = 15)
+    @NotBlank(message = "税收分类名称不允许为空")
+    @ExcelProperty(index = 3)
     @ApiModelProperty(value = "税收分类名称")
     private java.lang.String taxCategoryName;
     /**

+ 5 - 1
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/mapper/HlwInvoiceCategoryMapper.java

@@ -2,6 +2,9 @@ package org.jeecg.modules.hlwinvoice.mapper;
 
 import java.util.List;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
 import org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -9,9 +12,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 /**
  * @Description: hlw_invoice_category
  * @Author: jeecg-boot
- * @Date:   2022-10-26
+ * @Date: 2022-10-26
  * @Version: V1.0
  */
 public interface HlwInvoiceCategoryMapper extends BaseMapper<HlwInvoiceCategory> {
 
+    List<HlwInvoiceCategory> findList(Page<HlwInvoiceCategory> page, @Param("hlwInvoiceCategory") HlwInvoiceCategory hlwInvoiceCategory, @Param(Constants.WRAPPER) QueryWrapper<HlwInvoiceCategory> queryWrapper);
 }

+ 15 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/mapper/xml/HlwInvoiceCategoryMapper.xml

@@ -2,4 +2,19 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.jeecg.modules.hlwinvoice.mapper.HlwInvoiceCategoryMapper">
 
+    <select id="findList" resultType="org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory">
+        select
+        a.*
+        from hlw_invoice_category a
+        <where>
+            <if test="hlwInvoiceCategory.invoiceCategoryName != null and hlwInvoiceCategory.invoiceCategoryName !=''">
+                and a.invoice_category_name like concat('%',#{hlwInvoiceCategory.invoiceCategoryName},'%')
+            </if>
+            <if test="hlwInvoiceCategory.taxCategoryName != null and hlwInvoiceCategory.taxCategoryName !=''">
+                and a.tax_category_name like concat('%',#{hlwInvoiceCategory.taxCategoryName},'%')
+            </if>
+        </where>
+        order by a.create_time desc, a.id desc
+    </select>
+
 </mapper>

+ 9 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/service/IHlwInvoiceCategoryService.java

@@ -1,7 +1,13 @@
 package org.jeecg.modules.hlwinvoice.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
 
 /**
  * @Description: hlw_invoice_category
@@ -11,4 +17,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface IHlwInvoiceCategoryService extends IService<HlwInvoiceCategory> {
 
+    Page<HlwInvoiceCategory> pageList(Page<HlwInvoiceCategory> page, HlwInvoiceCategory hlwInvoiceCategory, QueryWrapper<HlwInvoiceCategory> queryWrapper);
+
+    Result<?> importExcelGeneral(MultipartFile file) throws IOException;
 }

+ 34 - 1
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/hlwinvoice/service/impl/HlwInvoiceCategoryServiceImpl.java

@@ -1,19 +1,52 @@
 package org.jeecg.modules.hlwinvoice.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.hlwinvoice.entity.HlwInvoiceCategory;
 import org.jeecg.modules.hlwinvoice.mapper.HlwInvoiceCategoryMapper;
 import org.jeecg.modules.hlwinvoice.service.IHlwInvoiceCategoryService;
+import org.jeecg.modules.utils.excel.ExcelUtil;
+import org.jeecg.modules.utils.excel.ImportDataListener;
 import org.springframework.stereotype.Service;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
 
 /**
  * @Description: hlw_invoice_category
  * @Author: jeecg-boot
- * @Date:   2022-10-26
+ * @Date: 2022-10-26
  * @Version: V1.0
  */
+@Slf4j
 @Service
 public class HlwInvoiceCategoryServiceImpl extends ServiceImpl<HlwInvoiceCategoryMapper, HlwInvoiceCategory> implements IHlwInvoiceCategoryService {
 
+    @Override
+    public Page<HlwInvoiceCategory> pageList(Page<HlwInvoiceCategory> page, HlwInvoiceCategory hlwInvoiceCategory, QueryWrapper<HlwInvoiceCategory> queryWrapper) {
+        List<HlwInvoiceCategory> list = baseMapper.findList(page, hlwInvoiceCategory, queryWrapper);
+        return page.setRecords(list);
+    }
+
+    @Override
+    public Result<?> importExcelGeneral(MultipartFile file) throws IOException {
+        ExcelUtil.importExcel(file.getInputStream(), HlwInvoiceCategory.class, 2, new ImportDataListener(true) {
+            @Override
+            public void insertListForExcel(List list) {
+                //update-begin-author:taoyan date:20190528 for:批量插入数据
+                long start = System.currentTimeMillis();
+                saveBatch(list);
+                //400条 saveBatch消耗时间1592毫秒  循环插入消耗时间1947毫秒
+                //1200条  saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
+                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
+                //update-end-author:taoyan date:20190528 for:批量插入数据
+            }
+        });
+        return Result.ok("文件导入成功!");
+    }
 }

+ 81 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/DictUtils.java

@@ -0,0 +1,81 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package org.jeecg.modules.utils;
+
+
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.system.vo.DictModel;
+import org.jeecg.modules.api.SysBaseRemoteApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+
+/**
+ * 字典工具类
+ *
+ * @author jeeplus
+ * @version 2016-5-29
+ */
+@Component
+public class DictUtils {
+    @Autowired
+    private SysBaseRemoteApi sysBaseRemoteApi;
+
+    public static DictUtils dictUtils;
+    public static SysBaseRemoteApi iSysDictService;
+
+    @PostConstruct
+    public void init() {
+        dictUtils = this;
+        iSysDictService = sysBaseRemoteApi;
+    }
+
+    /**
+     * 解析字典类型
+     * 通过编码和存储的value查询字典text、
+     *
+     * @param value
+     * @param dictCode
+     * @return
+     */
+    public static String queryDictTextByKey(String dictCode, String value) {
+        if (StringUtils.isNotBlank(dictCode) && StringUtils.isNotBlank(value)) {
+            return iSysDictService.queryDictTextByKey(dictCode, value);
+        }
+        return "";
+    }
+
+    /**
+     * 解析字典类型
+     * 通过编码和存储的text查询字典value、
+     *
+     * @param dictCode
+     * @param dictText
+     * @return
+     */
+    public static Integer queryDictKeyByText(String dictCode, String dictText) {
+        if (StringUtils.isNotBlank(dictCode) && StringUtils.isNotBlank(dictText)) {
+            return iSysDictService.queryDictKeyByText(dictCode, dictText);
+        }
+        return null;
+    }
+
+    /**
+     * 通过字典查询easypoi,所需字典文本
+     *
+     * @return
+     * @Author:scott
+     * @since:2019-04-09
+     */
+    public static List<DictModel> queryDictItemsByCode(String dictCode) {
+        if (StringUtils.isNotBlank(dictCode)) {
+            List<DictModel> dictList = iSysDictService.queryDictItemsByCode(dictCode);
+            return dictList;
+        }
+        return null;
+    }
+
+}

+ 303 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/ExcelUtil.java

@@ -0,0 +1,303 @@
+package org.jeecg.modules.utils.excel;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.metadata.fill.FillConfig;
+import com.alibaba.excel.write.metadata.fill.FillWrapper;
+import org.springframework.core.io.ClassPathResource;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author bao
+ * @ClassName ExcelUtil.java
+ * @Description easyExcel工具类
+ * @Date 2021/8/3 11:03
+ **/
+public class ExcelUtil {
+
+
+    /**
+     * 导出excel(字段全部导出)
+     * 浏览器
+     *
+     * @param response
+     * @param title
+     * @param head
+     * @param list
+     * @throws IOException
+     */
+    public static void exportExcelWeb(HttpServletResponse response, String title, Class head, List list) throws IOException {
+        exportExcelWeb(response, title, head, list, null);
+    }
+
+    /**
+     * 导出excel(字段全部导出)
+     * 本地
+     *
+     * @param filePath 文件导出路径
+     * @param title
+     * @param head
+     * @param list
+     * @throws IOException
+     */
+    public static void exportExcelLocal(String filePath, String title, Class head, List list) throws IOException {
+        exportExcelLocal(filePath, title, head, list, null);
+    }
+
+    /**
+     * 导出excel(按照模板导出)
+     * 本地
+     *
+     * @param response
+     * @param title
+     * @param templateUri
+     * @param list
+     * @throws IOException
+     */
+    public static void exportExcelByTemplateLocal(HttpServletResponse response, String title, String templateUri, Map map, List list) throws IOException {
+        exportExcelByTemplateLocal(response, title, templateUri, map, list, false);
+    }
+
+    /**
+     * 导出excel(按照模板导出)
+     * 远程
+     *
+     * @param response
+     * @param title
+     * @param templateUri
+     * @param list
+     * @throws IOException
+     */
+    public static void exportExcelByTemplateWeb(HttpServletResponse response, String title, String templateUri, Map map, List list) throws IOException {
+        exportExcelByTemplateWeb(response, title, templateUri, map, list, true);
+    }
+
+    /**
+     * 导出功能(过滤需要倒数的属性)
+     * 本地
+     *
+     * @param path                    文件路径
+     * @param title                   导出文件的名称
+     * @param head                    导出数据的类
+     * @param list                    需要导出的数据列表
+     * @param includeColumnFiledNames 需要导出的字段属性
+     * @throws IOException
+     */
+    public static void exportExcelLocal(String path, String title, Class head, List list, Set<String> includeColumnFiledNames) throws IOException {
+        String file = path + File.separator + URLEncoder.encode(title, "UTF-8");
+        if (includeColumnFiledNames == null) {
+            EasyExcel.write(file, head).sheet("Sheet1").doWrite(list);
+        } else {
+            EasyExcel.write(file, head).includeColumnFiledNames(includeColumnFiledNames).sheet("Sheet1")
+                    .doWrite(list);
+        }
+    }
+
+    /**
+     * 导出功能(过滤需要倒数的属性)
+     * 浏览器
+     *
+     * @param response
+     * @param title                   导出文件的名称
+     * @param head                    导出数据的类
+     * @param list                    需要导出的数据列表
+     * @param includeColumnFiledNames 需要导出的字段属性
+     * @throws IOException
+     */
+    public static void exportExcelWeb(HttpServletResponse response, String title, Class head, List list, Set<String> includeColumnFiledNames) throws IOException {
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("utf-8");
+        String fileName = URLEncoder.encode(title, "UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+        if (includeColumnFiledNames == null) {
+            EasyExcel.write(response.getOutputStream(), head).sheet("Sheet1")
+                    .doWrite(list);
+        } else {
+            EasyExcel.write(response.getOutputStream(), head).includeColumnFiledNames(includeColumnFiledNames).sheet("Sheet1")
+                    .doWrite(list);
+        }
+    }
+
+    /**
+     * 导出csv
+     *
+     * @param response
+     * @param title
+     * @param head
+     * @param list
+     * @throws IOException
+     */
+    public static void exportCsvWeb(HttpServletResponse response, String title, Class head, List list) throws IOException {
+        exportCsvWeb(response, title, head, list, null);
+    }
+
+    /**
+     * 导出csv
+     *
+     * @param response
+     * @param title
+     * @param head
+     * @param list
+     * @param includeColumnFiledNames
+     * @throws IOException
+     */
+    public static void exportCsvWeb(HttpServletResponse response, String title, Class head, List list, Set<String> includeColumnFiledNames) throws IOException {
+        response.setContentType("text/csv");
+        response.setCharacterEncoding("utf-8");
+        String fileName = URLEncoder.encode(title, "UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".csv");
+        if (includeColumnFiledNames == null) {
+            EasyExcel.write(response.getOutputStream(), head).sheet("Sheet1")
+                    .doWrite(list);
+        } else {
+            EasyExcel.write(response.getOutputStream(), head).includeColumnFiledNames(includeColumnFiledNames).sheet("Sheet1")
+                    .doWrite(list);
+        }
+    }
+
+    /**
+     * 按照模板导出(模板的上半部分是固定的数据,下半部分是一个不定数量的列表,使用时请注意场景是否一样)
+     * 本地
+     * 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
+     * {} 代表普通变量 {.} 代表是list的变量
+     * {data.xx} 代表对象的变量
+     * 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
+     * forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
+     * 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
+     *
+     * @param response
+     * @param title       导出文件的名称
+     * @param templateUri 模板在资源文件夹下的全路径
+     * @param map         上半部分的固定数据,默认new HashMap(),不属于list的数据,如:表头、末尾统计,操作这里
+     * @param list        下半部分的列表数据
+     * @throws IOException
+     */
+    public static void exportExcelByTemplateLocal(HttpServletResponse response, String title, String templateUri, Map map, List list, boolean isWeb) {
+        InputStream inputStream = null;
+        try {
+            ClassPathResource classPathResource = new ClassPathResource(templateUri);
+            inputStream = classPathResource.getInputStream();
+            response.setContentType("application/vnd.ms-excel");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode(title, "UTF-8");
+            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
+            WriteSheet writeSheet = EasyExcel.writerSheet().build();
+            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
+            excelWriter.fill(map, writeSheet);
+            excelWriter.fill(new FillWrapper("data", list), fillConfig, writeSheet);
+            excelWriter.finish();
+            response.flushBuffer();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 按照模板导出(模板的上半部分是固定的数据,下半部分是一个不定数量的列表,使用时请注意场景是否一样)
+     * 远程
+     * 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
+     * {} 代表普通变量 {.} 代表是list的变量
+     * {data.xx} 代表对象的变量
+     * 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
+     * forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
+     * 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
+     *
+     * @param response
+     * @param title       导出文件的名称
+     * @param templateUri 模板在资源文件夹下的全路径
+     * @param map         上半部分的固定数据,默认new HashMap(),不属于list的数据,如:表头、末尾统计,操作这里
+     * @param list        下半部分的列表数据
+     */
+    public static void exportExcelByTemplateWeb(HttpServletResponse response, String title, String templateUri, Map map, List list, boolean isWeb) {
+        InputStream inputStream = null;
+        try {
+            // 统一资源
+            URL url = new URL(templateUri);
+            // 连接类的父类,抽象类
+            URLConnection urlConnection = url.openConnection();
+            // http的连接类
+            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
+            //设置超时
+            httpURLConnection.setConnectTimeout(1000 * 5);
+            //设置请求方式,默认是GET
+            httpURLConnection.setRequestMethod("GET");
+            // 设置字符编码
+            httpURLConnection.setRequestProperty("Charset", "UTF-8");
+            // 打开到此 URL引用的资源的通信链接(如果尚未建立这样的连接)。
+            httpURLConnection.connect();
+            inputStream = httpURLConnection.getInputStream();
+            response.setContentType("application/vnd.ms-excel");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode(title, "UTF-8");
+            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
+            WriteSheet writeSheet = EasyExcel.writerSheet().build();
+            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
+            excelWriter.fill(map, writeSheet);
+            excelWriter.fill(new FillWrapper("data", list), fillConfig, writeSheet);
+            excelWriter.finish();
+            response.flushBuffer();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 导入功能
+     * 本地
+     *
+     * @param file               文件准确路径
+     * @param clazz              导入数据的对象
+     * @param importDataListener 自定义存储接口
+     * @return 返回导入数据的条数
+     */
+    public static int importExcelLocal(String file, Class clazz, Integer headRowNumber, ImportDataListener importDataListener) {
+        EasyExcel.read(file, clazz, importDataListener).sheet().headRowNumber(headRowNumber).doRead();
+        return importDataListener.getTotal();
+    }
+
+    /**
+     * 导入功能
+     * 浏览器
+     *
+     * @param inputStream
+     * @param clazz              导入数据的对象
+     * @param headRowNumber      头部所占行数
+     * @param importDataListener 自定义存储接口
+     * @return 返回导入数据的条数
+     */
+    public static int importExcel(InputStream inputStream, Class clazz, Integer headRowNumber, ImportDataListener importDataListener) {
+        EasyExcel.read(inputStream, clazz, importDataListener).sheet().headRowNumber(headRowNumber).doRead();
+        return importDataListener.getTotal();
+    }
+
+}

+ 212 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/ImportDataListener.java

@@ -0,0 +1,212 @@
+package org.jeecg.modules.utils.excel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.exception.ExcelAnalysisException;
+import com.alibaba.excel.exception.ExcelDataConvertException;
+import com.alibaba.excel.metadata.data.ReadCellData;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.modules.utils.excel.validation.group.ExcelImport;
+import org.springframework.validation.annotation.Validated;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import java.lang.reflect.Field;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * 模板的读取类
+ *
+ * @author zwq
+ */
+@Slf4j
+public abstract class ImportDataListener<T> extends AnalysisEventListener<T> {
+
+    /**
+     * 单次缓存的数据量,然后清理list ,方便内存回收
+     */
+    private static final int BATCH_COUNT = 1000;
+    /**
+     * 临时存储
+     */
+    private List<T> cachedDataList = new ArrayList<>();
+    /**
+     * 扩展的map传值
+     */
+    private static final Validator validator;
+    private int total = 0;
+    /**
+     * 是否验证
+     */
+    private boolean checkFlag = false;
+    /**
+     * 头部信息集合
+     */
+    Map<Integer, ReadCellData<?>> headRowMap = new HashMap<>();
+
+    //获得验证器实例
+    static {
+        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+        validator = factory.getValidator();
+        factory.close();
+    }
+
+    public ImportDataListener(boolean checkFlag) {
+        this.checkFlag = checkFlag;
+    }
+
+    /**
+     * 这个每一条数据解析都会来调用
+     *
+     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
+     * @param context
+     */
+    @Override
+    public void invoke(@Validated T data, AnalysisContext context) {
+        log.info("解析到一条数据:{}", JsonUtils.toJson(data));
+        //对数据进行判空,过滤掉空字符串解析出来的对象
+        try {
+            if (filterEmpty(data)) {
+                return;
+            }
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+        //进行注解的校验
+        if (checkFlag) {
+            checkBean(data, context);
+        }
+        cachedDataList.add(data);
+    }
+
+
+    private boolean filterEmpty(T bean) throws IllegalAccessException {
+        // 获取实体类的所有属性,返回Field数组
+        Field[] field = bean.getClass().getDeclaredFields();
+        int emptyNum = 0;
+        for (int i = 0; i < field.length; i++) {
+            Field f = field[i];
+            //设置些属性是可以访问的
+            f.setAccessible(true);
+            //得到此属性的值
+            Object val = f.get(bean);
+            if (f.getName().equals("serialVersionUID")) {
+                emptyNum++;
+                continue;
+            }
+            if (val == null) {
+                emptyNum++;
+                continue;
+            }
+            //得到此属性的类型
+            String type = f.getType().toString();
+            if (type.endsWith("String")) {
+                String str = (String) val;
+                if (StringUtils.isBlank(str.trim())) {
+                    emptyNum++;
+                }
+            }
+        }
+        if (emptyNum - field.length == 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 检查导入数据的完整性
+     *
+     * @param data
+     * @param context
+     */
+    private void checkBean(T data, AnalysisContext context) {
+        Set<ConstraintViolation<T>> set = validator.validate(data, ExcelImport.class);
+        if (set != null && !set.isEmpty()) {
+            StringBuilder stringBuilder = new StringBuilder();
+            set.forEach(item -> {
+                stringBuilder.append(item.getMessage());
+                stringBuilder.append(",");
+                throw new ExcelAnalysisException(MessageFormat.format("您的数据的第{0}行有问题-{1}请检查后再进行导入",
+                        context.readRowHolder().getRowIndex() + 1, stringBuilder.toString()));
+            });
+        }
+    }
+
+    /**
+     * 所有数据解析完成了,会来调用
+     *
+     * @param context
+     */
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        log.info("所有数据解析完成!");
+        saveData();
+    }
+
+    @Override
+    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
+        log.info("解析到第{}行头数据: {}", context.readRowHolder().getRowIndex() + 1, JSON.toJSONString(headMap));
+        headRowMap = headMap;
+    }
+
+    @Override
+    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
+        super.invokeHeadMap(headMap, context);
+    }
+
+    @Override
+    public void onException(Exception exception, AnalysisContext context) throws Exception {
+        log.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
+        // 如果是某一个单元格的转换异常 能获取到具体行号
+        // 如果要获取头的信息 配合invokeHead使用
+        ExcelDataConvertException excelDataConvertException = null;
+        if (exception instanceof ExcelDataConvertException) {
+            excelDataConvertException = (ExcelDataConvertException) exception;
+            log.error(MessageFormat.format("您的数据的第{0}行有问题-{1},请检查后再进行导入",
+                    excelDataConvertException.getRowIndex() + 1, headRowMap.get(excelDataConvertException.getColumnIndex()).getStringValue() + "解析异常"));
+            throw new ExcelAnalysisException(MessageFormat.format("您的数据的第{0}行有问题-{1},请检查后再进行导入",
+                    excelDataConvertException.getRowIndex() + 1, headRowMap.get(excelDataConvertException.getColumnIndex()).getStringValue() + "解析异常"));
+        }
+        throw new ExcelAnalysisException(exception.getMessage());
+    }
+
+    @Override
+    public boolean hasNext(AnalysisContext context) {
+        return super.hasNext(context);
+    }
+
+    /**
+     * 加上存储数据库
+     */
+    private void saveData() {
+        if (cachedDataList == null || cachedDataList.isEmpty()) {
+            return;
+        }
+        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
+        try {
+            insertListForExcel(cachedDataList);
+            total += cachedDataList.size();
+        } catch (JeecgBootException e) {
+            throw new ExcelAnalysisException(e.getMessage());
+        }
+        log.info("存储数据库成功!");
+    }
+
+    /**
+     * 扩展插入操作<>具体自定义的</>
+     *
+     * @param list
+     */
+    public abstract void insertListForExcel(List<T> list);
+
+
+    public int getTotal() {
+        return total;
+    }
+}

+ 147 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/JsonUtils.java

@@ -0,0 +1,147 @@
+package org.jeecg.modules.utils.excel;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * jackson工具类
+ */
+public final class JsonUtils {
+
+    /**
+     * jackson map
+     */
+    private static ObjectMapper mapper = new ObjectMapper();
+    /**
+     * 设置JSON时间格式
+     */
+    private static SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    static {
+        mapper.setDateFormat(myDateFormat);
+    }
+
+    private JsonUtils() {
+    }
+
+    /**
+     * 将bean转换成json
+     *
+     * @param obj bean对象
+     * @return json
+     */
+    public static String toJson(Object obj) {
+        try {
+            return mapper.writeValueAsString(obj);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    /**
+     * 把json字符串转换为相应的JavaBean对象
+     *
+     * @param json json数据
+     * @param type bean 类型
+     * @param <T>  泛型
+     * @return bean
+     */
+    public static <T> T toBean(String json, Class<T> type) {
+        if (json == null || json.isEmpty()) {
+            return null;
+        }
+
+        try {
+            return mapper.readValue(json, type);
+        } catch (Exception e) {
+            LogFactory.getLog(JsonUtils.class).error("非法的JSON字符串:" + json);
+        }
+
+        return null;
+    }
+
+    /**
+     * 将json转换成指定类型的集合
+     *
+     * @param json
+     * @param elementClasses
+     * @param <T>
+     * @return List
+     */
+    public static <T> T toList(String json, Class<?>... elementClasses) {
+        if (json == null || json.isEmpty()) {
+            return null;
+        }
+
+        try {
+            return mapper.readValue(json, mapper.getTypeFactory().constructParametricType(List.class, elementClasses));
+        } catch (Exception e) {
+            LogFactory.getLog(JsonUtils.class).error("非法的JSON字符串:" + json);
+            return null;
+        }
+    }
+
+    /**
+     * 将json字符串转换为HashMap
+     *
+     * @param json json
+     * @return hashmap
+     */
+    public static Map toMap(String json) {
+        if (json == null || json.isEmpty()) {
+            return null;
+        }
+
+        try {
+            return mapper.readValue(json, HashMap.class);
+        } catch (Exception e) {
+            LogFactory.getLog(JsonUtils.class).error("非法的JSON字符串:" + json);
+            return null;
+        }
+    }
+
+    /**
+     * 获取json中的某个字段值
+     *
+     * @param json json字符串
+     * @return 字段值
+     */
+    public static String getValue(String json, String name) {
+        try {
+            Map<String, String> map = mapper.readValue(json, HashMap.class);
+
+            return map.get(name);
+        } catch (JsonParseException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    /**
+     * 获取泛型Collection JavaType
+     *
+     * @param collectionClass 泛型的Collection
+     * @param elementClasses  元素类
+     * @return JavaType Java类型
+     * @since 1.0
+     */
+    public static JavaType getJavaType(Class<?> collectionClass, Class<?>... elementClasses) {
+        return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
+    }
+}

+ 64 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/converter/ExcelDateConverter.java

@@ -0,0 +1,64 @@
+package org.jeecg.modules.utils.excel.converter;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+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 com.alibaba.excel.util.DateUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2021/12/3 18:36
+ * @Description: Date类型
+ */
+@Slf4j
+public class ExcelDateConverter implements Converter<Date> {
+    @Override
+    public Class<Date> supportJavaTypeKey() {
+        return Date.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    /**
+     * 这里读的时候会调用
+     *
+     * @return
+     */
+    @Override
+    public Date convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException {
+        //获取转换的字段值
+        log.info("自定义时间格式转换:{}", cellData.getStringValue());
+        if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
+            log.info("s:{}", contentProperty.getDateTimeFormatProperty().getFormat());
+            return DateUtils.parseDate(cellData.getStringValue(), contentProperty.getDateTimeFormatProperty().getFormat());
+        }
+        return DateUtils.parseDate(cellData.getStringValue(), "yyyy/MM/dd");
+    }
+
+    /**
+     * 这里是写的时候会调用
+     *
+     * @return
+     */
+    @Override
+    public WriteCellData<?> convertToExcelData(Date date, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        log.info("自定义时间格式转换: {}", date);
+        if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
+            log.info("s:{}", contentProperty.getDateTimeFormatProperty().getFormat());
+            return new WriteCellData<>(DateUtils.format(date, contentProperty.getDateTimeFormatProperty().getFormat()));
+        }
+        return new WriteCellData<>(DateUtils.format(date, "yyyy/MM/dd"));
+    }
+
+
+}

+ 87 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/converter/ExcelDictConverter.java

@@ -0,0 +1,87 @@
+package org.jeecg.modules.utils.excel.converter;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+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 lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.system.vo.DictModel;
+import org.jeecg.modules.utils.DictUtils;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2021/12/3 15:39
+ * @Description: excel字典转换器
+ */
+@Slf4j
+public class ExcelDictConverter implements Converter<Integer> {
+    @Override
+    public Class<?> supportJavaTypeKey() {
+        return Integer.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    /**
+     * 这里读的时候会调用
+     *
+     * @return
+     */
+    @Override
+    public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        //获取类
+        Field field = contentProperty.getField();
+        //获取注解对象
+        ExcelProperty excelProperty = (ExcelProperty) field.getAnnotation(ExcelProperty.class);
+        //获取转换的字段值
+        log.info("自定义字典转换text:{}", cellData.getStringValue());
+        //当前字段对应的字典值
+        Integer dictValue = null;
+        List<DictModel> dictList = DictUtils.queryDictItemsByCode(excelProperty.dictCode());
+        //根据dictText过滤
+        dictList = dictList.stream().filter(item -> item.getText().equals(cellData.getStringValue())).collect(Collectors.toList());
+        if (dictList != null && dictList.size() > 0) {
+            DictModel dictModel = dictList.get(0);
+            dictValue = Integer.parseInt(dictModel.getValue());
+        }
+        log.info("自定义字典转换key: {}", dictValue);
+        return dictValue;
+    }
+
+    /**
+     * 这里是写的时候会调用
+     *
+     * @return
+     */
+    @Override
+    public WriteCellData<?> convertToExcelData(Integer dictKey, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        //获取类
+        Field field = contentProperty.getField();
+        //获取注解对象
+        ExcelProperty excelProperty = (ExcelProperty) field.getAnnotation(ExcelProperty.class);
+        //当前字段对应的字典text
+        String dictText = null;
+        if (dictKey != null) {
+            List<DictModel> dictList = DictUtils.queryDictItemsByCode(excelProperty.dictCode());
+            //根据dictKey过滤
+            dictList = dictList.stream().filter(item -> String.valueOf(dictKey).equals(item.getValue())).collect(Collectors.toList());
+            if (dictList != null && dictList.size() > 0) {
+                DictModel dictModel = dictList.get(0);
+                dictText = dictModel.getText();
+            }
+            log.info("自定义字典转换text: {}", dictText);
+        }
+        return new WriteCellData<>(dictText);
+    }
+
+}

+ 147 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/match/ExcelImportMapUtil.java

@@ -0,0 +1,147 @@
+package org.jeecg.modules.utils.excel.match;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Objects.isNull;
+
+/**
+*@ClassName ExcelImportMapUtil.java
+*@author bao
+*@Description 导入关联工具类,解决导入报表时部门等关联问题。
+*@Date  2021/8/3 10:03
+**/
+public class ExcelImportMapUtil<T> {
+
+    private static final String DELIMIT = ":";
+    private Map<String, T> map = new ConcurrentHashMap<>();
+
+    public boolean saveToMap(List<T> orgList, Class<T> c, String... element) {
+        if (orgList != null && orgList.size() > 0) {
+            try {
+                Class aClass = Class.forName(c.getName());
+
+                List<String> list = Stream.of(element).filter(Objects::nonNull)
+                        .map(String::valueOf)
+                        .filter(StringUtils::isNotBlank)
+                        .collect(Collectors.toList());
+
+                orgList.forEach(t -> {
+                    Object[] str = new Object[list.size()];
+                    for (int i = 0; i < list.size(); i++) {
+                        try {
+                            Field field = aClass.getDeclaredField(list.get(i));
+                            field.setAccessible(true);
+                            str[i] = field.get(t);
+                        } catch (NoSuchFieldException e) {
+                            e.printStackTrace();
+                        } catch (IllegalAccessException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    map.put(concat(DELIMIT, str), t);
+                });
+                map.forEach((key, value) -> System.out.println("key : " + key + "; value : " + value));
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 获取匹配的key
+     *
+     * @param element
+     * @return
+     */
+    public List<String> getKey(List<ExcelMatch> element) {
+        return map.keySet().stream().filter(
+                item -> {
+                    boolean flag = false;
+                    String[] str = item.split(DELIMIT);
+                    for (int i = 0; i < element.size(); i++) {
+                        if (!str[element.get(i).sort].matches(element.get(i).toString())) {
+                            flag = false;
+                            break;
+                        }
+                        flag = true;
+                    }
+                    return flag;
+                }).collect(Collectors.toList());
+    }
+
+    /**
+     * 判断长度
+     *
+     * @return
+     */
+    public int size() {
+        return map.size();
+    }
+
+    /**
+     * 获取缓存中的对象
+     *
+     * @return
+     */
+    public T getObejct(Object key) {
+        return map.get(key);
+    }
+
+    /**
+     * 获取对象list
+     *
+     * @return
+     */
+    public List<T> getObjectList(List<ExcelMatch> element) {
+        return map.entrySet().stream().filter(
+                item -> {
+                    boolean flag = false;
+                    String[] str = item.getKey().split(DELIMIT);
+                    for (int i = 0; i < element.size(); i++) {
+                        if (!str[element.get(i).sort].matches(element.get(i).toString())) {
+                            flag = false;
+                            break;
+                        }
+                        flag = true;
+                    }
+                    return flag;
+                }).map(item -> item.getValue()).collect(Collectors.toList());
+    }
+
+    /**
+     * 清空
+     */
+    public void clear() {
+        map.clear();
+    }
+
+    /**
+     * key的规则生成
+     *
+     * @param delimiter
+     * @param element
+     * @return
+     */
+    public String concat(String delimiter, Object... element) {
+        if (isNull(element) || element.length == 0) {
+            return null;
+        }
+        return Stream.of(element)
+                .filter(Objects::nonNull)
+                .map(String::valueOf)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.joining(delimiter));
+    }
+
+
+}

+ 43 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/match/ExcelMatch.java

@@ -0,0 +1,43 @@
+package org.jeecg.modules.utils.excel.match;
+
+import lombok.Data;
+
+/**
+ * @创建人:bao
+ * @创建时间:2020/5/28
+ * @描述:匹配项配置类
+ */
+@Data
+public class ExcelMatch {
+
+    /**
+     * 匹配值
+     */
+    public Object value;
+    /**
+     * 是否精准匹配
+     */
+    public boolean exactMatch;
+    /**
+     * 匹配位数
+     */
+    public int sort;
+
+    public ExcelMatch(Object value, boolean exactMatch, int sort) {
+
+        this.value = value;
+        this.exactMatch = exactMatch;
+        this.sort = sort;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer stringBuffer = new StringBuffer();
+        if (exactMatch) {
+            stringBuffer.append(value);
+        } else {
+            stringBuffer.append(value).append("(.*)");
+        }
+        return stringBuffer.toString();
+    }
+}

+ 17 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/properties/ExportProperties.java

@@ -0,0 +1,17 @@
+package org.jeecg.modules.utils.excel.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2022/10/26 16:00
+ * @Description: 导出文件配置类
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "jeecg.excel.export")
+public class ExportProperties {
+
+}

+ 21 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/properties/ImportProperties.java

@@ -0,0 +1,21 @@
+package org.jeecg.modules.utils.excel.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2022/10/26 16:00
+ * @Description: 导入文件配置类
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "jeecg.excel.url")
+public class ImportProperties {
+
+    /**
+     * 开票内容
+     */
+    private String invoiceCategory;
+}

+ 38 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/BankCard.java

@@ -0,0 +1,38 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * 通用银行卡号格式的校验器
+ *
+ * @author zwq
+ * @date 2021-12-15 09:04
+ */
+@Documented
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = BankCardValidator.class)
+@Repeatable(BankCard.List.class)
+public @interface BankCard {
+
+    String message() default "银行卡格式不正确";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+
+    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+    @Retention(RUNTIME)
+    @Documented
+    public @interface List {
+        BankCard[] value();
+    }
+
+
+}

+ 42 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/BankCardValidator.java

@@ -0,0 +1,42 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 自定义银行卡号约束注解关联验证器
+ *
+ * @author zwq
+ * @date 2021-12-15 09:04
+ */
+public class BankCardValidator implements ConstraintValidator<BankCard, String> {
+
+
+    @Override
+    public void initialize(BankCard constraintAnnotation) {
+    }
+
+    /**
+     * 自定义校验逻辑方法
+     * 
+     * @param value
+     * @param context
+     * @return
+     */
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if (StringUtils.isBlank(value)) {
+            return true;
+        }
+        String check = "^[1-9]*[1-9][0-9]*$";
+        Pattern regex = Pattern.compile(check);
+        Matcher matcher = regex.matcher(value);
+        return matcher.matches();
+    }
+
+
+}

+ 40 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/DateTimeFormat.java

@@ -0,0 +1,40 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * 通用日期时间字符串格式的校验器
+ *
+ * @author dong
+ * @date 2020-05-26 14:03
+ */
+@Documented
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = DateTimeFormatValidator.class)
+@Repeatable(DateTimeFormat.List.class)
+public @interface DateTimeFormat {
+
+    String message() default "日期字符串格式不正确";
+
+    String[] value() default {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd"};
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+
+    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+    @Retention(RUNTIME)
+    @Documented
+    public @interface List {
+        DateTimeFormat[] value();
+    }
+
+
+}

+ 42 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/DateTimeFormatValidator.java

@@ -0,0 +1,42 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.text.ParseException;
+
+/**
+ * 自定义时间格式字符串约束注解关联验证器
+ *
+ * @author dong
+ * @date 2020-05-26 17:04
+ */
+public class DateTimeFormatValidator implements ConstraintValidator<DateTimeFormat, String> {
+
+    private String[] dateTimePatterns;
+
+    @Override
+    public void initialize(DateTimeFormat constraintAnnotation) {
+        this.dateTimePatterns = constraintAnnotation.value();
+    }
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if (StringUtils.isBlank(value)) {
+            return true;
+        }
+        if (dateTimePatterns == null || dateTimePatterns.length == 0) {
+            return true;
+        }
+        try {
+            DateUtils.parseDate(value, dateTimePatterns);
+        } catch (ParseException e) {
+            return false;
+        }
+        return true;
+    }
+
+
+}

+ 37 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/IdCard.java

@@ -0,0 +1,37 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * 通用身份证格式的校验器
+ * @author dong
+ * @date 2020-04-10 17:03
+ */
+@Documented
+@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = IdCardValidator.class)
+@Repeatable(IdCard.List.class)
+public @interface IdCard {
+
+    String message() default "身份证格式不正确";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+
+    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+    @Retention(RUNTIME)
+    @Documented
+    public @interface List {
+        IdCard[] value();
+    }
+
+
+}

+ 55 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/IdCardValidator.java

@@ -0,0 +1,55 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 自定义身份证约束注解关联验证器
+ *
+ * @author dong
+ * @date 2020-04-10 17:04
+ */
+public class IdCardValidator implements ConstraintValidator<IdCard, String> {
+
+
+
+    @Override
+    public void initialize(IdCard constraintAnnotation) {
+    }
+
+    /**
+     * 自定义校验逻辑方法
+     *
+     * //注释:编码规则顺序从左至右依次为6位数字地址码,8位数字出生年份日期码,3位数字顺序码,1位数字校验码(可为x)。
+     *
+     * [1-9]\d{5}                 前六位地区,非0打头
+     *
+     * (18|19|([23]\d))\d{2}      出身年份,覆盖范围为 1800-3999 年
+     *
+     * ((0[1-9])|(10|11|12))      月份,01-12月
+     *
+     * (([0-2][1-9])|10|20|30|31) 日期,01-31天
+     *
+     * \d{3}[0-9Xx]:              顺序码三位 + 一位校验码
+     *
+     * @param value
+     * @param context
+     * @return
+     */
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if(StringUtils.isBlank(value)){
+            return true;
+        }
+        String check = "^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
+        Pattern regex = Pattern.compile(check);
+        Matcher matcher = regex.matcher(value);
+        return matcher.matches();
+    }
+
+
+}

+ 37 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/Phone.java

@@ -0,0 +1,37 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * 通用验证手机号码格式的校验器
+ * @author dong
+ * @date 2020-04-01 13:48
+ */
+@Documented
+@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = PhoneValidator.class)
+@Repeatable(Phone.List.class)
+public @interface Phone {
+
+    String message() default "手机号码格式不正确";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+
+    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+    @Retention(RUNTIME)
+    @Documented
+    public @interface List {
+        Phone[] value();
+    }
+
+
+}

+ 40 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/PhoneValidator.java

@@ -0,0 +1,40 @@
+package org.jeecg.modules.utils.excel.validation;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 自定义手机号约束注解关联验证器
+ *
+ * @author dong
+ * @date 2020-04-01 13:52
+ */
+public class PhoneValidator implements ConstraintValidator<Phone, String> {
+
+
+
+    @Override
+    public void initialize(Phone constraintAnnotation) {
+    }
+
+    /**
+     * 自定义校验逻辑方法
+     * @param value
+     * @param context
+     * @return
+     */
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if(StringUtils.isBlank(value)){
+            return true;
+        }
+        String check = "^[1]([3-9])[0-9]{9}$";
+        Pattern regex = Pattern.compile(check);
+        Matcher matcher = regex.matcher(value);
+        return matcher.matches();
+    }
+}

+ 11 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Delete.java

@@ -0,0 +1,11 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.groups.Default;
+
+/**
+ * @创建人:bao
+ * @创建时间:2020/3/16
+ * @描述:验证分组 删除
+ */
+public interface Delete extends Default {
+}

+ 10 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/ExcelImport.java

@@ -0,0 +1,10 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.groups.Default;
+
+/**
+ * @author dong
+ * @date 2020-05-09 15:46
+ */
+public interface ExcelImport extends Default {
+}

+ 11 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Get.java

@@ -0,0 +1,11 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.groups.Default;
+
+/**
+ * @创建人:bao
+ * @创建时间:2020/3/16
+ * @描述:验证分组 get获取
+ */
+public interface Get extends Default{
+}

+ 12 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Save.java

@@ -0,0 +1,12 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.groups.Default;
+
+/**
+*@ClassName Save.java
+*@author bao
+*@Description 保存
+*@Date  2021/4/23 15:31
+**/
+public interface Save extends Default {
+}

+ 12 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/Update.java

@@ -0,0 +1,12 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.groups.Default;
+
+/**
+*@ClassName Save.java
+*@author bao
+*@Description 修改
+*@Date  2021/4/23 15:31
+**/
+public interface Update extends Default {
+}

+ 137 - 0
happy-cloud-wisdom/happy-cloud-wisdom-biz/src/main/java/org/jeecg/modules/utils/excel/validation/group/ValidList.java

@@ -0,0 +1,137 @@
+package org.jeecg.modules.utils.excel.validation.group;
+
+import javax.validation.Valid;
+import java.util.*;
+
+/**
+ * 验证时用的list
+ * @param <E>
+ */
+public class ValidList<E> implements List<E> {
+
+    @Valid
+    private List<E> list = new LinkedList<>();
+
+    @Override
+    public int size() {
+        return list.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return list.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return list.contains(o);
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return list.iterator();
+    }
+
+    @Override
+    public Object[] toArray() {
+        return list.toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        return list.toArray(a);
+    }
+
+    @Override
+    public boolean add(E e) {
+        return list.add(e);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        return list.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return list.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+        return list.addAll(c);
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
+        return list.addAll(index, c);
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        return list.removeAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        return list.retainAll(c);
+    }
+
+    @Override
+    public void clear() {
+        list.clear();
+    }
+
+    @Override
+    public E get(int index) {
+        return list.get(index);
+    }
+
+    @Override
+    public E set(int index, E element) {
+        return list.set(index, element);
+    }
+
+    @Override
+    public void add(int index, E element) {
+        list.add(index, element);
+    }
+
+    @Override
+    public E remove(int index) {
+        return list.remove(index);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        return list.indexOf(o);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        return list.lastIndexOf(o);
+    }
+
+    @Override
+    public ListIterator<E> listIterator() {
+        return list.listIterator();
+    }
+
+    @Override
+    public ListIterator<E> listIterator(int index) {
+        return list.listIterator(index);
+    }
+
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        return list.subList(fromIndex, toIndex);
+    }
+
+    public List<E> getList() {
+        return list;
+    }
+
+    public void setList(List<E> list) {
+        this.list = list;
+    }
+}

+ 9 - 1
pom.xml

@@ -81,6 +81,7 @@
 		<logstash-logback-encoder.version>6.1</logstash-logback-encoder.version>
 		<hutool-all.version>5.3.8</hutool-all.version>
 		<commons-beanutils.version>1.9.4</commons-beanutils.version>
+		<easyexcel.version>3.0.5</easyexcel.version>
     </properties>
 
 	<dependencies>
@@ -263,7 +264,14 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
-		
+
+		<!--EasyExcel-->
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>easyexcel</artifactId>
+			<version>${easyexcel.version}</version>
+		</dependency>
+
 		<dependency>
 		    <groupId>cn.hutool</groupId>
 		    <artifactId>hutool-all</artifactId>