Bläddra i källkod

Merge branch 'feature/20260228-export' of AHX-Bid/auction into dev

jintao.geng 2 veckor sedan
förälder
incheckning
06f7dd18e5

+ 17 - 4
auc/src/main/java/cn/hobbystocks/auc/web/LotController.java

@@ -6,6 +6,10 @@ import java.util.*;
 import cn.hobbystocks.auc.annotation.RequireRoles;
 import cn.hobbystocks.auc.app.AppClient;
 import cn.hobbystocks.auc.common.core.domain.AjaxResult;
+import cn.hobbystocks.auc.common.easy.factory.EasyColumnEnums;
+import cn.hobbystocks.auc.common.easy.factory.EasyExcelFactory;
+import cn.hobbystocks.auc.common.easy.factory.EasyExcelTypeEnums;
+import cn.hobbystocks.auc.common.poi.ExcelUtil;
 import cn.hobbystocks.auc.common.user.UserInfo;
 import cn.hobbystocks.auc.common.user.UserUtils;
 import cn.hobbystocks.auc.common.utils.ExcelUtils;
@@ -14,6 +18,7 @@ import cn.hobbystocks.auc.common.utils.UserType;
 import cn.hobbystocks.auc.domain.Bid;
 import cn.hobbystocks.auc.domain.Lot;
 import cn.hobbystocks.auc.common.constant.Constants;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
 import cn.hobbystocks.auc.dto.LotExportDTO;
 import cn.hobbystocks.auc.mapper.BidMapper;
 import cn.hobbystocks.auc.request.LotRequest;
@@ -188,12 +193,20 @@ public class LotController extends AdminBaseController {
 
     @ApiOperation(value = "导出拍品列表信息", notes = "拍品列表信息\n", response = AjaxResult.class, responseContainer = "AjaxResult.success")
     @PostMapping("/export")
-    public void export(@RequestBody LotRequest request, HttpServletResponse response) {
+    public AjaxResult export(@RequestBody LotRequest request, HttpServletResponse response) {
 
         List<LotExportDTO> lotList = lotService.exportLotList(request);
-        ExcelUtils<LotExportDTO> util = new ExcelUtils<>(LotExportDTO.class);
-        util.exportExcelHttp(lotList, response, "拍品管理导出");
-//        return AjaxResult.success();
+//        ExcelUtils<LotExportDTO> util = new ExcelUtils<>(LotExportDTO.class);
+//        util.exportExcelHttp(lotList, response, "拍品管理导出");
+
+
+        List<ExportFieldDto> excelFields = new ExcelUtil<>(LotExportDTO.class).getExcelFields();
+        EasyExcelFactory.init(EasyExcelTypeEnums.EXPORT , LotExportDTO.class, "拍品管理导出", EasyColumnEnums.include, excelFields)
+            .build()
+            .doWriteStream(lotList);
+
+
+        return AjaxResult.success();
     }
 
 

+ 5 - 0
lot/pom.xml

@@ -203,6 +203,11 @@
 			<version>3.17</version>
 		</dependency>
 
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>easyexcel</artifactId>
+			<version>3.3.2</version>
+		</dependency>
 
 	</dependencies>
 </project>

+ 49 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/EasyConfig.java

@@ -0,0 +1,49 @@
+package cn.hobbystocks.auc.common.easy;
+
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class EasyConfig {
+
+    //sheet
+    private List<Sheet> sheet;
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Sheet {
+
+        public Sheet(String type,String key, String name, Map<String, String> header){
+            this.type = type;
+            this.key = key;
+            this.name = name;
+            this.header = header;
+        }
+        //类型: map , bean
+        private String type;
+        //index
+        private int index;
+        //sheet映射的字段
+        private String key;
+        //sheet名称
+        private String name;
+        //sheet头
+        private Map<String, String> header;
+        //数据
+        private List<Map<String, String>> data;
+        //数据【非自定义头时使用】
+        private List<Object> beanDatas;
+        //导出字段
+        private List<ExportFieldDto> excelFields;
+
+    }
+
+
+
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/DictTypeFormat.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+/**
+ * 字典表转换注解
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DictTypeFormat {
+    String value();
+}

+ 40 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/HeadMerge.java

@@ -0,0 +1,40 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.FIELD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface HeadMerge {
+    /**
+     * 是否需要合并
+     */
+    boolean merge() default false;
+
+    /**
+     * 合并方向:ROW 行合并,COLUMN 列合并
+     */
+    MergeDirection mergeDirection() default MergeDirection.ROW;
+
+    /**
+     * 合并单元格数量(默认为1)
+     */
+    int mergeSpan() default 1;
+
+    /**
+     * 描述信息(默认为空)
+     */
+    String description() default "";
+
+    /**
+     * 自定义样式(默认无样式)
+     */
+    String style() default "";
+
+    /**
+     * 合并方向枚举
+     */
+    enum MergeDirection {
+        ROW, COLUMN
+    }
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/IsMust.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+
+import java.lang.annotation.*;
+
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface IsMust {
+
+
+
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/ReadConverterExpFormat.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+/**
+ * 列举数据转换注解
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ReadConverterExpFormat {
+    String value();
+}

+ 20 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyColumnEnums.java

@@ -0,0 +1,20 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import lombok.Getter;
+
+@Getter
+public enum EasyColumnEnums {
+    //包含
+    include("import"),
+    //忽略
+    export("export");
+
+    private String type;
+
+    EasyColumnEnums(String type)
+    {
+        this.type = type;
+    }
+
+
+}

+ 406 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelFactory.java

@@ -0,0 +1,406 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import cn.hobbystocks.auc.common.easy.EasyConfig;
+import cn.hobbystocks.auc.common.easy.util.EasyExcelImportUtil;
+import cn.hobbystocks.auc.common.easy.util.EasyExcelUtil;
+import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.common.utils.Global;
+import cn.hobbystocks.auc.common.utils.ServletUtils;
+import cn.hobbystocks.auc.common.utils.StringUtils;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.list.TreeList;
+
+import javax.servlet.ServletOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ *
+ */
+@Slf4j
+public class EasyExcelFactory<T,R> {
+    private EasyExcelTypeEnums type;
+    private final int pageSize = 1000;
+    //调用对象
+    protected Object service;
+    //调用方法
+    protected String methodName;
+    //查询总数
+    protected String countMethodName;
+    //查询参数
+    protected Object param;
+    // 是否合并表头
+    private Boolean headMerge;
+
+    private EasyExcelUtil<T, Object> easyExcelUtil;
+    private EasyExcelImportUtil<T, T> importerUtil;
+    private List<T> list ;
+    private String path;
+    private Class<T> clazz;
+    private String sheetName;
+    private EasyColumnEnums columnsType;
+    private List<ExportFieldDto> exportFields;
+    private File file;
+    private EasyConfig easyConfig;
+
+    /**
+     * @param type
+     * @param service
+     * @param methodName
+     * @param countMethodName
+     * @param param
+     * @return
+     */
+    public static EasyExcelFactory initConfig(EasyExcelTypeEnums type,Object service, String methodName,String countMethodName, Object param){
+        EasyExcelFactory factory = new EasyExcelFactory();
+        factory.type = type;
+        factory.service = service;
+        factory.methodName = methodName;
+        factory.countMethodName = countMethodName;
+        factory.param = param;
+        return factory;
+    }
+
+    /**
+     * @param clazz
+     * @param name
+     * @param columnsType
+     * @param exportFields
+     * @param <T>
+     * @param <R>
+     * @return
+     */
+    public static <T, R> EasyExcelFactory<T,R> init(EasyExcelTypeEnums type,Class<T> clazz, String name,EasyColumnEnums columnsType, List<ExportFieldDto> exportFields){
+        EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
+        factory.type = type;
+        factory.clazz = clazz;
+        factory.sheetName = name;
+        factory.columnsType = columnsType;
+        factory.exportFields = exportFields;
+        return factory;
+    }
+
+    /**
+     * @param type
+     * @param clazz
+     * @param url
+     * @param <T>
+     * @param <R>
+     * @return
+     */
+    public static <T, R> EasyExcelFactory<T, R> init(EasyExcelTypeEnums type,Class<T> clazz, String url){
+        EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
+        factory.type = type;
+        factory.clazz = clazz;
+        factory.path = url;
+        return factory;
+    }
+
+    public EasyExcelFactory<T,R> easyConfig(EasyConfig easyConfig){
+        this.easyConfig = easyConfig;
+        return this;
+    }
+
+    /**
+     * @param headMerge
+     * @return
+     */
+    public EasyExcelFactory<T,R> headMerge(boolean headMerge){
+        this.headMerge = headMerge;
+        return this;
+    }
+
+
+    /**
+     * @param clazz
+     * @param <T>
+     * @return
+     */
+    public static<T> Object getExcelFields(Class<T> clazz) {
+        List<ExportFieldDto> exportFields = new ArrayList<>();
+        if(!Objects.isNull(clazz)){
+            Arrays.asList(clazz.getDeclaredFields()).forEach(field -> {
+                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+                if(!Objects.isNull(excelProperty)){
+                    ExportFieldDto exportFieldDto = new ExportFieldDto(excelProperty.value()[0],false);
+                    exportFields.add(exportFieldDto);
+                }
+            });
+        }
+        return exportFields;
+    }
+
+    /**
+     * @return
+     */
+    public EasyExcelFactory<T,R> build(){
+        switch (type){
+            case EXPORT: //导出
+                path = Global.getDownloadPath() + "//easyDownload-" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date()) + "//" + this.sheetName + ".xlsx";
+                if(Objects.isNull(easyConfig)){
+                    Set<String> exportColumns = name2Column(this.clazz, exportFields);
+                    easyExcelUtil = EasyExcelUtil.init(this.clazz, this.sheetName)
+                                                 .path(path)
+                                                 .headMerge(!Objects.isNull(this.headMerge) && this.headMerge)
+                                                 //设置包含选中的字段导出
+                                                 .includeColumns(this.columnsType, exportColumns)
+                                                 .build();
+                }
+                break;
+            case IMPORT: //导入
+                list = new ArrayList<>();
+                importerUtil = EasyExcelImportUtil.create(clazz, list::addAll, Function.identity())
+                                                  .batch();
+                break;
+        }
+        return this;
+    }
+
+    /**
+     * @param tList
+     */
+    private void writeFile(List<T> tList){
+        try {
+            if (!Objects.isNull(tList)) {
+                easyExcelUtil.doWrite(tList);
+            }
+        }catch (Exception e){
+            log.error("导出excel失败",e);
+        } finally {
+            Optional.ofNullable(tList).orElseGet(ArrayList::new).clear();
+        }
+    }
+
+    /**
+     * 导出流
+     * @param tList
+     */
+    public void doWriteStream(List<T> tList){
+        try {
+            writeFile(tList);
+            if (!Objects.isNull(easyExcelUtil)) {
+                easyExcelUtil.finish();
+                ServletOutputStream outputStream = ServletUtils.getResponse().getOutputStream();
+                outputStream.write(easyExcelUtil.getBytes());
+            }
+        } catch (Exception e) {
+            log.error("easy导出excel失败",e);
+        } finally {
+            clear();
+        }
+    }
+
+    /**
+     *
+     */
+    public void finish(){
+        if(!Objects.isNull(easyExcelUtil)) {
+            easyExcelUtil.finish();
+        }
+    }
+
+    /**
+     *
+     */
+    public void clear(){
+        if(!Objects.isNull(easyExcelUtil)) {
+            easyExcelUtil.clear();
+        }
+        if(StringUtils.isNotBlank(path) && !path.startsWith("http")){
+            try {
+                File file = new File(path);
+                if(file.exists()){
+                    file.delete();
+                }
+                if(file.getParentFile().exists()){
+                    file.getParentFile().delete();
+                }
+            }catch (Exception e){
+                log.error("删除文件失败",e);
+            }
+        }
+    }
+
+
+    private int searchCount(){
+        try {
+            Method method = service.getClass().getMethod(countMethodName, param.getClass());
+            return (int) method.invoke(service, param);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+    /**
+     * @param fieldName
+     * @param clazz
+     * @return
+     */
+    private Object getValueByField(String fieldName,Class<?> clazz) {
+        try {
+            Field field = this.param.getClass().getDeclaredField(fieldName);
+            field.setAccessible(true);
+            Object value = field.get(this.param);
+            if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
+                return value;
+            }
+            return field.get(this.param);
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+            try {
+                Field field = this.param.getClass().getSuperclass().getDeclaredField(fieldName);
+                field.setAccessible(true);
+                Object value = field.get(this.param);
+                if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
+                    return value;
+                }
+                return field.get(this.param);
+            } catch (NoSuchFieldException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            }
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * @return
+     */
+    private List searchList() {
+        try {
+            Method method = service.getClass().getMethod(methodName, param.getClass());
+            return (List) method.invoke(service, param);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    private Set<String> name2Column(Class<T> claszz, List<ExportFieldDto> exportFields) {
+        Set<String> columns = new HashSet<>();
+        Field[] fields = claszz.getDeclaredFields();
+        Set<String> sets = Optional.ofNullable(exportFields).orElse(new ArrayList<>()).stream().map(ExportFieldDto::getName).collect(Collectors.toSet());
+        for (Field field : fields) {
+            field.setAccessible(true);
+            //获取属性名
+            //是否存在注解
+            if(field.isAnnotationPresent(ExcelProperty.class)) {
+                ExcelProperty excelProperty =  field.getAnnotation(ExcelProperty.class);
+                if (CollectionUtils.isEmpty(exportFields) || sets.contains(Optional.ofNullable(excelProperty.value()).orElse(new String[]{"default"})[0])){
+                    columns.add(field.getName());
+                }
+            }
+        }
+        return columns;
+    }
+
+    /**
+     * @param easyConfig
+     * @param excelWriter
+     */
+    public void doWriteBySheetFinal(EasyConfig easyConfig, ExcelWriter excelWriter){
+        if (Objects.nonNull(easyConfig) && CollectionUtils.isNotEmpty(easyConfig.getSheet())) {
+            List<EasyConfig.Sheet> sheets = easyConfig.getSheet();
+            for (int i = 0; i < sheets.size(); i++) {
+                EasyConfig.Sheet sheet = sheets.get(i);
+                if (StringUtils.isNotBlank(sheet.getType())) {
+                    if (Objects.equals(sheet.getType(), "map")) {
+                        //header 按照key值正序排序 转成List<List<String>>
+                        Map<String, String> headerMap = sheet.getHeader();
+                        List<List<String>> header = headerMap.entrySet()
+                                                             .stream()
+                                                             .sorted(Map.Entry.comparingByKey())
+                                                             .map(item -> {
+                                                                 String value = item.getValue();
+                                                                 return Collections.singletonList(value);
+                                                             })
+                                                             .collect(Collectors.toList());
+                        List<String> headerKeys = headerMap.entrySet()
+                                                           .stream()
+                                                           .sorted(Map.Entry.comparingByKey())
+                                                           .map(Map.Entry::getKey)
+                                                           .collect(Collectors.toList());
+                        List<Map<String, String>> i18nSheetDatas = sheet.getData();
+                        //以header 对 i8nSheetData 进行排序 并返回 List<List<String>>
+                        List<List<String>> i18nSheetData = i18nSheetDatas.stream()
+                                                                         //根据headerKeys 值进行排序
+                                                                         .sorted(Comparator.comparing(item -> {
+                                                                             //判断头部是否存在 如果不存在则在最后添加一条
+                                                                             //获取 item key value
+                                                                             Set<String> keySet = item.keySet();
+                                                                             keySet.forEach(key -> {
+                                                                                 if (!headerKeys.contains(key)) {
+                                                                                     headerKeys.add(key);
+                                                                                     header.add(Collections.singletonList(key));
+                                                                                 }
+                                                                             });
+                                                                             return Optional.ofNullable(item.get(headerKeys.iterator()
+                                                                                                                           .next()))
+                                                                                            .orElse("");
+                                                                         }))
+                                                                         .map(item -> {
+                                                                             List<String> dataList = new TreeList();
+                                                                             headerKeys.forEach(kk -> {
+                                                                                 String vv = item.get(kk);
+                                                                                 if (org.apache.commons.lang3.StringUtils.isEmpty(vv)) {
+                                                                                     vv = "";
+                                                                                 }
+                                                                                 dataList.add(vv);
+                                                                             });
+                                                                             return dataList;
+                                                                         })
+                                                                         .collect(Collectors.toList());
+                        //对i18nSheetData 做去重处理
+                        i18nSheetData = i18nSheetData.stream()
+                                                     .distinct()
+                                                     .collect(Collectors.toList());
+                        WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                         .head(header)
+                                                         .useDefaultStyle(true)
+                                                         .build();
+                        excelWriter.write(i18nSheetData, writeSheet);
+                    } else {
+                        List<Object> beanDatas = sheet.getBeanDatas();
+                        List<String> fieldNames = null;
+                        if(CollectionUtils.isNotEmpty(sheet.getExcelFields())){
+                            fieldNames = sheet.getExcelFields()
+                                              .stream()
+                                              .map(ExportFieldDto::getName)
+                                              .collect(Collectors.toList());
+                        }
+                        Object beanData = beanDatas.get(0);
+                        WriteSheet writeSheet;
+                        if (CollectionUtils.isNotEmpty(fieldNames)) {
+                            writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                  .head(beanData.getClass())
+                                                  .useDefaultStyle(true)
+                                                  //设置包含选中的字段导出
+                                                  .includeColumnFieldNames(fieldNames)
+                                                  .build();
+                        } else {
+                            writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                  .head(beanData.getClass())
+                                                  .useDefaultStyle(true)
+                                                  .build();
+                        }
+                        excelWriter.write(beanDatas, writeSheet);
+                    }
+                }
+            }
+        }
+
+    }
+
+
+}

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelTypeEnums.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import lombok.Getter;
+
+@Getter
+public enum EasyExcelTypeEnums {
+
+    //导入
+    IMPORT("import", "导入"),
+
+    //导出
+    EXPORT("export", "导出");
+
+    private String type;
+
+    private String desc;
+
+    EasyExcelTypeEnums(String type, String desc) {
+        this.type = type;
+        this.desc = desc;
+    }
+
+
+
+}

+ 228 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/handler/EasyDataFormatHandler.java

@@ -0,0 +1,228 @@
+package cn.hobbystocks.auc.common.easy.handler;
+
+import cn.hobbystocks.auc.common.easy.annotion.DictTypeFormat;
+import cn.hobbystocks.auc.common.easy.annotion.ReadConverterExpFormat;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.metadata.property.FontProperty;
+import com.alibaba.excel.metadata.property.StyleProperty;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 字典表查询注解监听
+ * 列数据格式化
+ */
+@Slf4j
+public class EasyDataFormatHandler implements CellWriteHandler {
+
+    // 用于记录每列的最大宽度
+    public final Map<Integer, Integer> maxWidthMap = new HashMap<>();
+    @Setter
+    private int dataSize = 0;
+    private boolean headMerge;
+
+
+    public static EasyDataFormatHandler init(Integer dataSize){
+        EasyDataFormatHandler handler = new EasyDataFormatHandler();
+        handler.setDataSize(dataSize);
+        return handler;
+    }
+
+    public EasyDataFormatHandler headMerge(boolean headMerge) {
+        this.headMerge = headMerge;
+        return this;
+    }
+
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
+                                 Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
+        if (isHead) {
+            // 设置头部 列宽
+            int currentWidth = calculateTextLength(head.getHeadNameList().get(0));
+            maxWidthMap.put(columnIndex, Math.max(maxWidthMap.getOrDefault(columnIndex, 0), currentWidth));
+            log.info(" 设置头部 列宽 ");
+            // 设置表头样式
+            StyleProperty styleProperty = new StyleProperty();
+            styleProperty.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//灰色
+            head.setHeadStyleProperty(styleProperty);
+            //设置字号 11
+            FontProperty fontProperty = new FontProperty();
+            fontProperty.setFontHeightInPoints((short) 11);
+            head.setHeadFontProperty(fontProperty);
+        }
+    }
+
+    /**
+     * @param writeSheetHolder
+     * @param writeTableHolder
+     * @param cell
+     * @param head
+     * @param relativeRowIndex
+     * @param isHead
+     */
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
+                                Head head, Integer relativeRowIndex, Boolean isHead) {
+        //判断是否是最后一条 row
+        if(dataSize == relativeRowIndex + 1 || (dataSize == 0 && isHead)) {
+            // 所有数据写入完成后,设置列宽
+            writeSheetHolder.getSheet()
+                            .forEach(row -> {
+                                row.forEach(r -> {
+                                    int columnIndex = r.getColumnIndex();
+                                    Integer maxWidth = maxWidthMap.get(columnIndex);
+                                    if (maxWidth != null && maxWidth > 0) {
+                                        // 设置列宽,单位是 1/256 字符宽度
+                                        writeSheetHolder.getSheet()
+                                                        .setColumnWidth(columnIndex, (maxWidth) * 256);
+                                    }
+                                });
+                            });
+        }
+    }
+
+    @Override
+    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
+                                       WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex,
+                                       Boolean isHead) {
+        if (!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(ReadConverterExpFormat.class)) {
+            Field field = head.getField();
+            field.setAccessible(true);
+            ReadConverterExpFormat annotation = field.getAnnotation(ReadConverterExpFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                String cellValue = cellData.getStringValue();
+                switch (cellData.getType()){
+                    case NUMBER:
+                        cellValue = String.valueOf(cellData.getNumberValue());
+                        break;
+                    case STRING:
+                        break;
+                    case DATE:
+                        LocalDateTime dateValue = cellData.getDateValue();
+                        //LocalDateTime 转 String
+//                        cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+                        break;
+                }
+                String[] expDatas = annotation.value().split(",");
+                String finalCellValue = cellValue;
+                Arrays.asList(expDatas).forEach(expData -> {
+                    String[] expDataArr = expData.split("=");
+                    if(Objects.equals(finalCellValue, expDataArr[0])){
+                        cellData.setType(CellDataTypeEnum.STRING);
+                        cellData.setStringValue(expDataArr[1]);
+                        cell.setCellType(CellType.STRING);
+                        cell.setCellValue(expDataArr[1]);
+                    }
+                });
+            }
+        }else if(!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(DictTypeFormat.class)){
+            //查询字典表数据
+            DictTypeFormat annotation = head.getField().getAnnotation(DictTypeFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                String cellValue = cellData.getStringValue();
+                switch (cellData.getType()){
+                    case NUMBER:
+                        cellValue = String.valueOf(cellData.getNumberValue());
+                        break;
+                    case STRING:
+                        break;
+                    case DATE:
+                        LocalDateTime dateValue = cellData.getDateValue();
+                        //LocalDateTime 转 String
+//                        cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+                        break;
+                    }
+                if (StringUtils.isNotBlank(cellValue)) {
+//                    String dictValue = DictUtils.getDictLabel(annotation.value(), cellValue, ",");
+                    cellData.setType(CellDataTypeEnum.STRING);
+//                    cellData.setStringValue(dictValue);
+                }
+            }
+        }else if(!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(DateTimeFormat.class)){
+            //如果有时间格式化注解
+            DateTimeFormat annotation = head.getField().getAnnotation(DateTimeFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                LocalDateTime dateValue = cellData.getDateValue();
+                //LocalDateTime 转 String
+//                String cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+//                if (StringUtils.isNotBlank(cellValue)) {
+//                    cellData.setType(CellDataTypeEnum.STRING);
+//                    cellData.setStringValue(cellValue);
+//                }
+            }
+        }
+        // 设置列最大宽度
+        checkCellMaxWith(cellData, cell);
+    }
+
+    /**
+     * 设置列最大宽度
+     * @param cellData
+     * @param cell
+     */
+    private void checkCellMaxWith(WriteCellData<?> cellData, Cell cell) {
+        int columnIndex = cell.getColumnIndex();
+        int currentWidth = 0;
+
+        switch (cellData.getType()) {
+            case STRING:
+                //currentWidth = 中文字符 * 2  || currentWidth = 英文 等字符 * 1
+                currentWidth = calculateTextLength(cellData.getStringValue());
+                break;
+            case NUMBER:
+                currentWidth = String.valueOf(cellData.getNumberValue()).length();
+                break;
+            case BOOLEAN:
+                currentWidth = String.valueOf(cellData.getBooleanValue()).length();
+                break;
+            case DATE:
+                currentWidth = String.valueOf(cellData.getDateValue()).length();
+                break;
+            case ERROR:
+            case EMPTY:
+            default:
+                break;
+        }
+
+        // 更新最大宽度
+        maxWidthMap.put(columnIndex, Math.max(maxWidthMap.getOrDefault(columnIndex, 0), currentWidth));
+    }
+    private int calculateTextLength(String text) {
+        if (text == null || text.isEmpty()) {
+            return 0;
+        }
+
+        int length = 0;
+        for (char c : text.toCharArray()) {
+            if (String.valueOf(c).getBytes().length > 1) {
+                // 中文字符,占 2 个英文字符宽度
+                length += 2;
+            } else {
+                // 英文字符,占 1 个英文字符宽度
+                length += 1;
+            }
+        }
+        if(length > 255){
+            length = 255;
+        }
+        return length;
+    }
+}

+ 192 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelImportUtil.java

@@ -0,0 +1,192 @@
+package cn.hobbystocks.auc.common.easy.util;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * @author hdd
+ * @description
+ * @date 2024/4/9 12:26
+ */
+public class EasyExcelImportUtil<T, R> {
+
+    /**
+     * excel行数据转换
+     */
+    private Function<T, R> rowConverter;
+
+    /**
+     * 解析后的数据处理
+     */
+    private Consumer<List<R>> consumer;
+
+    /**
+     * 是否对读取到的数据进行批量处理
+     */
+    private boolean batch;
+
+    /**
+     * 批处理数
+     */
+    private int batchCount = 500;
+
+    /**
+     * 是否异步处理读取到到数据
+     */
+    private boolean async;
+
+    /**
+     * excel行数据读取后转换成指定类对象
+     */
+    private Class<T> clazz;
+
+    /**
+     * 异步线程池
+     */
+    private ThreadPoolExecutor executor;
+
+    /**
+     * 构建
+     */
+    public static <T, R> EasyExcelImportUtil<T, R> create(Class<T> clazz, Consumer<List<R>> consumer, Function<T, R> rowConverter) {
+        EasyExcelImportUtil<T, R> util = new EasyExcelImportUtil<>();
+        util.clazz = clazz;
+        util.consumer = consumer;
+        util.rowConverter = rowConverter;
+        return util;
+    }
+
+    /**
+     * 批处理
+     */
+    public EasyExcelImportUtil<T, R> batch() {
+        return batch(batchCount);
+    }
+
+    /**
+     * 批处理
+     */
+    public EasyExcelImportUtil<T, R> batch(Integer batchCount) {
+        if (batchCount == null || batchCount <= 0) {
+            throw new IllegalArgumentException("批处理数必须大于0");
+        }
+        this.batch = true;
+        this.batchCount = batchCount;
+        return this;
+    }
+
+    /**
+     * 异步操作设置线程池
+     */
+    public EasyExcelImportUtil<T, R> async(ThreadPoolExecutor executor) {
+        this.executor = executor;
+        this.async = true;
+        return this;
+    }
+
+    /**
+     * 设置转换器
+     *
+     * @param rowConverter
+     * @return
+     */
+    public EasyExcelImportUtil<T, R> rowConverter(Function<T, R> rowConverter) {
+        this.rowConverter = rowConverter;
+        return this;
+    }
+
+    /**
+     * 读取并处理excel
+     */
+    public void doRead(InputStream inputStream) {
+        EasyExcel.read(inputStream, this.clazz, new DefaultListener()).sheet().doRead();
+    }
+
+    /**
+     * 读取并处理excel
+     */
+    public void doReadByHttp(String fileUrl) throws Exception {
+        InputStream inputStream = null;
+        try {
+            inputStream = download(fileUrl);
+            EasyExcel.read(inputStream, this.clazz, new DefaultListener()).sheet().doRead();
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        }
+    }
+
+    private InputStream download(String path) throws IOException {
+        URL url = new URL(path);
+        //打开链接
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        //设置请求方式为"GET"
+        conn.setRequestMethod("GET");
+        //超时响应时间为20秒
+        conn.setConnectTimeout(20 * 1000);
+        conn.setReadTimeout(120 * 1000);
+        //通过输入流获取图片数据
+        return conn.getInputStream();
+    }
+
+    private class DefaultListener extends AnalysisEventListener<T> {
+
+        private final List<R> list = new ArrayList<>();
+
+        private final List<CompletableFuture<Void>> futureList = new ArrayList<>();
+
+        /**
+         * 处理每行的时候都会调用
+         */
+        @Override
+        public void invoke(T t, AnalysisContext analysisContext) {
+            list.add(rowConverter.apply(t));
+            if (!batch || list.size() >= batchCount) {
+                handle();
+            }
+        }
+
+        /**
+         * 处理结束的时候
+         */
+        @Override
+        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+            handle();
+            // 异步处理时等待所有线程执行结束
+            if (async) {
+                CompletableFuture[] futures = futureList.toArray(new CompletableFuture[futureList.size()]);
+                CompletableFuture<Void> future = CompletableFuture.allOf(futures);
+                future.join();
+            }
+        }
+
+        private void handle() {
+            if (list.isEmpty()) {
+                return;
+            }
+            List<R> newList = new ArrayList<>(list);
+            list.clear();
+            if (!async) {
+                consumer.accept(newList);
+            } else {
+                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> consumer.accept(newList), executor);
+                futureList.add(future);
+            }
+        }
+
+    }
+
+}

+ 254 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelUtil.java

@@ -0,0 +1,254 @@
+package cn.hobbystocks.auc.common.easy.util;
+
+import cn.hobbystocks.auc.common.easy.factory.EasyColumnEnums;
+import cn.hobbystocks.auc.common.easy.handler.EasyDataFormatHandler;
+import cn.hobbystocks.auc.common.exception.ServiceException;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.builder.ExcelWriterBuilder;
+import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * 导出工具类
+ */
+@Slf4j
+public class EasyExcelUtil<T, R> {
+
+    /**
+     *
+     */
+    private Class<T> clazz;
+    /**
+     *
+     */
+    private String sheet;
+    /**
+     *
+     */
+    private List<T> data;
+
+    /**
+     *
+     */
+    private String path;
+
+    /**
+     *
+     */
+    private File file ;
+
+    private ExcelWriter writer;
+    private WriteSheet writeSheet;
+    private ExcelWriterSheetBuilder writerSheetBuilder;
+    //
+    private EasyColumnEnums columnsType;
+    //字段
+    private Set<String> columns;
+    //
+    private int startIndex;
+    // 是否合并表头
+    private boolean headMerge;
+
+
+    /**
+     * @param clazz
+     * @param data
+     * @return
+     */
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, List<T> data) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.data = data;
+        return that;
+    }
+
+    /**
+     * @param clazz
+     * @param data
+     * @param sheet
+     * @return
+     */
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, List<T> data, String sheet) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.data = data;
+        that.sheet = sheet;
+        return that;
+    }
+
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, String sheet) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.sheet = sheet;
+        return that;
+    }
+
+    /**
+     * @param path
+     * @return
+     */
+    public EasyExcelUtil<T, R> path(String path){
+        this.path = path;
+        return this;
+    }
+
+    /**
+     *
+     * @param columns
+     * @return
+     * @see EasyColumnEnums
+     */
+    public EasyExcelUtil<T, R> includeColumns(EasyColumnEnums columnsType, Set<String> columns){
+        this.columnsType = columnsType;
+        this.columns = columns;
+        return this;
+    }
+
+    public EasyExcelUtil<T, R> headMerge(boolean headMerge){
+        this.headMerge = headMerge;
+        return this;
+    }
+    /**
+     * @return
+     */
+    public EasyExcelUtil<T, R> build() {
+        File file = new File(path);
+        if (!file.getParentFile().exists()) {
+            file.getParentFile().mkdirs();
+        }
+        this.file = file;
+        this.writer = EasyExcel.write(path, this.clazz).build();
+        int size = Objects.isNull(data)?0:data.size();
+        if (CollectionUtils.isNotEmpty(columns)) {
+            if (Objects.nonNull(columnsType)) {
+                switch (columnsType) {
+                    case include: //包含
+                        this.writerSheetBuilder = EasyExcel.writerSheet(sheet)
+//                                                   .registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge))
+                                                   .includeColumnFieldNames(columns)
+                                                   .useDefaultStyle(true)
+                                                   ;
+                        break;
+                    case export: //排除
+                        this.writerSheetBuilder = EasyExcel
+                                                   .writerSheet(sheet)
+//                                                   .registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge))
+                                                   .excludeColumnFieldNames(columns)
+                                                   .useDefaultStyle(true)
+                                                   ;
+                        break;
+                }
+            }
+        } else {
+            this.writerSheetBuilder = EasyExcel.writerSheet(sheet)
+                                       .useDefaultStyle(true)
+                                       ;
+        }
+        if(!Objects.equals(size, 0)){
+            this.writerSheetBuilder = this.writerSheetBuilder.registerWriteHandler(EasyDataFormatHandler.init(size));
+        }
+        return this;
+    }
+
+
+    public void doWrite(List<T> data) {
+        //是否存在文件
+        try {
+            if (Objects.isNull(this.file)) {
+                throw new ServiceException("文件不存在",500);
+            }
+            int size = Objects.isNull(data)?0:data.size();
+            this.writer.write(data,this.writerSheetBuilder.registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge)).build());
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常 doWrite {} ",e);
+            throw new ServiceException("生成excel文件时异常[doWrite]",500 );
+        }
+    }
+
+    public void finish() {
+        try {
+            if (Objects.isNull(this.file)) {
+                throw new ServiceException("文件不存在", 500);
+            }
+            this.writer.finish();
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常 finish {} ",e);
+            throw new ServiceException("生成excel文件时异常[finish]", 500);
+        }
+    }
+
+    /**
+     *
+     */
+    public void doWrite(String path) {
+        //是否存在文件
+        try {
+            File file = new File(path);
+            if (!file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            ExcelWriterBuilder write = EasyExcel.write(path, clazz);
+            write.sheet(sheet).useDefaultStyle(true)
+                 .doWrite(data);
+            this.path = path;
+            this.file = file;
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常{} ",e);
+            throw new ServiceException("下载文件时异常",500 );
+        }
+    }
+
+
+    /**
+     *
+     */
+    public void doWriteStream(OutputStream out) {
+        //是否存在文件
+        try {
+            EasyExcel.write(out,clazz).sheet(sheet).doWrite(data);
+        } catch (Exception e) {
+            log.error(" 生成excel流时异常{} ",e);
+            throw new ServiceException("下载文件时异常",500);
+        }
+    }
+    /**
+     *
+     */
+    public void clear( ){
+        File file = new File(path);
+        if(!Objects.isNull(file)){
+            boolean delete = file.delete();
+            if (delete) {
+                file.getParentFile().delete();
+            }
+        }
+
+    }
+
+    public byte[] getBytes() {
+        try {
+            return Files.readAllBytes(this.file.toPath());
+        } catch (Exception e) {
+            log.error(" 获取文件流异常{} ",e);
+            throw new ServiceException("获取文件流异常",500);
+        }
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public void setFile(File file) {
+        this.file = file;
+    }
+}

+ 134 - 0
lot/src/main/java/cn/hobbystocks/auc/common/poi/ExcelUtil.java

@@ -0,0 +1,134 @@
+package cn.hobbystocks.auc.common.poi;
+
+
+import cn.hobbystocks.auc.common.core.text.Convert;
+import cn.hobbystocks.auc.common.utils.*;
+import cn.hobbystocks.auc.common.utils.reflect.ReflectUtils;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Excel相关处理
+ *
+ * @author zheng
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    /**
+     * Excel sheet最大行数,默认65536
+     */
+    public static final int sheetSize = 65536;
+    /**
+     * 文件保存路径
+     */
+    private String filepath;
+
+    /**
+     * 工作表名称
+     */
+    private String sheetName;
+
+    /**
+     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
+     */
+    private Excel.Type type;
+
+    /**
+     * 工作薄对象
+     */
+    private Workbook wb;
+
+    /**
+     * 工作表对象
+     */
+    private Sheet sheet;
+
+    /**
+     * 样式列表
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 导入导出数据列表
+     */
+    private List<T> list;
+
+    /**
+     * 注解列表
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 实体对象
+     */
+    public Class<T> clazz;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    public void init(List<T> list, String sheetName, Excel.Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+    }
+
+    /**
+     * 得到所有定义字段
+     */
+    public List<ExportFieldDto> getExcelFields()
+    {
+        List<ExportFieldDto> fields = new ArrayList<ExportFieldDto>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        for (Field field : tempFields)
+        {
+            // 单注解
+            if (field.isAnnotationPresent(Excel.class))
+            {
+                fields.add(new ExportFieldDto(field.getAnnotation(Excel.class).name(),field.getAnnotation(Excel.class).isMust()));
+            }
+
+            // 多注解
+            if (field.isAnnotationPresent(Excels.class))
+            {
+                Excels attrs = field.getAnnotation(Excels.class);
+                Excel[] excels = attrs.value();
+                for (Excel excel : excels)
+                {
+                    fields.add(new ExportFieldDto(excel.name(),excel.isMust()));
+                }
+            }
+        }
+        return fields;
+    }
+
+}

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/dto/ExportFieldDto.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+@Data
+@ToString
+@NoArgsConstructor
+public class ExportFieldDto {
+
+    public ExportFieldDto(String name, boolean isMust){
+        this.name = name;
+        this.isMust = isMust;
+    }
+
+    private String name;
+
+    private String dateFormat;
+
+    private boolean isMust;
+
+
+
+}

+ 16 - 2
lot/src/main/java/cn/hobbystocks/auc/dto/LotExportDTO.java

@@ -3,6 +3,7 @@ package cn.hobbystocks.auc.dto;
 import cn.hobbystocks.auc.annotation.Sensitive;
 import cn.hobbystocks.auc.annotation.View;
 import cn.hobbystocks.auc.common.utils.Excel;
+import com.alibaba.excel.annotation.ExcelProperty;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
@@ -17,65 +18,78 @@ import java.util.Date;
 public class LotExportDTO {
 
     @Excel(name = "拍品ID")
+    @ExcelProperty(value = "拍品ID") // 新增
     private String id;
 
     /** 商品ID */
     @Excel(name = "商品ID")
+    @ExcelProperty(value = "商品ID") // 新增
     private String goodsId;
 
     @Excel(name = "商品名称")
+    @ExcelProperty(value = "商品名称") // 新增
     private String goodsName;
 
     @Excel(name = "商品种类")
+    @ExcelProperty(value = "商品种类") // 新增
     private String goodsType;
 
     /** 排序 */
     @Excel(name = "排序")
+    @ExcelProperty(value = "排序") // 新增
     private String sort;
 
     /** 出价次数 */
     @Excel(name = "出价次数")
+    @ExcelProperty(value = "出价次数") // 新增
     private String bidCount;
 
     /** (1已上架  2已下架  0未审核) */
     @Excel(name = "状态")
+    @ExcelProperty(value = "状态") // 新增
     private String pubStatus;
 
-
     /** 拍卖状态(Waiting:未开始;Starting:开启中;Bidding:进行中;Finished:拍卖结束;Cancelled:撤拍;Pass:流拍;Sold:成交) */
     @Excel(name = "拍卖状态")
+    @ExcelProperty(value = "拍卖状态") // 新增
     private String status;
 
     /** 创建时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @Excel(name = "创建时间")
+    @ExcelProperty(value = "创建时间") // 新增
     private String createTime;
 
     /** 拍卖开始时间 */
     @Excel(name = "拍卖开始时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ExcelProperty(value = "拍卖开始时间") // 新增
     private String startTime;
 
     /** 拍卖结束时间 */
     @Excel(name = "拍卖结束时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ExcelProperty(value = "拍卖结束时间") // 新增
     private String endTime;
 
     /** 保证金(元) */
     @Excel(name ="保证金(元)")
+    @ExcelProperty(value = "保证金(元)") // 新增
     private String deposit;
 
     /** 服务费(%) */
     @Excel(name ="服务费(%)")
+    @ExcelProperty(value = "服务费(%)") // 新增
     private String serviceTariff;
 
     /** 规则类型:traditional_delay;标准延时,traditional_delay_v2:重置延时,traditional_delay_v3:增价拍卖 */
     @Excel(name ="拍卖方式")
+    @ExcelProperty(value = "拍卖方式") // 新增
     private String ruleType;
 
     /** 最新价格 */
     @Excel(name ="起拍价/当前价")
+    @ExcelProperty(value = "起拍价/当前价") // 新增
     private String lastPrice;
 
-
 }