Kaynağa Gözat

feat(charging): 集成并同步第三方充电站数据到本地数据库

- 新增充电站、设备、接口的实体类及对应MyBatis Plus Mapper接口
- 实现ThirdPartyStationDataService,支持批量保存充电站信息及其设备、接口
- 在ChargingBusinessServiceImpl中调用ThirdPartyStationDataService存储第三方充电站数据
- 新增ChargingJob定时任务,每半小时从第三方接口同步充电站信息并存库
- 添加ChargeOrderInfoMapper XML映射文件,支持充电订单详细信息查询并关联用户、设备、充电站数据
SheepHy 4 gün önce
ebeveyn
işleme
223285de53

+ 96 - 0
src/main/java/com/zsElectric/boot/charging/entity/ThirdPartyConnectorInfo.java

@@ -0,0 +1,96 @@
+package com.zsElectric.boot.charging.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.zsElectric.boot.common.base.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 第三方充电接口信息实体
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@TableName("third_party_connector_info")
+@Getter
+@Setter
+public class ThirdPartyConnectorInfo extends BaseEntity {
+
+    /**
+     * 接口编码
+     */
+    private String connectorId;
+
+    /**
+     * 所属设备编码
+     */
+    private String equipmentId;
+
+    /**
+     * 所属充电站ID
+     */
+    private String stationId;
+
+    /**
+     * 接口名称
+     */
+    private String connectorName;
+
+    /**
+     * 接口类型
+     */
+    private Integer connectorType;
+
+    /**
+     * 额定电压上限(V)
+     */
+    private Integer voltageUpperLimits;
+
+    /**
+     * 额定电压下限(V)
+     */
+    private Integer voltageLowerLimits;
+
+    /**
+     * 额定电流(A)
+     */
+    private Integer current;
+
+    /**
+     * 额定功率(kW)
+     */
+    private BigDecimal power;
+
+    /**
+     * 车位号
+     */
+    private String parkNo;
+
+    /**
+     * 国家标准
+     */
+    private Integer nationalStandard;
+
+    /**
+     * 创建人ID
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createBy;
+
+    /**
+     * 更新人ID
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateBy;
+
+    /**
+     * 逻辑删除标识
+     */
+    @TableLogic
+    private Integer isDeleted;
+}

+ 96 - 0
src/main/java/com/zsElectric/boot/charging/entity/ThirdPartyEquipmentInfo.java

@@ -0,0 +1,96 @@
+package com.zsElectric.boot.charging.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.zsElectric.boot.common.base.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 第三方充电设备信息实体
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@TableName("third_party_equipment_info")
+@Getter
+@Setter
+public class ThirdPartyEquipmentInfo extends BaseEntity {
+
+    /**
+     * 设备编码
+     */
+    private String equipmentId;
+
+    /**
+     * 所属充电站ID
+     */
+    private String stationId;
+
+    /**
+     * 生产商ID
+     */
+    private String manufacturerId;
+
+    /**
+     * 生产商名称
+     */
+    private String manufacturerName;
+
+    /**
+     * 设备型号
+     */
+    private String equipmentModel;
+
+    /**
+     * 生产日期
+     */
+    private String productionDate;
+
+    /**
+     * 设备类型
+     */
+    private Integer equipmentType;
+
+    /**
+     * 设备经度
+     */
+    private BigDecimal equipmentLng;
+
+    /**
+     * 设备纬度
+     */
+    private BigDecimal equipmentLat;
+
+    /**
+     * 总功率(kW)
+     */
+    private BigDecimal power;
+
+    /**
+     * 设备名称
+     */
+    private String equipmentName;
+
+    /**
+     * 创建人ID
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createBy;
+
+    /**
+     * 更新人ID
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateBy;
+
+    /**
+     * 逻辑删除标识
+     */
+    @TableLogic
+    private Integer isDeleted;
+}

+ 161 - 0
src/main/java/com/zsElectric/boot/charging/entity/ThirdPartyStationInfo.java

@@ -0,0 +1,161 @@
+package com.zsElectric.boot.charging.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zsElectric.boot.common.base.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 第三方充电站信息实体
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@TableName("third_party_station_info")
+@Getter
+@Setter
+public class ThirdPartyStationInfo extends BaseEntity {
+
+    /**
+     * 充电站ID
+     */
+    private String stationId;
+
+    /**
+     * 运营商ID
+     */
+    private String operatorId;
+
+    /**
+     * 设备所属方ID
+     */
+    private String equipmentOwnerId;
+
+    /**
+     * 充电站名称
+     */
+    private String stationName;
+
+    /**
+     * 国家代码
+     */
+    private String countryCode;
+
+    /**
+     * 省市辖区编码
+     */
+    private String areaCode;
+
+    /**
+     * 详细地址
+     */
+    private String address;
+
+    /**
+     * 站点电话
+     */
+    private String stationTel;
+
+    /**
+     * 服务电话
+     */
+    private String serviceTel;
+
+    /**
+     * 站点类型
+     */
+    private Integer stationType;
+
+    /**
+     * 站点状态
+     */
+    private Integer stationStatus;
+
+    /**
+     * 车位数量
+     */
+    private Integer parkNums;
+
+    /**
+     * 经度
+     */
+    private BigDecimal stationLng;
+
+    /**
+     * 纬度
+     */
+    private BigDecimal stationLat;
+
+    /**
+     * 站点引导
+     */
+    private String siteGuide;
+
+    /**
+     * 建设场所
+     */
+    private Integer construction;
+
+    /**
+     * 站点照片(JSON数组)
+     */
+    private String pictures;
+
+    /**
+     * 营业时间
+     */
+    private String busineHours;
+
+    /**
+     * 电费
+     */
+    private BigDecimal electricityFee;
+
+    /**
+     * 服务费
+     */
+    private BigDecimal serviceFee;
+
+    /**
+     * 停车费
+     */
+    private String parkFee;
+
+    /**
+     * 支付方式
+     */
+    private String payment;
+
+    /**
+     * 是否支持预约
+     */
+    private Integer supportOrder;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建人ID
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createBy;
+
+    /**
+     * 更新人ID
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateBy;
+
+    /**
+     * 逻辑删除标识
+     */
+    @TableLogic
+    private Integer isDeleted;
+}

+ 15 - 0
src/main/java/com/zsElectric/boot/charging/mapper/ThirdPartyConnectorInfoMapper.java

@@ -0,0 +1,15 @@
+package com.zsElectric.boot.charging.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 第三方充电接口信息Mapper接口
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@Mapper
+public interface ThirdPartyConnectorInfoMapper extends BaseMapper<ThirdPartyConnectorInfo> {
+}

+ 15 - 0
src/main/java/com/zsElectric/boot/charging/mapper/ThirdPartyEquipmentInfoMapper.java

@@ -0,0 +1,15 @@
+package com.zsElectric.boot.charging.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 第三方充电设备信息Mapper接口
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@Mapper
+public interface ThirdPartyEquipmentInfoMapper extends BaseMapper<ThirdPartyEquipmentInfo> {
+}

+ 15 - 0
src/main/java/com/zsElectric/boot/charging/mapper/ThirdPartyStationInfoMapper.java

@@ -0,0 +1,15 @@
+package com.zsElectric.boot.charging.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 第三方充电站信息Mapper接口
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@Mapper
+public interface ThirdPartyStationInfoMapper extends BaseMapper<ThirdPartyStationInfo> {
+}

+ 65 - 0
src/main/java/com/zsElectric/boot/charging/quartz/ChargingJob.java

@@ -0,0 +1,65 @@
+package com.zsElectric.boot.charging.quartz;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.zsElectric.boot.charging.service.ChargingBusinessService;
+import com.zsElectric.boot.charging.vo.QueryStationsInfoVO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 充电站信息同步定时任务
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class ChargingJob {
+
+    private final ChargingBusinessService chargingBusinessService;
+
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    /**
+     * 定时同步充电站信息
+     * 每半小时执行一次,从第三方接口获取充电站信息并存储到数据库
+     * cron表达式: 0 0/30 * * * ? 表示每小时的0分和30分执行
+     */
+    @Scheduled(cron = "0 0/30 * * * ?")
+    public void syncStationsInfo() {
+        log.info("开始执行充电站信息同步定时任务");
+        
+        try {
+            // 获取当前时间作为查询时间
+            String lastQueryTime = LocalDateTime.now().minusMinutes(30).format(FORMATTER);
+            
+            // 分页查询,每次查询100条
+            Integer pageNo = 1;
+            Integer pageSize = 100;
+            
+            log.info("查询参数 - LastQueryTime: {}, PageNo: {}, PageSize: {}", lastQueryTime, pageNo, pageSize);
+            
+            // 调用业务服务查询充电站信息(会自动保存到数据库)
+            QueryStationsInfoVO result = chargingBusinessService.queryStationsInfo(lastQueryTime, pageNo, pageSize);
+            
+            if (result != null && result.getStationInfos() != null) {
+                log.info("充电站信息同步完成,共同步 {} 个充电站", result.getStationInfos().size());
+            } else {
+                log.warn("充电站信息同步结果为空");
+            }
+            
+        } catch (JsonProcessingException e) {
+            log.error("充电站信息同步失败 - JSON处理异常", e);
+        } catch (Exception e) {
+            log.error("充电站信息同步失败 - 系统异常", e);
+        }
+        
+        log.info("充电站信息同步定时任务执行结束");
+    }
+}

+ 19 - 0
src/main/java/com/zsElectric/boot/charging/service/ThirdPartyStationDataService.java

@@ -0,0 +1,19 @@
+package com.zsElectric.boot.charging.service;
+
+import com.zsElectric.boot.charging.vo.QueryStationsInfoVO;
+
+/**
+ * 第三方充电站数据存储服务
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+public interface ThirdPartyStationDataService {
+
+    /**
+     * 保存充电站信息到数据库
+     *
+     * @param queryStationsInfoVO 充电站信息
+     */
+    void saveStationsInfo(QueryStationsInfoVO queryStationsInfoVO);
+}

+ 12 - 1
src/main/java/com/zsElectric/boot/charging/service/impl/ChargingBusinessServiceImpl.java

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.zsElectric.boot.charging.dto.StartChargingRequestDTO;
 import com.zsElectric.boot.charging.dto.StartChargingResponseVO;
 import com.zsElectric.boot.charging.service.ChargingBusinessService;
+import com.zsElectric.boot.charging.service.ThirdPartyStationDataService;
 import com.zsElectric.boot.charging.vo.*;
 import com.zsElectric.boot.common.constant.ConnectivityConstants;
 import com.zsElectric.boot.common.util.AESCryptoUtils;
@@ -30,6 +31,7 @@ import java.util.Objects;
 public class ChargingBusinessServiceImpl implements ChargingBusinessService {
 
     private final ChargingUtil chargingUtil;
+    private final ThirdPartyStationDataService thirdPartyStationDataService;
 
     private final ObjectMapper objectMapper = new ObjectMapper();
 
@@ -135,7 +137,16 @@ public class ChargingBusinessServiceImpl implements ChargingBusinessService {
         if (responseDecode == null) {
             return null;
         }
-        return objectMapper.readValue(responseDecode.toString(), QueryStationsInfoVO.class);
+        QueryStationsInfoVO result = objectMapper.readValue(responseDecode.toString(), QueryStationsInfoVO.class);
+        
+        // 保存充电站信息到数据库
+        try {
+            thirdPartyStationDataService.saveStationsInfo(result);
+        } catch (Exception e) {
+            log.error("保存充电站信息到数据库失败", e);
+        }
+        
+        return result;
     }
 
     @Override

+ 242 - 0
src/main/java/com/zsElectric/boot/charging/service/impl/ThirdPartyStationDataServiceImpl.java

@@ -0,0 +1,242 @@
+package com.zsElectric.boot.charging.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsElectric.boot.charging.entity.*;
+import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyEquipmentInfoMapper;
+import com.zsElectric.boot.charging.mapper.ThirdPartyStationInfoMapper;
+import com.zsElectric.boot.charging.service.ThirdPartyStationDataService;
+import com.zsElectric.boot.charging.vo.QueryStationsInfoVO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 第三方充电站数据存储服务实现
+ *
+ * @author system
+ * @since 2025-12-11
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ThirdPartyStationDataServiceImpl implements ThirdPartyStationDataService {
+
+    private final ThirdPartyStationInfoMapper stationInfoMapper;
+    private final ThirdPartyEquipmentInfoMapper equipmentInfoMapper;
+    private final ThirdPartyConnectorInfoMapper connectorInfoMapper;
+    private final ObjectMapper objectMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveStationsInfo(QueryStationsInfoVO queryStationsInfoVO) {
+        if (queryStationsInfoVO == null || CollectionUtils.isEmpty(queryStationsInfoVO.getStationInfos())) {
+            log.warn("充电站信息为空,跳过存储");
+            return;
+        }
+
+        List<StationInfo> stationInfos = queryStationsInfoVO.getStationInfos();
+        log.info("开始保存充电站信息,总数: {}", stationInfos.size());
+
+        for (StationInfo stationInfo : stationInfos) {
+            try {
+                // 保存充电站信息
+                saveStationInfo(stationInfo);
+
+                // 保存设备信息
+                if (!CollectionUtils.isEmpty(stationInfo.getEquipmentInfos())) {
+                    for (EquipmentInfo equipmentInfo : stationInfo.getEquipmentInfos()) {
+                        saveEquipmentInfo(equipmentInfo, stationInfo.getStationID());
+
+                        // 保存接口信息
+                        if (!CollectionUtils.isEmpty(equipmentInfo.getConnectorInfos())) {
+                            for (ConnectorInfo connectorInfo : equipmentInfo.getConnectorInfos()) {
+                                saveConnectorInfo(connectorInfo, equipmentInfo.getEquipmentID(), stationInfo.getStationID());
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                log.error("保存充电站信息失败, stationId: {}", stationInfo.getStationID(), e);
+                throw new RuntimeException("保存充电站信息失败: " + stationInfo.getStationID(), e);
+            }
+        }
+
+        log.info("充电站信息保存完成");
+    }
+
+    /**
+     * 保存充电站信息
+     */
+    private void saveStationInfo(StationInfo stationInfo) {
+        // 查询是否已存在
+        ThirdPartyStationInfo existingStation = stationInfoMapper.selectOne(
+                new LambdaQueryWrapper<ThirdPartyStationInfo>()
+                        .eq(ThirdPartyStationInfo::getStationId, stationInfo.getStationID())
+        );
+
+        ThirdPartyStationInfo entity = new ThirdPartyStationInfo();
+        if (existingStation != null) {
+            entity.setId(existingStation.getId());
+        }
+
+        // 设置字段值
+        entity.setStationId(stationInfo.getStationID());
+        entity.setOperatorId(stationInfo.getOperatorID());
+        entity.setEquipmentOwnerId(stationInfo.getEquipmentOwnerID());
+        entity.setStationName(stationInfo.getStationName());
+        entity.setCountryCode(stationInfo.getCountryCode());
+        entity.setAreaCode(stationInfo.getAreaCode());
+        entity.setAddress(stationInfo.getAddress());
+        entity.setStationTel(stationInfo.getStationTel());
+        entity.setServiceTel(stationInfo.getServiceTel());
+        entity.setStationType(stationInfo.getStationType());
+        entity.setStationStatus(stationInfo.getStationStatus());
+        entity.setParkNums(stationInfo.getParkNums());
+        
+        // 处理经纬度
+        if (stationInfo.getStationLng() != null) {
+            entity.setStationLng(BigDecimal.valueOf(stationInfo.getStationLng()));
+        }
+        if (stationInfo.getStationLat() != null) {
+            entity.setStationLat(BigDecimal.valueOf(stationInfo.getStationLat()));
+        }
+        
+        entity.setSiteGuide(stationInfo.getSiteGuide());
+        entity.setConstruction(stationInfo.getConstruction());
+        
+        // 处理图片列表(转JSON)
+        if (!CollectionUtils.isEmpty(stationInfo.getPictures())) {
+            try {
+                entity.setPictures(objectMapper.writeValueAsString(stationInfo.getPictures()));
+            } catch (JsonProcessingException e) {
+                log.warn("图片列表转JSON失败", e);
+            }
+        }
+        
+        entity.setBusineHours(stationInfo.getBusineHours());
+        
+        // 处理费用(字符串转BigDecimal)
+        if (stationInfo.getElectricityFee() != null) {
+            try {
+                entity.setElectricityFee(new BigDecimal(stationInfo.getElectricityFee()));
+            } catch (NumberFormatException e) {
+                log.warn("电费转换失败: {}", stationInfo.getElectricityFee(), e);
+            }
+        }
+        if (stationInfo.getServiceFee() != null) {
+            try {
+                entity.setServiceFee(new BigDecimal(stationInfo.getServiceFee()));
+            } catch (NumberFormatException e) {
+                log.warn("服务费转换失败: {}", stationInfo.getServiceFee(), e);
+            }
+        }
+        
+        entity.setParkFee(stationInfo.getParkFee());
+        entity.setPayment(stationInfo.getPayment());
+        entity.setSupportOrder(stationInfo.getSupportOrder());
+        entity.setRemark(stationInfo.getRemark());
+
+        // 插入或更新
+        if (existingStation == null) {
+            stationInfoMapper.insert(entity);
+        } else {
+            stationInfoMapper.updateById(entity);
+        }
+    }
+
+    /**
+     * 保存充电设备信息
+     */
+    private void saveEquipmentInfo(EquipmentInfo equipmentInfo, String stationId) {
+        // 查询是否已存在
+        ThirdPartyEquipmentInfo existingEquipment = equipmentInfoMapper.selectOne(
+                new LambdaQueryWrapper<ThirdPartyEquipmentInfo>()
+                        .eq(ThirdPartyEquipmentInfo::getEquipmentId, equipmentInfo.getEquipmentID())
+        );
+
+        ThirdPartyEquipmentInfo entity = new ThirdPartyEquipmentInfo();
+        if (existingEquipment != null) {
+            entity.setId(existingEquipment.getId());
+        }
+
+        // 设置字段值
+        entity.setEquipmentId(equipmentInfo.getEquipmentID());
+        entity.setStationId(stationId);
+        entity.setManufacturerId(equipmentInfo.getManufacturerID());
+        entity.setManufacturerName(equipmentInfo.getManufacturerName());
+        entity.setEquipmentModel(equipmentInfo.getEquipmentModel());
+        entity.setProductionDate(equipmentInfo.getProductionDate());
+        entity.setEquipmentType(equipmentInfo.getEquipmentType());
+        
+        // 处理经纬度
+        if (equipmentInfo.getEquipmentLng() != null) {
+            entity.setEquipmentLng(BigDecimal.valueOf(equipmentInfo.getEquipmentLng()));
+        }
+        if (equipmentInfo.getEquipmentLat() != null) {
+            entity.setEquipmentLat(BigDecimal.valueOf(equipmentInfo.getEquipmentLat()));
+        }
+        
+        // 处理功率
+        if (equipmentInfo.getPower() != null) {
+            entity.setPower(BigDecimal.valueOf(equipmentInfo.getPower()));
+        }
+        
+        entity.setEquipmentName(equipmentInfo.getEquipmentName());
+
+        // 插入或更新
+        if (existingEquipment == null) {
+            equipmentInfoMapper.insert(entity);
+        } else {
+            equipmentInfoMapper.updateById(entity);
+        }
+    }
+
+    /**
+     * 保存充电接口信息
+     */
+    private void saveConnectorInfo(ConnectorInfo connectorInfo, String equipmentId, String stationId) {
+        // 查询是否已存在
+        ThirdPartyConnectorInfo existingConnector = connectorInfoMapper.selectOne(
+                new LambdaQueryWrapper<ThirdPartyConnectorInfo>()
+                        .eq(ThirdPartyConnectorInfo::getConnectorId, connectorInfo.getConnectorID())
+        );
+
+        ThirdPartyConnectorInfo entity = new ThirdPartyConnectorInfo();
+        if (existingConnector != null) {
+            entity.setId(existingConnector.getId());
+        }
+
+        // 设置字段值
+        entity.setConnectorId(connectorInfo.getConnectorID());
+        entity.setEquipmentId(equipmentId);
+        entity.setStationId(stationId);
+        entity.setConnectorName(connectorInfo.getConnectorName());
+        entity.setConnectorType(connectorInfo.getConnectorType());
+        entity.setVoltageUpperLimits(connectorInfo.getVoltageUpperLimits());
+        entity.setVoltageLowerLimits(connectorInfo.getVoltageLowerLimits());
+        entity.setCurrent(connectorInfo.getCurrent());
+        
+        // 处理功率
+        if (connectorInfo.getPower() != null) {
+            entity.setPower(BigDecimal.valueOf(connectorInfo.getPower()));
+        }
+        
+        entity.setParkNo(connectorInfo.getParkNo());
+        entity.setNationalStandard(connectorInfo.getNationalStandard());
+
+        // 插入或更新
+        if (existingConnector == null) {
+            connectorInfoMapper.insert(entity);
+        } else {
+            connectorInfoMapper.updateById(entity);
+        }
+    }
+}

+ 90 - 0
src/main/resources/mapper/app/ChargeOrderInfoMapper.xml

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zsElectric.boot.app.mapper.ChargeOrderInfoMapper">
+
+    <resultMap type="com.zsElectric.boot.app.model.entity.ChargeOrderInfo" id="ChargeOrderInfoResult">
+        <result property="id"    column="id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="orderType"    column="order_type"    />
+        <result property="ecId"    column="ec_id"    />
+        <result property="firmPrice"    column="firm_price"    />
+        <result property="deviceId"    column="device_id"    />
+        <result property="paySsn"    column="paySsn"    />
+        <result property="chargeOrderNo"    column="charge_order_no"    />
+        <result property="startTime"    column="start_time"    />
+        <result property="endTime"    column="end_time"    />
+        <result property="chargeTime"    column="charge_time"    />
+        <result property="status"    column="status"    />
+        <result property="thirdPartyTotalCost"    column="third_party_total_cost"    />
+        <result property="thirdPartyServerfee"    column="third_party_serverfee"    />
+        <result property="thirdPartyElecfee"    column="third_party_elecfee"    />
+        <result property="realThirdCost"    column="real_third_cost"    />
+        <result property="totalCharge"    column="total_charge"    />
+        <result property="realCost"    column="real_cost"    />
+        <result property="realServiceCost"    column="real_service_cost"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="stopType"    column="stop_type"    />
+        <result property="updateFlag"    column="update_flag"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="phoneNum"    column="phone_num"    />
+        <result property="plateNum"    column="plate_num"    />
+        <result property="stopReason"    column="stop_reason"    />
+        <result property="chargeDetails"    column="charge_details"    />
+        <result property="thirdPartyStationId"    column="third_party_station_id"    />
+        <result property="preAmt"    column="preAmt"    />
+        <result property="realPredictServiceCost"    column="real_predict_service_cost"    />
+        <result property="beforeBalance"    column="before_balance"    />
+        <result property="changeBalance"    column="change_balance"    />
+        <result property="maspAmount"    column="maspAmount"    />
+        <result property="maspRealAmount"    column="masp_real_amount"    />
+        <result property="maspStatus"    column="masp_status"    />
+        <result property="maspTime"    column="masp_time"    />
+        <result property="discountMoney"    column="discountMoney"    />
+        <result property="discountDes"    column="discountDes"    />
+        <result property="discountInfoId"    column="discountInfoId"    />
+        <result property="couponPrice"    column="coupon_price"    />
+        <result property="couponId"    column="coupon_id"    />
+        <result property="totalMaspMoney"    column="total_masp_money"    />
+        <result property="firmName"    column="firm_name"    />
+        <result property="firmId"    column="firm_id"    />
+    </resultMap>
+
+    <sql id="selectChargeOrderInfoVo">
+        select o.*,
+               s.name as station_name,
+               u.phone as user_phone,
+               d.device_name,
+               d.device_no,
+               f.name as firm_name
+        from c_charge_order_info o
+        left join c_user_info u on o.user_id = u.id
+        left join c_charge_device d on o.device_id = d.id
+        left join c_charge_station s on d.station_id = s.id
+        left join c_firm_info f on o.firm_id = f.id
+    </sql>
+
+    <select id="selectChargeOrderInfoListWithDetails" parameterType="com.zsElectric.boot.app.model.query.ChargeOrderInfoPageQuery" resultMap="ChargeOrderInfoResult">
+        <include refid="selectChargeOrderInfoVo"/>
+        <where>
+            <if test="userId != null">and o.user_id = #{userId}</if>
+            <if test="orderType != null">and o.order_type = #{orderType}</if>
+            <if test="ecId != null">and o.ec_id = #{ecId}</if>
+            <if test="firmId != null">and o.firm_id = #{firmId}</if>
+            <if test="deviceId != null">and o.device_id = #{deviceId}</if>
+            <if test="status != null">and o.status = #{status}</if>
+            <if test="chargeOrderNo != null and chargeOrderNo != ''">and o.charge_order_no like concat('%', #{chargeOrderNo}, '%')</if>
+            <if test="startTimeBegin != null and startTimeBegin != ''">
+                and o.start_time &gt;= #{startTimeBegin}
+            </if>
+            <if test="startTimeEnd != null and startTimeEnd != ''">
+                and o.start_time &lt;= #{startTimeEnd}
+            </if>
+        </where>
+        order by o.create_time desc
+    </select>
+
+</mapper>