content: package org.ruoyi.common.excel.core;
  
  import cn.hutool.core.util.StrUtil;
  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 jakarta.validation.ConstraintViolation;
  import jakarta.validation.ConstraintViolationException;
  import lombok.NoArgsConstructor;
  import lombok.extern.slf4j.Slf4j;
  import org.ruoyi.common.core.utils.StreamUtils;
  import org.ruoyi.common.core.utils.ValidatorUtils;
  import org.ruoyi.common.json.utils.JsonUtils;
  
  import java.util.Map;
  import java.util.Set;
  
  /**
   * Excel 导入监听
   *
   * @author Yjoioooo
   * @author Lion Li
   */
  @Slf4j
  @NoArgsConstructor
  public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {
  
      /**
       * 是否Validator检验，默认为是
       */
      private Boolean isValidate = Boolean.TRUE;
  
      /**
       * excel 表头数据
       */
      private Map<Integer, String> headMap;
  
      /**
       * 导入回执
       */
      private ExcelResult<T> excelResult;
  
      public DefaultExcelListener(boolean isValidate) {
          this.excelResult = new DefaultExcelResult<>();
          this.isValidate = isValidate;
      }
  
      /**
       * 处理异常
       *
       * @param exception ExcelDataConvertException
       * @param context   Excel 上下文
       */
      @Override
      public void onException(Exception exception, AnalysisContext context) throws Exception {
          String errMsg = null;
          if (exception instanceof ExcelDataConvertException excelDataConvertException) {
              // 如果是某一个单元格的转换异常 能获取到具体行号
              Integer rowIndex = excelDataConvertException.getRowIndex();
              Integer columnIndex = excelDataConvertException.getColumnIndex();
              errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常<br/>",
                  rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
              if (log.isDebugEnabled()) {
                  log.error(errMsg);
              }
          }
          if (exception instanceof ConstraintViolationException constraintViolationException) {
              Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
              String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", ");
              errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
              if (log.isDebugEnabled()) {
                  log.error(errMsg);
              }
          }
          excelResult.getErrorList().add(errMsg);
          throw new ExcelAnalysisException(errMsg);
      }
  
      @Override
      public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
          this.headMap = headMap;
          log.debug("解析到一条表头数据: {}", JsonUtils.toJsonString(headMap));
      }
  
      @Override
      public void invoke(T data, AnalysisContext context) {
          if (isValidate) {
              ValidatorUtils.validate(data);
          }
          excelResult.getList().add(data);
      }
  
      @Override
      public void doAfterAllAnalysed(AnalysisContext context) {
          log.debug("所有数据解析完成！");
      }
  
      @Override
      public ExcelResult<T> getExcelResult() {
          return excelResult;
      }
  
  }
  