jiangping
2025-02-19 07ca844b3441a2774a1ca02a952e27e3fe986819
jtt808初始化
已添加3个文件
已删除1个文件
已修改18个文件
1660 ■■■■■ 文件已修改
server/platform/src/main/java/com/doumee/api/business/BikesController.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/platform/src/main/java/com/doumee/task/ScheduleTool.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelColumn.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelDataHandlerAdapter.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelExporter.java 625 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelImporter.java 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExportExcelUtils.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/Reflections.java 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/constants/Constants.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/wx/WxMiniUtilService.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Bikes.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/vo/BikesImportVO.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/BikesService.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/BaseParamServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/BikesServiceImpl.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/DeviceSubscribeServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/LocksServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/PricingParamServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/SitesServiceImpl.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/AccountApi.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/platform/src/main/java/com/doumee/api/business/BikesController.java
@@ -8,13 +8,14 @@
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Bikes;
import com.doumee.service.business.BikesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -86,7 +87,15 @@
    public void exportExcel (@RequestBody PageWrap<Bikes> pageWrap, HttpServletResponse response) {
        ExcelExporter.build(Bikes.class).export(bikesService.findPage(pageWrap).getRecords(), "自行车信息表", response);
    }
    @ApiOperation(value = "电车批量导入" ,notes = "保单申请")
    @PostMapping("/importExcel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "file", required = true, paramType = "query", dataType = "file", dataTypeClass = File.class),
    })
    @RequiresPermissions("business:member:create")
    public ApiResponse<String> importExcel (@ApiParam(value = "file") MultipartFile file) {
        return ApiResponse.success(bikesService.importBatch(file));
    }
    @ApiOperation("根据ID查询")
    @GetMapping("/{id}")
    @RequiresPermissions("business:bikes:query")
server/platform/src/main/java/com/doumee/task/ScheduleTool.java
@@ -121,7 +121,7 @@
    /**
     * æ›´æ–°å¾®ä¿¡ ACCESS_TOKEN
     */
    @Scheduled(fixedDelay = 1000L * 60L * 90L)
//    @Scheduled(fixedDelay = 1000L * 60L * 90L)
    public void updAccessToken(){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        ThreadContext.bind(manager);
@@ -134,7 +134,7 @@
        }
        //生成微信token
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
        String response = HttpsUtil.doGet(url,null);
        String response = HttpsUtil.get(url,false);
        JSONObject json = JSONObject.parseObject(response);
        SystemDictData systemDictData = systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME,Constants.ACCESS_TOKEN);
        if(!Objects.isNull(systemDictData)){
server/pom.xml
@@ -30,7 +30,7 @@
    <swagger.bootstrap-ui.version>1.9.6</swagger.bootstrap-ui.version>
    <fastjson.version>1.2.70</fastjson.version>
    <druid.version>1.2.0</druid.version>
    <mybatis.plus.version>3.4.2</mybatis.plus.version>
    <mybatis.plus.version>3.5.7</mybatis.plus.version>
    <apache.shiro.version>1.9.1</apache.shiro.version>
    <oshi.version>5.7.0</oshi.version>
    <jna.version>5.7.0</jna.version>
@@ -90,11 +90,12 @@
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper-spring-boot-starter</artifactId>
      <version>1.3.0</version>
     <!-- <version>1.3.0</version>-->
      <!--使用spring boot2整合 pagehelper-spring-boot-starter必须排除一下依赖
          å› ä¸ºpagehelper-spring-boot-starter也已经在pom依赖了mybatis与mybatis-spring
          æ‰€ä»¥ä¼šä¸Žmybatis-plus-boot-starter中的mybatis与mybatis-spring发生冲突
      -->
      <version>2.1.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.mybatis</groupId>
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelColumn.java
@@ -8,18 +8,25 @@
/**
 * æ ‡è®°ä¸ºExcel列
 * @author Eva.Caesar Liu
 * @date 2022/04/18 18:12
 * @date 2023/02/14 11:14
 */
@Inherited
@Target(ElementType.FIELD)
//@Target(ElementType.FIELD)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
    /**
     * å¯¼å‡ºå­—段名(默认调用当前字段的“get”方法,如指定导出字段为对象,请填写“对象名.对象属性”,例:“area.name”、“office.name”)
     */
    String value() default "";
    /**
     * å­—段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    int type() default 0;
    /**
     * åˆ—名
     */
    String name();
    /**
     * åˆ—宽(单位为字符),-1自动计算
@@ -34,7 +41,7 @@
    /**
     * å¯¹é½æ–¹å¼
     */
    HorizontalAlignment  align() default HorizontalAlignment.LEFT;
    HorizontalAlignment align() default HorizontalAlignment.LEFT;
    /**
     * åˆ—背景色
@@ -96,4 +103,13 @@
     */
    String[] args() default {};
    /**
     * åå°„类型
     */
    Class<?> fieldType() default Class.class;
    /**
     * å­—段归属组(根据分组导出导入)
     */
    int[] groups() default {};
}
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelDataHandlerAdapter.java
@@ -3,7 +3,7 @@
/**
 * Excel数据格式处理适配器
 * @author Eva.Caesar Liu
 * @date 2022/04/18 18:12
 * @date 2023/02/14 11:14
 */
public interface ExcelDataHandlerAdapter {
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelExporter.java
@@ -4,40 +4,25 @@
import com.doumee.core.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationConfigurationException;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * Excel导出实现
 * @author Eva.Caesar Liu
 * @date 2022/04/18 18:12
 * @date 2023/02/14 11:14
 */
@Data
public class ExcelExporter<T> {
@@ -48,13 +33,6 @@
    private ExcelExporter(){}
    private final static Logger log = LoggerFactory.getLogger(ExcelExporter.class);
    private final static String EXCEL2003 = "xls";
    private final static String EXCEL2007 = "xlsx";
    /**
     * æž„造器
     * @param modelClass å®žä½“Class对象
@@ -63,6 +41,75 @@
        ExcelExporter<T> excelExporter = new ExcelExporter<>();
        excelExporter.setModelClass(modelClass);
        return excelExporter;
    }
    /**
     * å¯¼å‡ºåˆ°æŒ‡å®šè¾“出流
     * @param data æ•°æ®
     * @param sheetName Sheet名称
     */
    public void exportWithFirstAndEnd (List<T> data, String sheetName,String first,String end, OutputStream os) {
        SXSSFWorkbook sxssfWorkbook;
        try {
            sxssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = sxssfWorkbook.createSheet(sheetName);
            // åˆ›å»ºåˆ—头
            sheet.createFreezePane(0, 2);
            sheet.addMergedRegion(new CellRangeAddress(0   ,0,0,this.getColumns().size()-1));
            Row title = sheet.createRow(0);
            title.setHeight((short) 1000);
            Cell c = title.createCell(0);
            c.setCellValue(first);
            configFirstCell(sxssfWorkbook,c);
            Row header = sheet.createRow(1);
            List<ColumnInfo> columns = this.getColumns();
            for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                ColumnInfo column = columns.get(columnIndex);
                Cell cell = header.createCell(columnIndex);
                cell.setCellValue(column.columnConfig.name());
                // åˆ—宽设置
                if (column.columnConfig.width() == -1) {
                    sheet.setColumnWidth(columnIndex, column.columnConfig.name().length() * 2 * 256);
                } else {
                    sheet.setColumnWidth(columnIndex, column.columnConfig.width() * 2 * 256);
                }
                // è®¾ç½®åˆ—头单元格
                configHeaderCell(sxssfWorkbook, cell, column.columnConfig);
            }
            // åˆ›å»ºæ•°æ®è®°å½•
            for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
                Row row = sheet.createRow(rowIndex + 2);
                for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                    ColumnInfo column = columns.get(columnIndex);
                    Cell cell = row.createCell(columnIndex);
                    cell.setCellValue(getCellData(column, data.get(rowIndex)));
                    // è®¾ç½®æ•°æ®å•元格
                    configDataCell(sxssfWorkbook, cell, column.columnConfig);
                }
            }
            sheet.addMergedRegion(new CellRangeAddress(data.size()+2   ,data.size()+2,0,this.getColumns().size()-1));
            Row endRow = sheet.createRow(data.size()+2);
//            endRow.setHeight((short) 600);
            Cell c1 = endRow.createCell(0);
            c1.setCellValue(end);
            configEndCell(sxssfWorkbook,c1);
            sxssfWorkbook.write(os);
            os.close();
        } catch (Exception e) {
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
@@ -75,8 +122,6 @@
        SXSSFWorkbook sxssfWorkbook;
        try {
            sxssfWorkbook = new SXSSFWorkbook();
            CellStyle style = sxssfWorkbook.createCellStyle();
            Sheet sheet = sxssfWorkbook.createSheet(sheetName);
            // åˆ›å»ºåˆ—头
            sheet.createFreezePane(0, 1);
@@ -93,7 +138,7 @@
                    sheet.setColumnWidth(columnIndex, column.columnConfig.width() * 2 * 256);
                }
                // è®¾ç½®åˆ—头单元格
                configHeaderCell(sxssfWorkbook, cell, column.columnConfig,style);
                configHeaderCell(sxssfWorkbook, cell, column.columnConfig);
            }
            // åˆ›å»ºæ•°æ®è®°å½•
            for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
@@ -102,8 +147,10 @@
                    ColumnInfo column = columns.get(columnIndex);
                    Cell cell = row.createCell(columnIndex);
                    cell.setCellValue(getCellData(column, data.get(rowIndex)));
                    // è®¾ç½®æ•°æ®å•元格
                    configDataCell(sxssfWorkbook, cell, column.columnConfig,style);
                    configDataCell(sxssfWorkbook, cell, column.columnConfig);
                }
            }
            sxssfWorkbook.write(os);
@@ -140,26 +187,6 @@
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        }
    }
    /**
     * å¯¼å‡ºè‡³å“åº”流
     * @param data æ•°æ®
     * @param fileName Excel文件名
     * @param response HttpServletResponse对象
     */
    public void export (List<T> data, String fileName, HttpServletResponse response) {
        this.export(data, fileName, DEFAULT_SHEET_NAME, response);
    }
    /**
     * å¯¼å‡ºè‡³å“åº”流
     * @param data æ•°æ®
     * @param fileName Excel文件名
     * @param response HttpServletResponse对象
     */
    public void exportWithFirstAndEnd (List<T> data, String fileName,String first,String end, HttpServletResponse response) {
        this.exportWithFirstAndEnd(data, fileName, DEFAULT_SHEET_NAME, first,end,response);
    }
    /**
     * å¯¼å‡ºè‡³å“åº”流
     * @param data æ•°æ®
@@ -179,74 +206,48 @@
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        }
    }
    /**
     * å¯¼å‡ºåˆ°æŒ‡å®šè¾“出流
     * @param data æ•°æ®
     * @param sheetName Sheet名称
     */
    public void exportWithFirstAndEnd (List<T> data, String sheetName,String first,String end, OutputStream os) {
        SXSSFWorkbook sxssfWorkbook;
        try {
            sxssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = sxssfWorkbook.createSheet(sheetName);
            // åˆ›å»ºåˆ—头
            sheet.createFreezePane(0, 2);
            sheet.addMergedRegion(new CellRangeAddress(0   ,0,0,this.getColumns().size()-1));
            Row title = sheet.createRow(0);
            title.setHeight((short) 1000);
            Cell c = title.createCell(0);
            c.setCellValue(first);
            configFirstCell(sxssfWorkbook,c);
            Row header = sheet.createRow(1);
            header.setHeight((short)600);
            List<ColumnInfo> columns = this.getColumns();
            for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                ColumnInfo column = columns.get(columnIndex);
                Cell cell = header.createCell(columnIndex);
                cell.setCellValue(new HSSFRichTextString(column.columnConfig.name()));
                // åˆ—宽设置
                if (column.columnConfig.width() == -1) {
                    sheet.setColumnWidth(columnIndex, column.columnConfig.name().length() * 2 * 256);
                } else {
                    sheet.setColumnWidth(columnIndex, column.columnConfig.width() * 2 * 256);
                }
                // è®¾ç½®åˆ—头单元格
                configHeaderCell(sxssfWorkbook, cell, column.columnConfig);
            }
            // åˆ›å»ºæ•°æ®è®°å½•
            for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
                Row row = sheet.createRow(rowIndex + 2);
                for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                    ColumnInfo column = columns.get(columnIndex);
                    Cell cell = row.createCell(columnIndex);
                    cell.setCellValue(getCellData(column, data.get(rowIndex)));
                    // è®¾ç½®æ•°æ®å•元格
                    configDataCell(sxssfWorkbook, cell, column.columnConfig);
                }
            }
            if(StringUtils.isNotBlank(end)){
                sheet.addMergedRegion(new CellRangeAddress(data.size()+2   ,data.size()+2,0,this.getColumns().size()-1));
                Row endRow = sheet.createRow(data.size()+2);
//            endRow.setHeight((short) 600);
                Cell c1 = endRow.createCell(0);
                c1.setCellValue(end);
                configEndCell(sxssfWorkbook,c1);
            }
            sxssfWorkbook.write(os);
            os.close();
        } catch (Exception e) {
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    /**
     * å¯¼å‡ºè‡³å“åº”流
     * @param data æ•°æ®
     * @param fileName Excel文件名
     * @param response HttpServletResponse对象
     */
    public void export (List<T> data, String fileName, HttpServletResponse response) {
        this.export(data, fileName, DEFAULT_SHEET_NAME, response);
    }
    /**
     * å¯¼å‡ºè‡³å“åº”流
     * @param data æ•°æ®
     * @param fileName Excel文件名
     * @param response HttpServletResponse对象
     */
    public void exportWithFirstAndEnd (List<T> data, String fileName,String first,String end, HttpServletResponse response) {
        this.exportWithFirstAndEnd(data, fileName, DEFAULT_SHEET_NAME, first,end,response);
    }
    /**O
     * èŽ·å–åˆ—é›†åˆ
     */
    private List<ColumnInfo> getColumns () {
        Map<Integer, ColumnInfo> sortedFields = new TreeMap<>();
        Field[] fields = modelClass.getDeclaredFields();
        int index = 0;
        for (Field field : fields) {
            ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);
            if (excelColumn == null) {
                continue;
            }
            if (sortedFields.get(excelColumn.index()) != null) {
                throw new AnnotationConfigurationException("Excel column contains the same index.");
            }
            sortedFields.put(excelColumn.index() == -1 ? index : excelColumn.index(), new ColumnInfo(excelColumn, field));
            index++;
        }
        return new ArrayList<>(sortedFields.values());
    }
    /**
     * é…ç½®æ•°æ®å•元格
     */
@@ -272,6 +273,25 @@
        style.setWrapText(true);
        cell.setCellStyle(style);
    }
    /**
     * é…ç½®åˆ—头单元格
     */
    private void configHeaderCell (SXSSFWorkbook workbook, Cell cell, ExcelColumn columnConfig) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(columnConfig.align());
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // è®¾ç½®èƒŒæ™¯
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillForegroundColor(columnConfig.backgroundColor().getIndex());
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints(columnConfig.fontSize());
        style.setFont(font);
        // è®¾ç½®è¾¹æ¡†
        configCellBorder(style);
        cell.setCellStyle(style);
    }
    /**
     * é…ç½®åˆ—头单元格
     */
@@ -281,11 +301,10 @@
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // è®¾ç½®èƒŒæ™¯
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short)24);
        font.setBold(true);
        font.setFontHeightInPoints((short)18);
        style.setFont(font);
        // è®¾ç½®è¾¹æ¡†
        configCellBorder(style);
@@ -304,96 +323,6 @@
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short)14);
        style.setFont(font);
        // è®¾ç½®è¾¹æ¡†
        configCellBorder(style);
        cell.setCellStyle(style);
    }
    /**
     * é…ç½®åˆ—头单元格
     */
    private void configHeaderCell (SXSSFWorkbook workbook, Cell cell, ExcelColumn columnConfig) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(columnConfig.align());
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // è®¾ç½®èƒŒæ™¯
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//        style.setFillForegroundColor(columnConfig.backgroundColor().getIndex());
        style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short)11);
        font.setColor(columnConfig.color().index);
        font.setBold(true);
        style.setFont(font);
        // è®¾ç½®è¾¹æ¡†
        style.setWrapText(true);
        configCellBorder(style);
        cell.setCellStyle(style);
    }
    /**
     * èŽ·å–åˆ—é›†åˆ
     */
    private List<ColumnInfo> getColumns () {
        Map<Integer, ColumnInfo> sortedFields = new TreeMap<>();
        Field[] fields = modelClass.getDeclaredFields();
        int index = 0;
        for (Field field : fields) {
            ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);
            if (excelColumn == null) {
                continue;
            }
            if (sortedFields.get(excelColumn.index()) != null) {
                throw new AnnotationConfigurationException("Excel column contains the same index.");
            }
            sortedFields.put(excelColumn.index() == -1 ? index : excelColumn.index(), new ColumnInfo(excelColumn, field));
            index++;
        }
        return new ArrayList<>(sortedFields.values());
    }
    public static void main(String[] args) {
        ExcelExporter m = new ExcelExporter();
//        ExcelExporter.build(UserSalaryListVO.class).getColumns();
    }
    /**
     * é…ç½®æ•°æ®å•元格
     */
    private void configDataCell (SXSSFWorkbook workbook, Cell cell, ExcelColumn columnConfig, CellStyle style) {
     //   CellStyle style = workbook.createCellStyle();
        style.setAlignment(columnConfig.align());
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // è®¾ç½®èƒŒæ™¯
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillForegroundColor(columnConfig.dataBackgroundColor().getIndex());
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints(columnConfig.fontSize());
        // å­—体颜色
        font.setColor(columnConfig.color().getIndex());
        // ç²—体
        font.setBold(columnConfig.bold());
        // æ–œä½“
        font.setItalic(columnConfig.italic());
        style.setFont(font);
        // è¾¹æ¡†
        configCellBorder(style);
        cell.setCellStyle(style);
    }
    /**
     * é…ç½®åˆ—头单元格
     */
    private void configHeaderCell (SXSSFWorkbook workbook, Cell cell, ExcelColumn columnConfig,CellStyle style) {
       // CellStyle style = workbook.createCellStyle();
        style.setAlignment(columnConfig.align());
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // è®¾ç½®èƒŒæ™¯
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillForegroundColor(columnConfig.backgroundColor().getIndex());
        // å­—体
        Font font = workbook.createFont();
        font.setFontHeightInPoints(columnConfig.fontSize());
        style.setFont(font);
        // è®¾ç½®è¾¹æ¡†
        configCellBorder(style);
@@ -471,289 +400,5 @@
        private Field field;
    }
    public static <T> List<T> readExcel(String path, Class<T> cls, MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
            log.error("上传文件格式不正确");
        }
        List<T> dataList = new ArrayList<>();
        Workbook workbook = null;
        try {
            InputStream is = file.getInputStream();
            if (fileName.endsWith(EXCEL2007)) {
                workbook = new XSSFWorkbook(is);
            }
            if (fileName.endsWith(EXCEL2003)) {
                workbook = new HSSFWorkbook(is);
            }
            if (workbook != null) {
                //类映射  æ³¨è§£ value-->bean columns
                Map<String, List<Field>> classMap = new HashMap<>();
                List<Field> fields = Stream.of(cls.getDeclaredFields()).collect(Collectors.toList());
                fields.forEach(
                        field -> {
                            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                            if (annotation != null) {
                                String value = annotation.name();
                                if (StringUtils.isBlank(value)) {
                                    return;//return起到的作用和continue是相同的 è¯­æ³•
                                }
                                if (!classMap.containsKey(value)) {
                                    classMap.put(value, new ArrayList<>());
                                }
                                field.setAccessible(true);
                                classMap.get(value).add(field);
                            }
                        }
                );
                //索引-->columns
                Map<Integer, List<Field>> reflectionMap = new HashMap<>(16);
                //默认读取第一个sheet
                Sheet sheet = workbook.getSheetAt(0);
                boolean firstRow = true;
                for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
                    Row row = sheet.getRow(i);
                    //首行  æå–注解
                    if (firstRow) {
                        for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                            Cell cell = row.getCell(j);
                            String cellValue = getCellValue(cell);
                            if (classMap.containsKey(cellValue)) {
                                reflectionMap.put(j, classMap.get(cellValue));
                            }
                        }
                        firstRow = false;
                    } else {
                        //忽略空白行
                        if (row == null) {
                            continue;
                        }
                        try {
                            T t = cls.newInstance();
                            //判断是否为空白行
                            boolean allBlank = true;
                            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                                if (reflectionMap.containsKey(j)) {
                                    Cell cell = row.getCell(j);
                                    String cellValue = getCellValue(cell);
                                    if (StringUtils.isNotBlank(cellValue)) {
                                        allBlank = false;
                                    }
                                    List<Field> fieldList = reflectionMap.get(j);
                                    fieldList.forEach(
                                            x -> {
                                                try {
                                                    handleField(t, cellValue, x);
                                                } catch (Exception e) {
                                                    log.error(String.format("reflect field:%s value:%s exception!", x.getName(), cellValue), e);
                                                }
                                            }
                                    );
                                }
                            }
                            if (!allBlank) {
                                dataList.add(t);
                            } else {
                                log.warn(String.format("row:%s is blank ignore!", i));
                            }
                        } catch (Exception e) {
                            log.error(String.format("parse row:%s exception!", i), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(String.format("parse excel exception!"), e);
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception e) {
                    log.error(String.format("parse excel exception!"), e);
                }
            }
        }
        return dataList;
    }
    private static <T> void handleField(T t, String value, Field field) throws Exception {
        Class<?> type = field.getType();
        if (type == null || type == void.class || StringUtils.isBlank(value)) {
            return;
        }
        if (type == Object.class) {
            field.set(t, value);
            //数字类型
        } else if (type.getSuperclass() == null || type.getSuperclass() == Number.class) {
            if (type == int.class || type == Integer.class) {
                field.set(t, NumberUtils.toInt(value));
            } else if (type == long.class || type == Long.class) {
                field.set(t, NumberUtils.toLong(value));
            } else if (type == byte.class || type == Byte.class) {
                field.set(t, NumberUtils.toByte(value));
            } else if (type == short.class || type == Short.class) {
                field.set(t, NumberUtils.toShort(value));
            } else if (type == double.class || type == Double.class) {
                field.set(t, NumberUtils.toDouble(value));
            } else if (type == float.class || type == Float.class) {
                field.set(t, NumberUtils.toFloat(value));
            } else if (type == char.class || type == Character.class) {
                field.set(t, CharUtils.toChar(value));
            } else if (type == boolean.class) {
                field.set(t, BooleanUtils.toBoolean(value));
            } else if (type == BigDecimal.class) {
                field.set(t, new BigDecimal(value));
            }
        } else if (type == Boolean.class) {
            field.set(t, BooleanUtils.toBoolean(value));
        } else if (type == Date.class) {
            field.set(t, value);
        } else if (type == String.class) {
            field.set(t, value);
        } else {
            Constructor<?> constructor = type.getConstructor(String.class);
            field.set(t, constructor.newInstance(value));
        }
    }
    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }else{
            return StringUtils.trimToEmpty(cell.getStringCellValue());
        }
       /* if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
            } else {
                return new BigDecimal(cell.getNumericCellValue()).toString();
            }
        } else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
            return StringUtils.trimToEmpty(cell.getStringCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
            return StringUtils.trimToEmpty(cell.getCellFormula());
        } else if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
            return "";
        } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
            return "ERROR";
        } else {
            return cell.toString().trim();
        }*/
    }
  /*  public static <T> void writeExcel(HttpServletResponse response, List<T> dataList, Class<T> cls, String fileName) {
        Field[] fields = cls.getDeclaredFields();
        List<Field> fieldList = Arrays.stream(fields)
                .filter(field -> {
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null && annotation.col() > 0) {
                        field.setAccessible(true);
                        return true;
                    }
                    return false;
                }).sorted(Comparator.comparing(field -> {
                    int col = 0;
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null) {
                        col = annotation.col();
                    }
                    return col;
                })).collect(Collectors.toList());
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("Sheet1");
        AtomicInteger ai = new AtomicInteger();
        {
            Row row = sheet.createRow(ai.getAndIncrement());
            AtomicInteger aj = new AtomicInteger();
            //写入头部
            fieldList.forEach(field -> {
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                String columnName = "";
                if (annotation != null) {
                    columnName = annotation.value();
                }
                Cell cell = row.createCell(aj.getAndIncrement());
                CellStyle cellStyle = wb.createCellStyle();
                cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
                Font font = wb.createFont();
                cellStyle.setFont(font);
                cell.setCellStyle(cellStyle);
                cell.setCellValue(columnName);
            });
        }
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataList.forEach(t -> {
                Row row1 = sheet.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Class<?> type = field.getType();
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        if (type == Date.class) {
                            cell.setCellValue(value.toString());
                        } else {
                            cell.setCellValue(value.toString());
                        }
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        //冻结窗格
        wb.getSheet("Sheet1").createFreezePane(0, 1, 0, 1);
        //浏览器下载excel
        buildExcelDocument(fileName, wb, response);
    }*/
    /**
     * æµè§ˆå™¨ä¸‹è½½excel
     *
     * @param fileName
     * @param wb
     * @param response
     */
/*
    private static void buildExcelDocument(String fileName, Workbook wb, HttpServletResponse response) {
        try {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            response.flushBuffer();
            wb.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/
    /**
     * ç”Ÿæˆexcel文件
     *
     * @param path ç”Ÿæˆexcel路径
     * @param wb
     */
 /*   private static void buildExcelFile(String path, Workbook wb) {
        File file = new File(path);
        if (file.exists()) {
            file.delete();
        }
        try {
            wb.write(new FileOutputStream(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/
}
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelImporter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,394 @@
package com.doumee.core.annotation.excel;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
 * å¯¼å…¥Excel文件(支持“XLS”和“XLSX”格式)
 */
public class ExcelImporter {
    private static Logger log = LoggerFactory.getLogger(ExcelImporter.class);
    /**
     * å·¥ä½œè–„对象
     */
    private Workbook wb;
    /**
     * å·¥ä½œè¡¨å¯¹è±¡
     */
    private Sheet sheet;
    /**
     * æ ‡é¢˜è¡Œå·
     */
    private int headerNum;
    /**
     * æ ‡é¢˜è¡Œå·
     */
    private CellType changeType;
    /**
     * æž„造函数
     * @param--path å¯¼å…¥æ–‡ä»¶ï¼Œè¯»å–第一个工作表
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(String fileName, int headerNum)
        throws InvalidFormatException, IOException {
        this(new File(fileName), headerNum);
    }
    /**
     * æž„造函数
     * @param--path å¯¼å…¥æ–‡ä»¶å¯¹è±¡ï¼Œè¯»å–第一个工作表
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1   (eg: 1)
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(File file, int headerNum)
        throws InvalidFormatException, IOException {
        this(file, headerNum, 0);
    }
    /**
     * æž„造函数
     * @param--path å¯¼å…¥æ–‡ä»¶
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @param sheetIndex å·¥ä½œè¡¨ç¼–号
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(String fileName, int headerNum, int sheetIndex)
        throws InvalidFormatException, IOException {
        this(new File(fileName), headerNum, sheetIndex);
    }
    /**
     * æž„造函数
     * @param--path å¯¼å…¥æ–‡ä»¶å¯¹è±¡
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @param sheetIndex å·¥ä½œè¡¨ç¼–号
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(File file, int headerNum, int sheetIndex)
        throws InvalidFormatException, IOException {
        this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
    }
    /**
     * æž„造函数 (重要)
     * @param--file å¯¼å…¥æ–‡ä»¶å¯¹è±¡
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @param sheetIndex å·¥ä½œè¡¨ç¼–号
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(MultipartFile multipartFile, int headerNum, int sheetIndex)
        throws InvalidFormatException, IOException {
        this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
    }
    /**
     * æž„造函数 (重要)
     * @param--file å¯¼å…¥æ–‡ä»¶å¯¹è±¡
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @param sheetIndex å·¥ä½œè¡¨ç¼–号
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(MultipartFile multipartFile, int headerNum, int sheetIndex, CellType cellType)
        throws InvalidFormatException, IOException {
        this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex,cellType);
    }
    /**
     * æž„造函数 ï¼ˆï¼‰
     * @param--path å¯¼å…¥æ–‡ä»¶å¯¹è±¡
     * @param headerNum æ ‡é¢˜è¡Œå·ï¼Œæ•°æ®è¡Œå·=标题行号+1
     * @param sheetIndex å·¥ä½œè¡¨ç¼–号 (eg: 0)
     * @throws InvalidFormatException
     * @throws IOException
     */
    public ExcelImporter(String fileName, InputStream in, int headerNum, int sheetIndex)
        throws InvalidFormatException, IOException {
        if (StringUtils.isBlank(fileName)){
            throw new RuntimeException("导入文档为空!");
        }else if(fileName.toLowerCase().endsWith("xls")){
            this.wb = new HSSFWorkbook(in);
        }else if(fileName.toLowerCase().endsWith("xlsx")){
            this.wb = new XSSFWorkbook(in);
        }else{
            throw new RuntimeException("文档格式不正确!");
        }
        if (this.wb.getNumberOfSheets()<sheetIndex){
            throw new RuntimeException("文档中没有工作表!");
        }
        this.sheet = this.wb.getSheetAt(sheetIndex);
        this.headerNum = headerNum;
        log.debug("Initialize success.");
    }
    public ExcelImporter(String fileName, InputStream in, int headerNum, int sheetIndex,CellType cellType)
        throws InvalidFormatException, IOException {
        if (StringUtils.isBlank(fileName)){
            throw new RuntimeException("导入文档为空!");
        }else if(fileName.toLowerCase().endsWith("xls")){
            this.wb = new HSSFWorkbook(in);
        }else if(fileName.toLowerCase().endsWith("xlsx")){
            this.wb = new XSSFWorkbook(in);
        }else{
            throw new RuntimeException("文档格式不正确!");
        }
        if (this.wb.getNumberOfSheets()<sheetIndex){
            throw new RuntimeException("文档中没有工作表!");
        }
        this.sheet = this.wb.getSheetAt(sheetIndex);
        this.headerNum = headerNum;
        this.changeType = cellType;
        log.debug("Initialize success.");
    }
    /**
     * èŽ·å–è¡Œå¯¹è±¡
     * @param rownum
     * @return
     */
    public Row getRow(int rownum){
        return this.sheet.getRow(rownum);
    }
    /**
     * èŽ·å–æ•°æ®è¡Œå·
     * @return
     */
    public int getDataRowNum(){
        return headerNum+1;
    }
    /**
     * èŽ·å–æœ€åŽä¸€ä¸ªæ•°æ®è¡Œå·
     * @return
     */
    public int getLastDataRowNum(){
        return this.sheet.getLastRowNum()+headerNum;
    }
    /**
     * èŽ·å–æœ€åŽä¸€ä¸ªåˆ—å·
     * @return
     */
    public int getLastCellNum(){
        return this.getRow(headerNum).getLastCellNum();
    }
    /**
     * èŽ·å–å•å…ƒæ ¼å€¼
     * @param row èŽ·å–çš„è¡Œ
     * @param column èŽ·å–å•å…ƒæ ¼åˆ—å·
     * @return å•元格值
     */
    public Object getCellValue(Row row, int column){
        Object val = "";
        try{
            Cell cell = row.getCell(column);
            if (cell != null){
                if (cell.getCellType() == CellType.NUMERIC){
                    cell.setCellType(CellType.STRING); // ç¡®ä¿å•元格类型为字符串
                    val = cell.getStringCellValue();
                }else if (cell.getCellType() == CellType.STRING){
                    val = cell.getStringCellValue();
                }else if (cell.getCellType() == CellType.FORMULA){
                    val = cell.getCellFormula();
                }else if (cell.getCellType() == CellType.BOOLEAN){
                    val = cell.getBooleanCellValue();
                }else if (cell.getCellType() == CellType.ERROR){
                    val = cell.getErrorCellValue();
                }
            }
        }catch (Exception e) {
            return val;
        }
        return val;
    }
    /**
     * èŽ·å–å¯¼å…¥æ•°æ®åˆ—è¡¨
     * @param cls å¯¼å…¥å¯¹è±¡ç±»åž‹
     * @param groups å¯¼å…¥åˆ†ç»„  å¯ä¸ºç©º
     */
    public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
        List<Object[]> annotationList = new ArrayList<>();
        // Get annotation field
        Field[] fs = cls.getDeclaredFields();
        for (Field f : fs){
            ExcelColumn ef = f.getAnnotation(ExcelColumn.class);
            if (ef != null && (ef.type()==0 || ef.type()==2)){
                if (groups!=null && groups.length>0){
                    boolean inGroup = false;
                    for (int g : groups){
                        if (inGroup){
                            break;
                        }
                        for (int efg : ef.groups()){
                            if (g == efg){
                                inGroup = true;
                                annotationList.add(new Object[]{ef, f});
                                break;
                            }
                        }
                    }
                }else{
                    annotationList.add(new Object[]{ef, f});
                }
            }
        }
        // Get annotation method
        Method[] ms = cls.getDeclaredMethods();
        for (Method m : ms){
            ExcelColumn ef = m.getAnnotation(ExcelColumn.class);
            if (ef != null && (ef.type()==0 || ef.type()==2)){
                if (groups!=null && groups.length>0){
                    boolean inGroup = false;
                    for (int g : groups){
                        if (inGroup){
                            break;
                        }
                        for (int efg : ef.groups()){
                            if (g == efg){
                                inGroup = true;
                                annotationList.add(new Object[]{ef, m});
                                break;
                            }
                        }
                    }
                }else{
                    annotationList.add(new Object[]{ef, m});
                }
            }
        }
        // Field sorting
        Collections.sort(annotationList, (o1, o2) -> {
            int index1 =((ExcelColumn)o1[0]).index(), index2=((ExcelColumn)o2[0]).index();
            if(index1 == -1){
                index1  = annotationList.size()+99999;
            }
            if(index2 == -1){
                index2  = annotationList.size()+99999;
            }
            return new Integer(index1).compareTo(new Integer(index2));
        });
        //log.debug("Import column count:"+annotationList.size());
        // Get excel data
        List<E> dataList = new ArrayList<>();
        System.out.println("起始数据行:"+getDataRowNum());
        System.out.println("结束数据行:"+getLastDataRowNum());
        for (int i = this.getDataRowNum(); i <= this.getLastDataRowNum(); i++) {
            E e = (E)cls.newInstance();
            int column = 0;
            Row row = this.getRow(i);
            if (Objects.isNull(row)){
                continue;
            }
            StringBuilder sb = new StringBuilder();
            for (Object[] os : annotationList){
                Object val = this.getCellValue(row, column++);
                if (val != null){
                    ExcelColumn ef = (ExcelColumn)os[0];
                    // Get param type and type cast
                    Class<?> valType = Class.class;
                    if (os[1] instanceof Field){
                        valType = ((Field)os[1]).getType();
                    }else if(os[1] instanceof Method){
                        Method method = ((Method)os[1]);
                        if ("get".equals(method.getName().substring(0, 3))){
                            valType = method.getReturnType();
                        }else if("set".equals(method.getName().substring(0, 3))){
                            valType = ((Method)os[1]).getParameterTypes()[0];
                        }
                    }
                    //log.debug("Import value type: ["+i+","+column+"] " + valType);
                    try {
                        if (valType == String.class){
                            String s = String.valueOf(val.toString());
                            if(StringUtils.endsWith(s, ".0")){
                                val = StringUtils.substringBefore(s, ".0");
                            }else{
                                val = String.valueOf(val.toString()).trim();
                            }
                        }
                        else if (valType == Integer.class){
                            val = Double.valueOf(val.toString()).intValue();
                        }else if (valType == Long.class){
                            val = Double.valueOf(val.toString()).longValue();
                        }else if (valType == Double.class){
                            val = Double.valueOf(val.toString());
                        }else if (valType == Float.class){
                            val = Float.valueOf(val.toString());
                        }else if (valType == Date.class){
                            val = DateUtil.getJavaDate((Double)val);
                        }else{
                            if (ef.fieldType() != Class.class){
                                val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
                            }else{
                                val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
                                    "fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
                            }
                        }
                    } catch (Exception ex) {
                        log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
                        val = null;
                    }
                    // set entity value
                    if (os[1] instanceof Field){
                        Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
                    }else if (os[1] instanceof Method){
                        String mthodName = ((Method)os[1]).getName();
                        if ("get".equals(mthodName.substring(0, 3))){
                            mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
                        }
                        Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
                    }
                }
                sb.append(val+", ");
            }
            dataList.add(e);
            log.debug("Read success: ["+i+"] "+sb.toString());
        }
        return dataList;
    }
    /**
     *  å…³é—­æµ æ¸…理临时文件
     */
    public void dispose(){
        try {
            if(wb!=null){
                wb.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
server/services/src/main/java/com/doumee/core/annotation/excel/ExportExcelUtils.java
ÎļþÒÑɾ³ý
server/services/src/main/java/com/doumee/core/annotation/excel/Reflections.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,294 @@
package com.doumee.core.annotation.excel;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import java.lang.reflect.*;
/**
 * åå°„工具类.
 * æä¾›è°ƒç”¨getter/setter方法, è®¿é—®ç§æœ‰å˜é‡, è°ƒç”¨ç§æœ‰æ–¹æ³•, èŽ·å–æ³›åž‹ç±»åž‹Class, è¢«AOP过的真实类等工具函数.
 */
@SuppressWarnings("rawtypes")
public class Reflections {
    private static final String SETTER_PREFIX = "set";
    private static final String GETTER_PREFIX = "get";
    private static final String CGLIB_CLASS_SEPARATOR = "$$";
    private static Logger logger = LoggerFactory.getLogger(Reflections.class);
    /**
     * è°ƒç”¨Getter方法.
     * æ”¯æŒå¤šçº§ï¼Œå¦‚:对象名.对象名.方法
     */
    public static Object invokeGetter(Object obj, String propertyName) {
        Object object = obj;
        for (String name : StringUtils.split(propertyName, ".")){
            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
        }
        return object;
    }
    /**
     * è°ƒç”¨Setter方法, ä»…匹配方法名。
     * æ”¯æŒå¤šçº§ï¼Œå¦‚:对象名.对象名.方法
     */
    public static void invokeSetter(Object obj, String propertyName, Object value) {
        Object object = obj;
        String[] names = StringUtils.split(propertyName, ".");
        for (int i=0; i<names.length; i++){
            if(i<names.length-1){
                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
            }else{
                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
                invokeMethodByName(object, setterMethodName, new Object[] { value });
            }
        }
    }
    /**
     * ç›´æŽ¥è¯»å–对象属性值, æ— è§†private/protected修饰符, ä¸ç»è¿‡getter函数.
     */
    public static Object getFieldValue(final Object obj, final String fieldName) {
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
        }
        Object result = null;
        try {
            result = field.get(obj);
        } catch (IllegalAccessException e) {
            logger.error("非法访问的异常{}", e.getMessage());
        }
        return result;
    }
    /**
     * ç›´æŽ¥è®¾ç½®å¯¹è±¡å±žæ€§å€¼, æ— è§†private/protected修饰符, ä¸ç»è¿‡setter函数.
     */
    public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
        }
        try {
            field.set(obj, value);
        } catch (IllegalAccessException e) {
            logger.error("非法访问的异常:{}", e.getMessage());
        }
    }
    /**
     * ç›´æŽ¥è°ƒç”¨å¯¹è±¡æ–¹æ³•, æ— è§†private/protected修饰符.
     * ç”¨äºŽä¸€æ¬¡æ€§è°ƒç”¨çš„æƒ…况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
     * åŒæ—¶åŒ¹é…æ–¹æ³•名+参数类型,
     */
    public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
        final Object[] args) {
        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
        if (method == null) {
            throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
        }
        try {
            return method.invoke(obj, args);
        } catch (Exception e) {
            throw convertReflectionExceptionToUnchecked(e);
        }
    }
    /**
     * ç›´æŽ¥è°ƒç”¨å¯¹è±¡æ–¹æ³•, æ— è§†private/protected修饰符,
     * ç”¨äºŽä¸€æ¬¡æ€§è°ƒç”¨çš„æƒ…况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
     * åªåŒ¹é…å‡½æ•°åï¼Œå¦‚果有多个同名函数调用第一个。
     */
    public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
        Method method = getAccessibleMethodByName(obj, methodName);
        if (method == null) {
            throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
        }
        try {
            return method.invoke(obj, args);
        } catch (Exception e) {
            throw convertReflectionExceptionToUnchecked(e);
        }
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredField, å¹¶å¼ºåˆ¶è®¾ç½®ä¸ºå¯è®¿é—®.
     *
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     */
    public static Field getAccessibleField(final Object obj, final String fieldName) {
        Validate.notNull(obj, "object can't be null");
        Validate.notBlank(fieldName, "fieldName can't be blank");
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                Field field = superClass.getDeclaredField(fieldName);
                makeAccessible(field);
                return field;
            } catch (NoSuchFieldException e) {//NOSONAR
                // Field不在当前类定义,继续向上转型
                continue;// new add
            }
        }
        return null;
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredMethod,并强制设置为可访问.
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     * åŒ¹é…å‡½æ•°å+参数类型。
     *
     * ç”¨äºŽæ–¹æ³•需要被多次调用的情况. å…ˆä½¿ç”¨æœ¬å‡½æ•°å…ˆå–å¾—Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethod(final Object obj, final String methodName,
        final Class<?>... parameterTypes) {
        Validate.notNull(obj, "object can't be null");
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
                makeAccessible(method);
                return method;
            } catch (NoSuchMethodException e) {
                // Method不在当前类定义,继续向上转型
                continue;// new add
            }
        }
        return null;
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredMethod,并强制设置为可访问.
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     * åªåŒ¹é…å‡½æ•°åã€‚
     *
     * ç”¨äºŽæ–¹æ³•需要被多次调用的情况. å…ˆä½¿ç”¨æœ¬å‡½æ•°å…ˆå–å¾—Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
        Validate.notNull(obj, "object can't be null");
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
            Method[] methods = searchType.getDeclaredMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    makeAccessible(method);
                    return method;
                }
            }
        }
        return null;
    }
    /**
     * æ”¹å˜private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Method method) {
        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
            && !method.isAccessible()) {
            method.setAccessible(true);
        }
    }
    /**
     * æ”¹å˜private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Field field) {
        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
            .isFinal(field.getModifiers())) && !field.isAccessible()) {
            field.setAccessible(true);
        }
    }
    /**
     * é€šè¿‡åå°„, èŽ·å¾—Class定义中声明的泛型参数的类型, æ³¨æ„æ³›åž‹å¿…须定义在父类处
     * å¦‚无法找到, è¿”回Object.class.
     * eg.
     * public UserDao extends HibernateDao<User>
     *
     * @param clazz The class to introspect
     * @return the first generic declaration, or Object.class if cannot be determined
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getClassGenricType(final Class clazz) {
        return getClassGenricType(clazz, 0);
    }
    /**
     * é€šè¿‡åå°„, èŽ·å¾—Class定义中声明的父类的泛型参数的类型.
     * å¦‚无法找到, è¿”回Object.class.
     *
     * å¦‚public UserDao extends HibernateDao<User,Long>
     *
     * @param clazz clazz The class to introspect
     * @param index the Index of the generic ddeclaration,start from 0.
     * @return the index generic declaration, or Object.class if cannot be determined
     */
    public static Class getClassGenricType(final Class clazz, final int index) {
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0) {
            logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }
        return (Class) params[index];
    }
    public static Class<?> getUserClass(Object instance) {
        Assert.notNull(instance, "Instance must not be null");
        Class clazz = instance.getClass();
        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !Object.class.equals(superClass)) {
                return superClass;
            }
        }
        return clazz;
    }
    /**
     * å°†åå°„æ—¶çš„checked exception转换为unchecked exception.
     */
    public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
            || e instanceof NoSuchMethodException) {
            return new IllegalArgumentException(e);
        } else if (e instanceof InvocationTargetException) {
            return new RuntimeException(((InvocationTargetException) e).getTargetException());
        } else if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        }
        return new RuntimeException("Unexpected Checked Exception.", e);
    }
}
server/services/src/main/java/com/doumee/core/constants/Constants.java
@@ -51,6 +51,7 @@
    public static final String PAUSE_BIKE_TYPE ="PAUSE_BIKE_TYPE" ;
    public static final String HEART_TIME_EXPIRE_TIME ="HEART_TIME_EXPIRE_TIME" ;
    public static final String PARK_LAT_LNG_LIST = "PARK_LAT_LNG_LIST";
    public static final String LOW_BIKE_VOLTAGE ="LOW_BIKE_VOLTAGE" ;
    public static String REDIS_DEBUG_STR="test_";
    public static final String AD = "AD";
    public static String REPAIR = "REPAIR";
@@ -176,6 +177,7 @@
}
        public interface RedisKeys {
            public static final String submission_period_key = "sp_";
            public static final String import_bikes = "import_bikes";
        }
        public static final String ACCESS_ID = "ACCESS_ID";
server/services/src/main/java/com/doumee/core/wx/WxMiniUtilService.java
@@ -254,12 +254,12 @@
     * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html
     * @return
     */
    public void generateWXMiniCode(Locks locks,SystemDictData systemDictData,String prePath,String path){
    public void generateWXMiniCode(Locks locks,String token,String prePath,String path){
        if(Objects.isNull(systemDictData)){
        if(Objects.isNull(token)){
            return;
        }
         String url =  "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+ systemDictData.getCode();
         String url =  "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+ token;
        String release =   systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME,Constants.MINI_PROGRAMME_REALEASE).getCode();
        //生成图片上传OSS
        Map<String,Object> body = new HashMap<>();
server/services/src/main/java/com/doumee/dao/business/model/Bikes.java
@@ -126,6 +126,9 @@
    @ApiModelProperty(value = "最近定位地址")
    @ExcelColumn(name="最近定位地址")
    private String location;
    @ApiModelProperty(value = "是否低电量 0否 1是")
    @TableField(exist = false )
    private Integer lowVoltage;
}
server/services/src/main/java/com/doumee/dao/business/vo/BikesImportVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.doumee.dao.business.vo;
import com.doumee.core.annotation.excel.ExcelColumn;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import java.math.BigDecimal;
import java.util.Date;
/**
 * è®¢å•信息表
 * @author æ±Ÿè¹„蹄
 * @date 2023/09/27 18:06
 */
@Data
@ApiModel("电车导入模版")
public class BikesImportVO {
    @ExcelColumn(name="车辆类型",value = "paramName",index = 1)
    private String paramName;
    @ExcelColumn(name="车牌号",value = "code",index = 2)
    private String code;
    @ExcelColumn(name="控制器编码",value = "sn",index = 3)
    private String sn;
}
server/services/src/main/java/com/doumee/service/business/BikesService.java
@@ -3,6 +3,8 @@
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Bikes;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
@@ -86,7 +88,7 @@
     * @return PageData<Bikes>
     */
    PageData<Bikes> findPage(PageWrap<Bikes> pageWrap);
     String importBatch(MultipartFile file);
    /**
     * æ¡ä»¶ç»Ÿè®¡
     *
server/services/src/main/java/com/doumee/service/business/impl/BaseParamServiceImpl.java
@@ -51,7 +51,7 @@
                .eq(BaseParam::getIsdeleted,Constants.ZERO)
                .eq(BaseParam::getName,baseParam.getName());
        Integer count = baseParamMapper.selectCount(wrapper);
        long count = baseParamMapper.selectCount(wrapper);
        if (count > 0){
            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(),"车辆问题已存在");
        }
server/services/src/main/java/com/doumee/service/business/impl/BikesServiceImpl.java
@@ -1,6 +1,7 @@
package com.doumee.service.business.impl;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.annotation.excel.ExcelImporter;
import com.doumee.core.constants.Constants;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
@@ -13,6 +14,7 @@
import com.doumee.dao.business.BikesMapper;
import com.doumee.dao.business.join.BikesJoinMapper;
import com.doumee.dao.business.model.*;
import com.doumee.dao.business.vo.BikesImportVO;
import com.doumee.dao.business.web.response.BikeLogDTO;
import com.doumee.dao.business.web.response.MemberRidesDTO;
import com.doumee.dao.business.web.response.MiniProgrammeDTO;
@@ -27,10 +29,14 @@
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
import java.util.stream.Collectors;
@@ -43,6 +49,9 @@
@Service
public class BikesServiceImpl implements BikesService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private BikesMapper bikesMapper;
    @Autowired
@@ -70,7 +79,7 @@
                .eq(Bikes::getCode,bikes.getCode())
                .eq(Bikes::getIsdeleted,Constants.ZERO)
                .eq(Bikes::getType,Constants.ONE);
        Integer count = bikesMapper.selectCount(wrapper);
        Long count = bikesMapper.selectCount(wrapper);
        if (count > 0){
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"车牌号号已存在");
        }
@@ -114,7 +123,7 @@
                .eq(Bikes::getIsdeleted,Constants.ZERO)
                .ne(Bikes::getId,bikes.getId())
                .eq(Bikes::getType,Constants.ONE);
        Integer count = bikesMapper.selectCount(wrapper);
        long count = bikesMapper.selectCount(wrapper);
        if (count > 0){
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"车牌号号已存在");
        }
@@ -185,7 +194,7 @@
        QueryWrapper<SystemDictData> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(SystemDictData::getLabel, Arrays.asList(Constants.FORCE_BACK_SITE,Constants.FORCE_BACK_LOCK));
                .in(SystemDictData::getLabel, Arrays.asList(Constants.FORCE_BACK_SITE,Constants.FORCE_BACK_LOCK,Constants.LOW_BIKE_VOLTAGE));
        List<SystemDictData> systemDictData = systemDictDataMapper.selectList(wrapper);
        Map<String, SystemDictData> collect = systemDictData.stream().collect(Collectors.toMap(s -> s.getLabel(), s -> s));
@@ -197,7 +206,10 @@
                .leftJoin(Sites.class,Sites::getId,Bikes::getSiteId)
                .like(StringUtils.isNotBlank(pageWrap.getModel().getSiteId()),Bikes::getSiteId,pageWrap.getModel().getSiteId())
                .like(StringUtils.isNotBlank(pageWrap.getModel().getSiteName()), Sites::getName,pageWrap.getModel().getSiteName())
                .like(StringUtils.isNotBlank(pageWrap.getModel().getCode()), Bikes::getCode,pageWrap.getModel().getCode())
                .like(StringUtils.isNotBlank(pageWrap.getModel().getDeviceSn()), Bikes::getDeviceSn,pageWrap.getModel().getDeviceSn())
                .eq( pageWrap.getModel().getLockId() !=null,Bikes::getLockId,pageWrap.getModel().getLockId())
                .eq(  Bikes::getType,Constants.formatIntegerNum(pageWrap.getModel().getType()))//默认查询自行车
                .ne(Bikes::getLockId,Constants.formatIntegerFromStr(collect.get(Constants.FORCE_BACK_LOCK).getCode()))
                .ne(Bikes::getSiteId,collect.get(Constants.FORCE_BACK_SITE).getCode())
                .and(Constants.formatIntegerNum(pageWrap.getModel().getHasBike()) == Constants.ONE,
@@ -206,6 +218,20 @@
                .and(Constants.formatIntegerNum(pageWrap.getModel().getHasBike()) == Constants.TWO,s->s
                .isNotNull(Bikes::getCode)
                .and(b->b.ne(Bikes::getCode,"")));
        if(pageWrap.getModel().getLowVoltage()!=null){
            double low = 0;
            try {
                low = Double.parseDouble(collect.get(Constants.LOW_BIKE_VOLTAGE).getCode());
            }catch (Exception e){
            }
            if(pageWrap.getModel().getType() == Constants.ONE){
                //低电量
                queryWrapper.lt(Bikes::getVoltage,low);
            }else{
                //正常电量
                queryWrapper.ge(Bikes::getVoltage,low);
            }
        }
        queryWrapper.selectAll(Bikes.class)
                .selectAs(BaseParam::getName,Bikes::getParamName)
                .selectAs(Sites::getName,Bikes::getSiteName) ;
@@ -280,4 +306,110 @@
        QueryWrapper<Bikes> wrapper = new QueryWrapper<>(bikes);
        return bikesMapper.selectCount(wrapper);
    }
    @Override
    @Transactional(rollbackFor = {BusinessException.class,Exception.class})
    public String importBatch(MultipartFile file){
        Boolean importing = (Boolean) redisTemplate.opsForValue().get(Constants.RedisKeys.import_bikes);
        if(importing!=null && importing){
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,已存在导入任务正在执行中,请稍后再试!");
        }
        LoginUserInfo user =(LoginUserInfo) SecurityUtils.getSubject().getPrincipal();
        redisTemplate.opsForValue().set(Constants.RedisKeys.import_bikes,true);
        try {
            ExcelImporter ie = null;
            List<BikesImportVO> dataList =null;
            try {
                ie = new ExcelImporter(file,1,0, CellType.STRING); // ç¡®ä¿å•元格类型为字符串
                dataList = ie.getDataList(BikesImportVO.class,null);
            }  catch (Exception e) {
                e.printStackTrace();
            }
            if(dataList == null || dataList.size() ==0){
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,录入数据为空!");
            }
            List<Bikes> list =  bikesJoinMapper.selectJoinList(Bikes.class,new MPJLambdaWrapper<Bikes>()
                    .selectAll(Bikes.class)
                    .eq(Member::getIsdeleted,Constants.ZERO)
            );
            List<BaseParam> params =  baseParamMapper.selectList(new QueryWrapper<BaseParam>().lambda()
                    .eq(BaseParam::getIsdeleted,Constants.ZERO)
                    .eq(BaseParam::getType,Constants.FOUR)
            );
            List<Bikes> newList = new ArrayList<>();
            Date date = new Date();
            for(int i=0;i<dataList.size();i++){
                BikesImportVO model = dataList.get(i);
                if(StringUtils.isBlank(model.getSn())
                        &&StringUtils.isBlank(model.getCode())
                        &&StringUtils.isBlank(model.getParamName())){
                    continue;
                }
                Bikes bike = checkModelParam(model,newList,i,list,params,user.getId(),date);
                newList.add(bike);
            }
            if(newList == null || newList.size() ==0){
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,录入有效数据为空!");
            }
            bikesMapper.insert(newList);
            return "导入成功";
        }catch (BusinessException e){
            throw e;
        }catch (Exception e){
            throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"员工信息导入失败,请稍后重试");
        }finally {
            redisTemplate.delete(Constants.RedisKeys.import_bikes);
        }
    }
    private Bikes checkModelParam(BikesImportVO model, List<Bikes> newList, int index, List<Bikes> list, List<BaseParam> params,String userId,Date date) {
        Bikes bike = new Bikes();
        if(StringUtils.isBlank(model.getParamName())
                ||StringUtils.isBlank(model.getCode())
                ||StringUtils.isBlank(model.getSn())){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行人员信息不完整,请检查表格内容!");
        }
        if(params ==null){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,电车类型未配置,请联系系统技术人员处理!");
        }
        for(BaseParam p: params){
            if(StringUtils.equals(model.getParamName(),p.getName())){
                bike.setParamId(p.getId());
            }
        }
        if(bike.getParamId() ==null){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行车辆类型【"+model.getParamName()+"】不存在,请检查表格内容!");
        }
        if(list!=null){
            for(Bikes bikes: list){
                if(StringUtils.equals(model.getCode(),bikes.getCode())){
                    throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行车牌号【"+model.getCode()+"】已存在,请检查表格内容!");
                }
                if(StringUtils.equals(model.getSn(),bikes.getDeviceSn())){
                    throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行控制器sn【"+model.getSn()+"】已存在,请检查表格内容!");
                }
            }
        }
        for(Bikes bikes: newList){
            if(StringUtils.equals(model.getCode(),bikes.getCode())){
                throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行车牌号【"+model.getCode()+"】重复出现,请检查表格内容!");
            }
            if(StringUtils.equals(model.getSn(),bikes.getDeviceSn())){
                throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+(index+3)+"行控制器sn【"+model.getSn()+"】重复出现,请检查表格内容!");
            }
        }
        bike.setCode(model.getCode());
        bike.setDeviceSn(model.getSn());
        bike.setId(UUID.randomUUID().toString());
        bike.setCreateDate(new Date());
        bike.setCreator(userId);
        bike.setEditDate(date);
        bike.setEditor(userId);
        bike.setStatus(Constants.ZERO);
        bike.setIsdeleted(Constants.ZERO);
        bike.setType(Constants.ONE);//只能新增电车数据
        return  bike;
    }
}
server/services/src/main/java/com/doumee/service/business/impl/DeviceSubscribeServiceImpl.java
@@ -64,7 +64,7 @@
        MqttLog mqttLog = new MqttLog();
        mqttLog.setMsgId(msgId);
        mqttLog.setTopic(topic);
        int msgCount  =mqttLogMapper.selectCount(new QueryWrapper<MqttLog>().lambda().eq(MqttLog::getMsg, param).eq(MqttLog::getType, Constants.ZERO));
        long msgCount  =mqttLogMapper.selectCount(new QueryWrapper<MqttLog>().lambda().eq(MqttLog::getMsg, param).eq(MqttLog::getType, Constants.ZERO));
        if(msgCount>0){
            log.error("mqtt消息订阅==============已消费数据====="+param);
            return;
server/services/src/main/java/com/doumee/service/business/impl/LocksServiceImpl.java
@@ -2,6 +2,7 @@
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.core.model.LoginUserInfo;
import com.doumee.core.wx.WxMiniConfig;
import com.google.common.collect.Lists;
import com.doumee.biz.system.SystemDictDataBiz;
@@ -140,7 +141,10 @@
            // æ£€æŸ¥æ˜¯å¦æœ‰å›¾ç‰‡ä¿¡æ¯æ²¡æœ‰æ›´æ–°ä¿å­˜å›¾ç‰‡
            locksList.forEach(s-> {
                if (StringUtils.isBlank(s.getInfo())){
                    wxMiniUtilService.generateWXMiniCode(s,systemDictData,prePath,code);
                    try {
                        wxMiniUtilService.generateWXMiniCode(s, WxMiniConfig.wxMaService.getAccessToken(),prePath,code);
                    }catch (Exception e){
                    }
                    s.setEditor(loginUserInfo.getId());
                    s.setEditDate(new Date());
                    updateById(s);
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -71,7 +71,7 @@
                .eq(Member::getIsdeleted,Constants.ZERO)
                .eq(Member::getType,Constants.ONE)
                .eq(Member::getCardNo,member.getCardNo());
        Integer integer = memberMapper.selectCount(wrapper);
        long integer = memberMapper.selectCount(wrapper);
        if (integer > 0){
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"卡号存在重复");
server/services/src/main/java/com/doumee/service/business/impl/PricingParamServiceImpl.java
@@ -133,7 +133,7 @@
            wrapper.lambda()
                    .eq(PricingParam::getIsdeleted,Constants.ZERO)
                    .eq(PricingParam::getStatus,Constants.ZERO);
            Integer integer = pricingParamMapper.selectCount(wrapper);
            long integer = pricingParamMapper.selectCount(wrapper);
            if (integer <= 1 ){
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"该定价方案必须配置");
            }
server/services/src/main/java/com/doumee/service/business/impl/SitesServiceImpl.java
@@ -68,7 +68,7 @@
        wrapper.lambda()
                .eq(Sites::getCode,sites.getCode())
                .eq(Sites::getIsdeleted,Constants.ZERO);
        Integer count = sitesMapper.selectCount(wrapper);
        Long count = sitesMapper.selectCount(wrapper);
        if (count > 0){
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"站点编号已存在");
        }
@@ -244,6 +244,9 @@
        if (pageWrap.getModel().getClientVersion() != null) {
            queryWrapper.lambda().eq(Sites::getClientVersion, pageWrap.getModel().getClientVersion());
        }
        if (pageWrap.getModel().getType() != null) {
            queryWrapper.lambda().eq(Sites::getType, pageWrap.getModel().getType());
        }
         /*for(PageWrap.SortData sortData: pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
server/web/src/main/java/com/doumee/api/web/AccountApi.java
@@ -7,6 +7,7 @@
import com.doumee.core.annotation.trace.Trace;
import com.doumee.core.constants.Constants;
import com.doumee.core.model.ApiResponse;
import com.doumee.core.wx.WxMiniConfig;
import com.doumee.core.wx.WxMiniUtilService;
import com.doumee.dao.business.model.Locks;
import com.doumee.dao.business.web.request.RegisterRequest;
@@ -20,6 +21,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -109,12 +111,12 @@
    @ApiOperation(value = "测试生成二维码", notes = "小程序端")
    @GetMapping("/generateWXMiniCode")
    public ApiResponse<Locks> generateWXMiniCode() {
    public ApiResponse<Locks> generateWXMiniCode() throws WxErrorException {
        Locks locks = new Locks();
        locks.setCode(12);
        locks.setSiteId("1005");
        SystemDictData systemDictData = systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME,Constants.ACCESS_TOKEN);
        wxMiniUtilService.generateWXMiniCode(locks,systemDictData,"/usr/local/static_resources/bike/bike_file/","");
        wxMiniUtilService.generateWXMiniCode(locks, WxMiniConfig.wxMaService.getAccessToken(),"/usr/local/static_resources/bike/bike_file/","");
        return  ApiResponse.success("操作成功",locks);
    }