Forráskód Böngészése

银月:Excel复杂导入

tangbin 1 éve
szülő
commit
1c5a113bc7

+ 0 - 1
logic/equip-logic/src/main/java/com/iohao/mmo/equip/entity/EquipEntryProperty.java

@@ -36,7 +36,6 @@ import java.math.BigDecimal;
  * @date 2023-07-24
  */
 @Data
-@Builder
 @Document
 @FieldDefaults(level = AccessLevel.PRIVATE)
 public class EquipEntryProperty {

+ 0 - 1
logic/equip-logic/src/main/java/com/iohao/mmo/equip/entity/EquipEntryTemplate.java

@@ -36,7 +36,6 @@ import java.util.List;
  * @date 2023-07-26
  */
 @Data
-@Builder
 @Document
 @FieldDefaults(level = AccessLevel.PRIVATE)
 public class EquipEntryTemplate {

+ 41 - 41
logic/equip-logic/src/main/java/com/iohao/mmo/equip/service/EquipEntryTemplateService.java

@@ -85,47 +85,47 @@ public class EquipEntryTemplateService {
      * 初始化装备词条库(临时方法,后期移除改为从运营数据中导入)
      */
     public void initEquipTemplate() {
-        // 初始化一些装备配置,后期将移到 excel 中做。
-        EquipEntryTemplate equipEntryTemplate = EquipEntryTemplate.builder()
-                .name("根骨")
-                .code(PropertyNameEnum.GENGU.getCode())
-                .description("根骨")
-                .hitProb(BigDecimal.valueOf(0.10))
-                .entryProperty(
-                        EquipEntryProperty.builder()
-                                .levelMin(1)
-                                .levelMax(10)
-                                .countType(1) // 属性计算方式(1装备加,2装备增加百分比,3全身增加百分比)
-                                .showType(1) // 显示方式(1原值显示,2小数转百分比)
-                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
-                                .propertyValueMin(BigDecimal.valueOf(1))
-                                .propertyValueMax(BigDecimal.valueOf(5))
-                                .build()
-                )
-                .entryProperty(
-                        EquipEntryProperty.builder()
-                                .levelMin(11)
-                                .levelMax(20)
-                                .countType(1)
-                                .showType(1)
-                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
-                                .propertyValueMin(BigDecimal.valueOf(4))
-                                .propertyValueMax(BigDecimal.valueOf(10))
-                                .build()
-                )
-                .entryProperty(
-                        EquipEntryProperty.builder()
-                                .levelMin(21)
-                                .levelMax(30)
-                                .countType(1)
-                                .showType(1)
-                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
-                                .propertyValueMin(BigDecimal.valueOf(7))
-                                .propertyValueMax(BigDecimal.valueOf(15))
-                                .build()
-                )
-                .build();
-        mongoTemplate.save(equipEntryTemplate);
+//        // 初始化一些装备配置,后期将移到 excel 中做。
+//        EquipEntryTemplate equipEntryTemplate = EquipEntryTemplate.builder()
+//                .name("根骨")
+//                .code(PropertyNameEnum.GENGU.getCode())
+//                .description("根骨")
+//                .hitProb(BigDecimal.valueOf(0.10))
+//                .entryProperty(
+//                        EquipEntryProperty.builder()
+//                                .levelMin(1)
+//                                .levelMax(10)
+//                                .countType(1) // 属性计算方式(1装备加,2装备增加百分比,3全身增加百分比)
+//                                .showType(1) // 显示方式(1原值显示,2小数转百分比)
+//                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
+//                                .propertyValueMin(BigDecimal.valueOf(1))
+//                                .propertyValueMax(BigDecimal.valueOf(5))
+//                                .build()
+//                )
+//                .entryProperty(
+//                        EquipEntryProperty.builder()
+//                                .levelMin(11)
+//                                .levelMax(20)
+//                                .countType(1)
+//                                .showType(1)
+//                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
+//                                .propertyValueMin(BigDecimal.valueOf(4))
+//                                .propertyValueMax(BigDecimal.valueOf(10))
+//                                .build()
+//                )
+//                .entryProperty(
+//                        EquipEntryProperty.builder()
+//                                .levelMin(21)
+//                                .levelMax(30)
+//                                .countType(1)
+//                                .showType(1)
+//                                .effectPropertyName(PropertyNameEnum.GENGU.getCode())
+//                                .propertyValueMin(BigDecimal.valueOf(7))
+//                                .propertyValueMax(BigDecimal.valueOf(15))
+//                                .build()
+//                )
+//                .build();
+//        mongoTemplate.save(equipEntryTemplate);
     }
 
     /**

+ 6 - 2
logic/excel-logic/src/main/java/com/iohao/mmo/excel/controller/EquipExcelController.java

@@ -8,6 +8,7 @@ import com.iohao.mmo.excel.dto.DemoExcelDTO;
 import com.iohao.mmo.excel.dto.EquipEntryTemplateExcelDTO;
 import com.iohao.mmo.excel.kit.ExcelKit;
 import com.iohao.mmo.excel.listener.EquipEntryTemplateExcelListener;
+import com.iohao.mmo.excel.listener.ExcelAnalysisHelper;
 import com.iohao.mmo.excel.listener.ExcelDataCustomListener;
 import com.iohao.mmo.excel.service.EquipEntryTemplateExcelService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -43,7 +44,7 @@ public class EquipExcelController {
     @GetMapping("exportExcel")
     public void exportExcel(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception{
         List<EquipEntryTemplate> list = equipEntryTemplateExcelService.list(params,EquipEntryTemplate.class);
-        ExcelKit.exportExcelToTarget(response, null, "装备词条", list, DemoExcelDTO.class);
+        ExcelKit.exportExcelToTarget(response, null, "装备词条", list, EquipEntryTemplateExcelDTO.class);
     }
 
     /**
@@ -56,7 +57,10 @@ public class EquipExcelController {
     @Operation(summary = "导入数据自定义处理示例",description = "导入数据自定义处理示例")
     public Result importExcel(@RequestPart("file") @Parameter(description = "文件")MultipartFile file) throws Exception {
         //自定义读取
-        EasyExcel.read(file.getInputStream(), EquipEntryTemplateExcelDTO.class, new EquipEntryTemplateExcelListener<>(equipEntryTemplateExcelService)).sheet(0).doRead();
+        EasyExcel.read(file.getInputStream(), EquipEntryTemplateExcelDTO.class, new EquipEntryTemplateExcelListener<>(equipEntryTemplateExcelService,2)).sheet(0).doRead();
+//        ExcelAnalysisHelper excelAnalysisHelper = new ExcelAnalysisHelper();
+//        List<EquipEntryTemplateExcelDTO> list = excelAnalysisHelper.getList(file.getInputStream(), EquipEntryTemplateExcelDTO.class);
+//        list.forEach(System.out::println);
         return new Result().ok("导入成功!");
     }
 }

+ 43 - 0
logic/excel-logic/src/main/java/com/iohao/mmo/excel/dto/EquipEntryPropertyExcelDTO.java

@@ -0,0 +1,43 @@
+package com.iohao.mmo.excel.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 装备词条Excel
+ *
+ * @author Toby javatangbin@163.com
+ */
+@Data
+@ContentRowHeight(20)
+@HeadRowHeight(20)
+@ColumnWidth(25)
+public class EquipEntryPropertyExcelDTO {
+    @ExcelProperty(value = {"装备属性","等级最小值"})
+    private int levelMin;
+
+    @ExcelProperty(value = {"装备属性","等级最大值"})
+    private int levelMax;
+
+    @ExcelProperty(value = {"装备属性","属性计算方式"})
+    private int countType;
+
+    @ExcelProperty(value = {"装备属性","显示方式"})
+    private int showType;
+
+    @ExcelProperty(value = {"装备属性","影响属性"})
+    private String effectPropertyName;
+
+    @ExcelProperty(value = {"装备属性","属性范围最小值"})
+    private BigDecimal propertyValueMin;
+
+    @ExcelProperty(value = {"装备属性","属性范围最大值"})
+    private BigDecimal propertyValueMax;
+
+
+}

+ 13 - 14
logic/excel-logic/src/main/java/com/iohao/mmo/excel/dto/EquipEntryTemplateExcelDTO.java

@@ -5,7 +5,6 @@ import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import com.alibaba.excel.annotation.write.style.ContentRowHeight;
 import com.alibaba.excel.annotation.write.style.HeadRowHeight;
 import lombok.Data;
-
 import java.math.BigDecimal;
 
 /**
@@ -19,45 +18,45 @@ import java.math.BigDecimal;
 @ColumnWidth(25)
 public class EquipEntryTemplateExcelDTO {
     @ColumnWidth(20)
-    @ExcelProperty("名称")
+    @ExcelProperty(value ="名称",index = 0)
     private String name;
 
-    @ExcelProperty("编号")
+    @ExcelProperty(value ="编号",index = 1)
     private String code;
 
     @ColumnWidth(20)
-    @ExcelProperty(value = "描述")
+    @ExcelProperty(value = "描述",index = 2)
     private String description;
 
-    @ExcelProperty(value = "出现概率")
+    @ExcelProperty(value = "出现概率",index = 3)
     private BigDecimal hitProb;
 
     @ColumnWidth(20)
-    @ExcelProperty(value = "装备部位")
+    @ExcelProperty(value = "装备部位",index = 4)
     private String positionStrs;
 
-    @ExcelProperty(value = "最大次数")
+    @ExcelProperty(value = "最大次数",index = 5)
     private int maxExist;
 
-    @ExcelProperty(value = {"装备属性","等级最小值"})
+    @ExcelProperty(value = {"装备属性","等级最小值"},index = 6)
     private int levelMin;
 
-    @ExcelProperty(value = {"装备属性","等级最大值"})
+    @ExcelProperty(value = {"装备属性","等级最大值"},index = 7)
     private int levelMax;
 
-    @ExcelProperty(value = {"装备属性","属性计算方式"})
+    @ExcelProperty(value = {"装备属性","属性计算方式"},index = 8)
     private int countType;
 
-    @ExcelProperty(value = {"装备属性","显示方式"})
+    @ExcelProperty(value = {"装备属性","显示方式"},index = 9)
     private int showType;
 
-    @ExcelProperty(value = {"装备属性","影响属性"})
+    @ExcelProperty(value = {"装备属性","影响属性"},index = 10)
     private String effectPropertyName;
 
-    @ExcelProperty(value = {"装备属性","属性范围最小值"})
+    @ExcelProperty(value = {"装备属性","属性范围最小值"},index = 11)
     private BigDecimal propertyValueMin;
 
-    @ExcelProperty(value = {"装备属性","属性范围最大值"})
+    @ExcelProperty(value = {"装备属性","属性范围最大值"},index = 12)
     private BigDecimal propertyValueMax;
 
 

+ 70 - 11
logic/excel-logic/src/main/java/com/iohao/mmo/excel/listener/EquipEntryTemplateExcelListener.java

@@ -2,14 +2,18 @@ package com.iohao.mmo.excel.listener;
 
 import com.alibaba.excel.context.AnalysisContext;
 import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.metadata.CellExtra;
 import com.alibaba.fastjson2.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.iohao.mmo.equip.entity.EquipEntryProperty;
 import com.iohao.mmo.equip.entity.EquipEntryTemplate;
 import com.iohao.mmo.excel.dto.DemoExcelDTO;
+import com.iohao.mmo.excel.dto.EquipEntryTemplateExcelDTO;
 import com.iohao.mmo.excel.entity.DemoExcel;
 import com.iohao.mmo.excel.kit.ConvertKit;
 import com.iohao.mmo.excel.service.DemoExcelService;
 import com.iohao.mmo.excel.service.EquipEntryTemplateExcelService;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -17,7 +21,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * 装备词条模板excel
+ * 装备词条模板excel(公共列未合并)
  *
  * @author Toby javatangbin@163.com
  */
@@ -27,20 +31,28 @@ public class EquipEntryTemplateExcelListener<E, T> extends AnalysisEventListener
      * 每隔2000条存储数据库,然后清理list,方便内存回收
      */
     private static final int BATCH_COUNT = 2000;
-    private final List<EquipEntryTemplate> list = new ArrayList<>();
+    private final List<EquipEntryTemplate> equipEntryTemplateList = new ArrayList<>();
+
+    private EquipEntryTemplate nowEquipEntryTemplate;
+    private final List<EquipEntryProperty> equipEntryPropertyList = new ArrayList<>();
 
     /**
      * 通过构造器注入Service
      */
     private final EquipEntryTemplateExcelService equipEntryTemplateExcelService;
+    /**
+     * 表头行数
+     */
+    int headRowNumber = 1;
 
     /**
      * 构造方法
      *
      * @param equipEntryTemplateExcelService Service对象
      */
-    public EquipEntryTemplateExcelListener(EquipEntryTemplateExcelService equipEntryTemplateExcelService) {
+    public EquipEntryTemplateExcelListener(EquipEntryTemplateExcelService equipEntryTemplateExcelService,int headRowNumber) {
         this.equipEntryTemplateExcelService = equipEntryTemplateExcelService;
+        this.headRowNumber = headRowNumber;
     }
 
     /**
@@ -49,20 +61,67 @@ public class EquipEntryTemplateExcelListener<E, T> extends AnalysisEventListener
     @Override
     public void invoke(T data, AnalysisContext context) {
         LOGGER.info("解析到一条数据:{}", JSONObject.toJSONString(data));
-        DemoExcelDTO excel = ConvertKit.sourceToTarget(data, DemoExcelDTO.class);
+        EquipEntryTemplateExcelDTO excel = ConvertKit.sourceToTarget(data, EquipEntryTemplateExcelDTO.class);
+        if(StringUtils.isNotBlank(excel.getCode())){
+            // 这里对数据做自定义设置
+            nowEquipEntryTemplate = ConvertKit.sourceToTarget(excel, EquipEntryTemplate.class);
 
-        // 这里对数据做自定义设置
-        EquipEntryTemplate entity = ConvertKit.sourceToTarget(excel, EquipEntryTemplate.class);
+            equipEntryTemplateList.add(nowEquipEntryTemplate);
+        }
 
-        list.add(entity);
+        EquipEntryProperty equipEntryProperty = ConvertKit.sourceToTarget(excel, EquipEntryProperty.class);
+        List<EquipEntryProperty> lastPropertyList = nowEquipEntryTemplate.getEntryPropertyList();
+        if(lastPropertyList==null){
+            lastPropertyList = new ArrayList<>();
+        }
+        lastPropertyList.add(equipEntryProperty);
+        nowEquipEntryTemplate.setEntryPropertyList(lastPropertyList);
 
         // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
-        if (list.size() >= BATCH_COUNT) {
+        if (equipEntryTemplateList.size() >= BATCH_COUNT) {
             saveData();
             // 存储完成清理 list
-            list.clear();
+            equipEntryTemplateList.clear();
         }
     }
+    @Override
+    public void extra(CellExtra extra, AnalysisContext context) {
+        switch (extra.getType()) {
+            case COMMENT: {
+                LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
+                        extra.getText());
+                break;
+            }
+            case HYPERLINK: {
+                if ("Sheet1!A1".equals(extra.getText())) {
+                    LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
+                            extra.getColumnIndex(), extra.getText());
+                } else if ("Sheet2!A1".equals(extra.getText())) {
+                    LOGGER.info(
+                            "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
+                                    + "内容是:{}",
+                            extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
+                            extra.getLastColumnIndex(), extra.getText());
+                } else {
+                    LOGGER.info("Unknown hyperlink!");
+                }
+                break;
+            }
+            case MERGE: {
+                LOGGER.info(
+                        "额外信息是合并单元格,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",
+                        extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
+                        extra.getLastColumnIndex());
+                if (extra.getRowIndex() >= headRowNumber) {
+//                    extraMergeInfoList.add(extra);
+                }
+                break;
+            }
+            default: {
+            }
+        }
+    }
+
     /**
      * 所有数据解析完成了 都会来调用
      */
@@ -76,10 +135,10 @@ public class EquipEntryTemplateExcelListener<E, T> extends AnalysisEventListener
      * 加上存储数据库
      */
     private void saveData() {
-        LOGGER.info("{}条数据,开始存储数据库!", list.size());
+        LOGGER.info("{}条数据,开始存储数据库!", equipEntryTemplateList.size());
         try {
             //根据code批量更新或者插入
-            equipEntryTemplateExcelService.updateBatch(list);
+            equipEntryTemplateExcelService.updateBatch(equipEntryTemplateList);
         } catch (JsonProcessingException e) {
             throw new RuntimeException(e);
         }

+ 128 - 0
logic/excel-logic/src/main/java/com/iohao/mmo/excel/listener/ExcelAnalysisHelper.java

@@ -0,0 +1,128 @@
+package com.iohao.mmo.excel.listener;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.enums.CellExtraTypeEnum;
+import com.alibaba.excel.metadata.CellExtra;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * @Filename: ExcelAnalysisHelper
+ * @Author: sheng.wanping
+ * <li>Date: 2021/9/26 9:48</li>
+ * <li>Version: 1.0</li>
+ * <li>Content: create</li>
+ */
+@Slf4j
+public class ExcelAnalysisHelper<T> {
+
+    public List<T> getList(InputStream inputStream, Class<T> clazz) {
+        return getList(inputStream, clazz, 0, 2);
+    }
+
+    public List<T> getList(InputStream inputStream, Class<T> clazz, Integer sheetNo, Integer headRowNumber) {
+        ExcelImportListener<T> listener = new ExcelImportListener<>(headRowNumber);
+
+        EasyExcel.read(inputStream, clazz, listener).extraRead(CellExtraTypeEnum.MERGE).sheet(sheetNo).headRowNumber(headRowNumber).doRead();
+
+        List<CellExtra> extraMergeInfoList = listener.getExtraMergeInfoList();
+        if (CollectionUtils.isEmpty(extraMergeInfoList)) {
+            return listener.getData();
+        }
+        List<T> data = explainMergeData(listener.getData(), extraMergeInfoList, headRowNumber);
+        return data;
+    }
+
+    /**
+     * 处理合并单元格
+     *
+     * @param data               解析数据
+     * @param extraMergeInfoList 合并单元格信息
+     * @param headRowNumber      起始行
+     * @return 填充好的解析数据
+     */
+    private List<T> explainMergeData(List<T> data, List<CellExtra> extraMergeInfoList, Integer headRowNumber) {
+//        循环所有合并单元格信息
+        extraMergeInfoList.forEach(cellExtra -> {
+            int firstRowIndex = cellExtra.getFirstRowIndex() - headRowNumber;
+            int lastRowIndex = cellExtra.getLastRowIndex() - headRowNumber;
+            int firstColumnIndex = cellExtra.getFirstColumnIndex();
+            int lastColumnIndex = cellExtra.getLastColumnIndex();
+//            获取初始值
+            Object initValue = getInitValueFromList(firstRowIndex, firstColumnIndex, data);
+//            设置值
+            for (int i = firstRowIndex; i <= lastRowIndex; i++) {
+                for (int j = firstColumnIndex; j <= lastColumnIndex; j++) {
+                    setInitValueToList(initValue, i, j, data);
+                }
+            }
+        });
+        return data;
+    }
+
+    /**
+     * 设置合并单元格的值
+     *
+     * @param filedValue  值
+     * @param rowIndex    行
+     * @param columnIndex 列
+     * @param data        解析数据
+     */
+    public void setInitValueToList(Object filedValue, Integer rowIndex, Integer columnIndex, List<T> data) {
+        T object = data.get(rowIndex);
+
+        for (Field field : object.getClass().getDeclaredFields()) {
+            //提升反射性能,关闭安全检查
+            field.setAccessible(true);
+            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
+            if (annotation != null) {
+                if (annotation.index() == columnIndex) {
+                    try {
+                        field.set(object, filedValue);
+                        break;
+                    } catch (IllegalAccessException e) {
+                        log.warn("解析数据时发生异常!");
+                        //  throw new BizException(ResultCode.FAILURE, "解析数据时发生异常!");
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 获取合并单元格的初始值
+     * rowIndex对应list的索引
+     * columnIndex对应实体内的字段
+     *
+     * @param firstRowIndex    起始行
+     * @param firstColumnIndex 起始列
+     * @param data             列数据
+     * @return 初始值
+     */
+    private Object getInitValueFromList(Integer firstRowIndex, Integer firstColumnIndex, List<T> data) {
+        Object filedValue = null;
+        T object = data.get(firstRowIndex);
+        for (Field field : object.getClass().getDeclaredFields()) {
+            //提升反射性能,关闭安全检查
+            field.setAccessible(true);
+            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
+            if (annotation != null) {
+                if (annotation.index() == firstColumnIndex) {
+                    try {
+                        filedValue = field.get(object);
+                        break;
+                    } catch (IllegalAccessException e) {
+                        log.warn("解析数据时发生异常!");
+                        //  throw new BizException(ResultCode.FAILURE, "解析数据时发生异常!");
+                    }
+                }
+            }
+        }
+        return filedValue;
+    }
+}

+ 99 - 0
logic/excel-logic/src/main/java/com/iohao/mmo/excel/listener/ExcelImportListener.java

@@ -0,0 +1,99 @@
+package com.iohao.mmo.excel.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.metadata.CellExtra;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @Filename: ExcelImportListener
+ * @Author: sheng.wanping
+ * <li>Date: 2021/9/26 9:48</li>
+ * <li>Version: 1.0</li>
+ * <li>Content: (公共列合并单元格)</li>
+ */
+@Slf4j
+public class ExcelImportListener<T> extends AnalysisEventListener<T> {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelImportListener.class);
+
+    /**
+     * 解析的数据
+     */
+    List<T> list = new ArrayList<>();
+    public List<T> getData(){
+        return list;
+    }
+    /**
+     * 正文起始行
+     */
+    private Integer headRowNumber;
+    /**
+     * 合并单元格
+     */
+    private List<CellExtra> extraMergeInfoList = new ArrayList<>();
+    public List<CellExtra> getExtraMergeInfoList(){
+        return extraMergeInfoList;
+    }
+    public ExcelImportListener(Integer headRowNumber) {
+        this.headRowNumber = headRowNumber;
+    }
+
+    /**
+     * 有多少条数据执行多少次
+     */
+    @Override
+    public void invoke(T data, AnalysisContext context) {
+        list.add(data);
+    }
+    /**
+     * 等invoke把所有数据解析完成了,最后执行一次
+     * @param context
+     */
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        log.info("");
+    }
+
+    @Override
+    public void extra(CellExtra extra, AnalysisContext context) {
+        switch (extra.getType()) {
+            case COMMENT: {
+                LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
+                        extra.getText());
+                break;
+            }
+            case HYPERLINK: {
+                if ("Sheet1!A1".equals(extra.getText())) {
+                    LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
+                            extra.getColumnIndex(), extra.getText());
+                } else if ("Sheet2!A1".equals(extra.getText())) {
+                    LOGGER.info(
+                            "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
+                                    + "内容是:{}",
+                            extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
+                            extra.getLastColumnIndex(), extra.getText());
+                } else {
+                    LOGGER.info("Unknown hyperlink!");
+                }
+                break;
+            }
+            case MERGE: {
+                LOGGER.info(
+                        "额外信息是合并单元格,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",
+                        extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
+                        extra.getLastColumnIndex());
+                if (extra.getRowIndex() >= headRowNumber) {
+                    extraMergeInfoList.add(extra);
+                }
+                break;
+            }
+            default: {
+            }
+        }
+    }
+}

+ 4 - 4
one-client/src/main/java/com/iohao/mmo/client/input/LoginInputCommandRegion.java

@@ -61,10 +61,10 @@ public class LoginInputCommandRegion extends AbstractInputCommandRegion {
             clientUser.callbackInputCommandRegion();
         }).setDescription("登录").setInputRequestData(inputRequestData);
 
-        InternalKit.newTimeout(task -> {
-            // 自动登录
-            ofRequestCommand(LoginCmd.loginVerify).request();
-        }, 200, TimeUnit.MILLISECONDS);
+//        InternalKit.newTimeout(task -> {
+//            // 自动登录
+//            ofRequestCommand(LoginCmd.loginVerify).request();
+//        }, 200, TimeUnit.MILLISECONDS);
 
         ofCommand(LoginCmd.userIp).callback(StringValue.class, result -> {
             StringValue value = result.getValue();