无关风月
2025-04-19 8d6ef24217033e13b356502f2ade8737a43cce2b
MQ消息队列监管平台数据上传
7个文件已修改
82个文件已添加
5639 ■■■■■ 已修改文件
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/ServiceNameConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/pom.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/iotda/constant/SendTagConstant.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/ChargingMessage.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/ChargingOrderMessage.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/GunStatusMessage.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageUtil.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/EnhanceProduce.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/pom.xml 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/RuoYiJianGuanApplication.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseModel.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseModelJianGuan.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseRequest.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseRequestJianGuan.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseResult.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ChargeDetail.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorInfo.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatsInfo.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatusInfo.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatusInfo1.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/EquipmentInfo.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/EquipmentStatsInfo.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationChargeOrderInfo.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationChargeOrderInfoResult.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationEquipChargeStatusResult.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStartCharge.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStartChargeResult.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStationStatusResult.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStopCharge.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStopChargeResult.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/OperatorInfo.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PlaceHolder.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PlaceHolderPrice.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PolicyInfo.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipAuth.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipAuthResult.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipBusinessPolicy.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipBusinessPolicyResult.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipChargeStatus.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipChargeStatusResult.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStartCharge.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStartChargeResult.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStats.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatsResult.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatus.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatusResult.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationsInfo.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationsInfoResult.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStopCharge.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStopChargeResult.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryToken.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryTokenResult.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationInfo.java 375 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatsInfo.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatsInfoResult.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatusInfo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupChargeOrderInfo.java 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupConnectorPowerInfo.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupEquipChargeStatus.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupEquipmentPowerInfo.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationInfo.java 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationInfoResult.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationPowerInfo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationPowerInfoResult.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfo.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfoResult.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfoResultPage.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/BaseMessage.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/ChargingOrderMessage.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/GunStatusMessage.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/JianGuanMessage.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/EnvironmentIsolationConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketEnhanceProperties.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketMQEnhanceAutoConfiguration.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketMQMessageConverter.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/constant/EnhanceMessageConstant.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/produce/ChargingMessageListener.java 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/util/EnhanceMessageHandler.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/util/RocketMQEnhanceTemplate.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/AESUtil.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/AesEncryption.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/HMacMD5Util.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SendTagConstant.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SequenceGenerator.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SignUtil.java 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/TCECSuperviseUtil.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/resources/logback.xml 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/resources/mybatis-config.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/ServiceNameConstants.java
@@ -26,5 +26,6 @@
    public static final String OTHER_SERVICE = "ruoyi-other";
    public static final String ORDER_SERVICE = "ruoyi-order";
    public static final String INTEGRATION_SERVICE = "ruoyi-integration";
    public static final String JIANGUAN_SERVICE = "ruoyi-jianguan";
    public static final String PAYMENT_SERVICE = "ruoyi-payment";
}
ruoyi-service/pom.xml
@@ -15,6 +15,7 @@
        <module>ruoyi-payment</module>
        <module>ruoyi-other</module>
        <module>ruoyi-integration</module>
        <module>ruoyi-jianguan</module>
    </modules>
    <artifactId>ruoyi-service</artifactId>
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/iotda/constant/SendTagConstant.java
@@ -7,6 +7,18 @@
 */
public class SendTagConstant {
    /**
     * 推送充电设备接口状态信息
     */
    public static final String GUN_STATUS ="gun_status";
    /**
     * 推送充电状态信息
     */
    public static final String ORDER_STATUS ="order_status";
    /**
     * 推送充电订单信息
     */
    public static final String ORDER_INFO = "order_info";
    /**
     * 充电桩登录认证
     */
    public static final String ONLINE ="online";
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/ChargingMessage.java
@@ -1,12 +1,18 @@
package com.ruoyi.integration.rocket.model;
import com.ruoyi.integration.drainage.model.ConnectorStatusInfo;
import com.ruoyi.integration.drainage.model.SupChargeOrderInfo;
import com.ruoyi.integration.drainage.model.SupEquipChargeStatus;
import com.ruoyi.integration.rocket.base.BaseMessage;
import lombok.Data;
import org.apache.poi.ss.formula.functions.T;
@Data
public class ChargingMessage extends BaseMessage {
    // 充电设备状态message
    private GunStatusMessage gunStatusMessage;
    // 推送充电订单状态/充电订单信息message
    private ChargingOrderMessage orderMessage;
    private AcquisitionBillingModeMessage acquisitionBillingModeMessage;
    private BillingModeVerifyMessage billingModeVerifyMessage;
    private BmsAbortMessage bmsAbortMessage;
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/ChargingOrderMessage.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.integration.rocket.model;
import com.ruoyi.integration.rocket.base.BaseMessage;
import lombok.Data;
/**
 * 充电桩计费模型请求
 **/
@Data
public class ChargingOrderMessage extends BaseMessage {
    private String orderNumber;// 订单编号
    private String soc;// soc
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/model/GunStatusMessage.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.integration.rocket.model;
import com.ruoyi.integration.rocket.base.BaseMessage;
import lombok.Data;
/**
 * 充电桩计费模型请求
 **/
@Data
public class GunStatusMessage extends BaseMessage {
    private String fullNumber;// 枪完整编码
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageListener.java
@@ -133,7 +133,8 @@
    @Resource
    private RedisTemplate redisTemplate;
    
    @Autowired
    private EnhanceProduce enhanceProduce;
    
    
    
@@ -173,13 +174,6 @@
                        vo1.setPile_code(pingMessage.getCharging_pile_code());
                        vo1.setStatus(pingMessage.getCharging_gun_status());
                        chargingPileClient.updateChargingPileStatus(vo1);
                        try {
                            tcecPushUtil.pushSuperviseNotificationStationStatus(chargingGunClient.getChargingGunByFullNumber(pingMessage.getCharging_pile_code()+pingMessage.getCharging_gun_code()).getData());
                        }catch (Exception e){
                            e.printStackTrace();
                            System.out.println("设备状态推送监管平台失败:"+e.getMessage());
                        }
                    }
                });
                break;
@@ -196,14 +190,28 @@
                    public void run() {
                        // 业务处理
                        chargingOrderClient.endCharge(endCharge.getTransaction_serial_number());
                        try {
                            TChargingOrder chargingOrder = chargingOrderClient.getOrderByCode(endCharge.getTransaction_serial_number()).getData();
                            tcecPushUtil.pushSuperviseNotificationChargeOrderInfo(chargingOrder);
                            tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder);
                        }catch (Exception e){
                            e.printStackTrace();
                            System.out.println("充电结束推送监管平台失败:"+e.getMessage());
                        }
                        // 订单id
                        String transactionSerialNumber = endCharge.getTransaction_serial_number();
                        ChargingOrderMessage chargingOrderMessage = new ChargingOrderMessage();
                        chargingOrderMessage.setOrderNumber(transactionSerialNumber);
                        // 推送充电订单信息
                        ChargingMessage chargingMessage1 = new ChargingMessage();
                        chargingMessage1.setServiceId(SendTagConstant.ORDER_INFO);
                        chargingMessage1.setOrderMessage(chargingOrderMessage);
                        enhanceProduce.orderInfoMessage(chargingMessage1);
                        // 推送充电订单状态
                        ChargingMessage chargingMessage2 = new ChargingMessage();
                        chargingMessage2.setServiceId(SendTagConstant.ORDER_STATUS);
                        chargingMessage2.setOrderMessage(chargingOrderMessage);
                        enhanceProduce.orderStatusMessage(chargingMessage2);
//                        try {
//                            TChargingOrder chargingOrder = chargingOrderClient.getOrderByCode(endCharge.getTransaction_serial_number()).getData();
//                            tcecPushUtil.pushSuperviseNotificationChargeOrderInfo(chargingOrder);
//                            tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder);
//                        }catch (Exception e){
//                            e.printStackTrace();
//                            System.out.println("充电结束推送监管平台失败:"+e.getMessage());
//                        }
                    }
                });
                break;
@@ -276,8 +284,15 @@
                            BeanUtils.copyProperties(uploadRealTimeMonitoringData, query);
                            chargingOrderClient.chargeMonitoring(query);
                            chargingOrder.setEndSoc(uploadRealTimeMonitoringDataMessage.getSoc()+"");
                            tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder);
                            ChargingOrderMessage chargingOrderMessage3 = new ChargingOrderMessage();
                            chargingOrderMessage3.setSoc(uploadRealTimeMonitoringDataMessage.getSoc()+"");
                            chargingOrderMessage3.setOrderNumber(chargingOrder.getCode());
                            // 推送充电订单信息
                            ChargingMessage chargingMessage4 = new ChargingMessage();
                            chargingMessage4.setServiceId(SendTagConstant.ORDER_STATUS);
                            chargingMessage4.setOrderMessage(chargingOrderMessage3);
                            enhanceProduce.orderInfoMessage(chargingMessage4);
//                            tcecPushUtil.pushSuperviseNotificationEquipChargeStatus(chargingOrder);
                        }
                    });
                } catch (Exception e) {
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/ChargingMessageUtil.java
@@ -5,6 +5,7 @@
import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient;
import com.ruoyi.chargingPile.api.model.TAccountingStrategyDetail;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.chargingPile.api.vo.UpdateChargingPileStatusVo;
import com.ruoyi.integration.api.model.*;
import com.ruoyi.integration.drainage.TCECPushUtil;
@@ -20,6 +21,7 @@
import com.ruoyi.order.api.vo.SecurityDetectionVO;
import com.ruoyi.order.api.vo.TransactionRecordMessageVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
@@ -105,8 +107,8 @@
    private QrCodeDeliveryReplyService qrCodeDeliveryReplyService;
    @Autowired
    private SecurityDetectionService securityDetectionService;
//    @Autowired
//    private TCECPushUtil tcecPushUtil;
    @Autowired
    private TCECPushUtil tcecPushUtil;
    @Resource
    private ChargingPileClient chargingPileClient;
@@ -115,7 +117,8 @@
    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private EnhanceProduce enhanceProduce;
    
    
    
@@ -152,20 +155,16 @@
                vo1.setPile_code(pingMessage.getCharging_pile_code());
                vo1.setStatus(pingMessage.getCharging_gun_status());
                chargingPileClient.updateChargingPileStatus(vo1);
                // 监管平台推送充电设备状态
                SendResult sendResult;
                String gunCode = pingMessage.getCharging_pile_code() + pingMessage.getCharging_gun_code();
                ChargingMessage chargingMessage = new ChargingMessage();
                chargingMessage.setServiceId(SendTagConstant.GUN_STATUS);
                GunStatusMessage gunStatusMessage = new GunStatusMessage();
                gunStatusMessage.setFullNumber(gunCode);
                chargingMessage.setGunStatusMessage(gunStatusMessage);
                sendResult = enhanceProduce.gunStatusMessage(chargingMessage);
                
//                ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
//                threadPoolExecutor.execute(new Runnable() {
//                    @Override
//                    public void run() {
//
//                        try {
////                            tcecPushUtil.pushSuperviseNotificationStationStatus(chargingGunClient.getChargingGunByFullNumber(pingMessage.getCharging_pile_code()+pingMessage.getCharging_gun_code()).getData());
//                        }catch (Exception e){
//                            e.printStackTrace();
//                            System.out.println("设备状态推送监管平台失败:"+e.getMessage());
//                        }
//                    }
//                });
                break;
            case SendTagConstant.END_CHARGE:
                EndChargeMessage endChargeMessage = message.getEndChargeMessage();
@@ -176,6 +175,20 @@
                endChargeService.create(endCharge);
                // 业务处理
                chargingOrderClient.endCharge(endCharge.getTransaction_serial_number());
                // 订单id
                String transactionSerialNumber = endCharge.getTransaction_serial_number();
                ChargingOrderMessage chargingOrderMessage = new ChargingOrderMessage();
                chargingOrderMessage.setOrderNumber(transactionSerialNumber);
                // 推送充电订单信息
                ChargingMessage chargingMessage1 = new ChargingMessage();
                chargingMessage1.setServiceId(SendTagConstant.ORDER_INFO);
                chargingMessage1.setOrderMessage(chargingOrderMessage);
                enhanceProduce.orderInfoMessage(chargingMessage1);
                // 推送充电订单状态
                ChargingMessage chargingMessage2 = new ChargingMessage();
                chargingMessage2.setServiceId(SendTagConstant.ORDER_STATUS);
                chargingMessage2.setOrderMessage(chargingOrderMessage);
                enhanceProduce.orderStatusMessage(chargingMessage2);
//                ThreadPoolExecutor threadPoolExecutor1 = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
//                threadPoolExecutor1.execute(new Runnable() {
//                    @Override
@@ -255,6 +268,14 @@
                    UploadRealTimeMonitoringDataQuery query = new UploadRealTimeMonitoringDataQuery();
                    BeanUtils.copyProperties(uploadRealTimeMonitoringData, query);
                    chargingOrderClient.chargeMonitoring(query);
                    // 订单id
                    ChargingOrderMessage chargingOrderMessage3 = new ChargingOrderMessage();
                    chargingOrderMessage3.setOrderNumber(chargingOrder.getCode());
                    // 推送充电订单信息
                    ChargingMessage chargingMessage4 = new ChargingMessage();
                    chargingMessage4.setServiceId(SendTagConstant.ORDER_STATUS);
                    chargingMessage4.setOrderMessage(chargingOrderMessage3);
                    enhanceProduce.orderInfoMessage(chargingMessage4);
//                    ThreadPoolExecutor threadPoolExecutor2 = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
//                    threadPoolExecutor2.execute(new Runnable() {
//                        @Override
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/rocket/produce/EnhanceProduce.java
@@ -26,6 +26,7 @@
    private RocketMQEnhanceTemplate rocketMQEnhanceTemplate;
    private static final String TOPIC = "charge_";
    private static final String TOPIC_JIANGUAN = "jianguan_";
    /**
     * 充电桩登录认证
@@ -352,9 +353,40 @@
        // 设置消息来源,便于查询
        message.setSource(SendTagConstant.CHARGING_MESSAGE);
        
        return rocketMQEnhanceTemplate.send(TOPIC+SendTagConstant.CHARGING_MESSAGE, SendTagConstant.CHARGING_MESSAGE, message);
    }
    /**
     * 监管平台推送充电设备接口状态
     */
    public SendResult gunStatusMessage(ChargingMessage message) {
        // 设置业务key
        message.setKey(UUID.randomUUID().toString());
        // 设置消息来源,便于查询
        message.setSource(SendTagConstant.GUN_STATUS);
        return rocketMQEnhanceTemplate.send(TOPIC_JIANGUAN+SendTagConstant.GUN_STATUS, SendTagConstant.GUN_STATUS, message);
    }
    /**
     * 监管平台推送充电订单信息
     */
    public SendResult orderInfoMessage(ChargingMessage message) {
        // 设置业务key
        message.setKey(UUID.randomUUID().toString());
        // 设置消息来源,便于查询
        message.setSource(SendTagConstant.ORDER_INFO);
        return rocketMQEnhanceTemplate.send(TOPIC_JIANGUAN+SendTagConstant.ORDER_INFO, SendTagConstant.ORDER_INFO, message);
    }
    /**
     * 监管平台推送充电订单状态
     */
    public SendResult orderStatusMessage(ChargingMessage message) {
        // 设置业务key
        message.setKey(UUID.randomUUID().toString());
        // 设置消息来源,便于查询
        message.setSource(SendTagConstant.ORDER_STATUS);
        return rocketMQEnhanceTemplate.send(TOPIC_JIANGUAN+SendTagConstant.ORDER_STATUS, SendTagConstant.ORDER_STATUS, message);
    }
}
ruoyi-service/ruoyi-jianguan/pom.xml
New file
@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-service</artifactId>
        <version>3.6.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ruoyi-modules-jianguan</artifactId>
    <description>
        ruoyi-modules-jianguan监管平台数据上传模块
    </description>
    <dependencies>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-api-integration</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- SpringCloud Alibaba Sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>
        <!-- SpringBoot Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- Swagger UI -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.fox.version}</version>
        </dependency>
        <!-- Mysql Connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- RuoYi Common DataSource -->
        <!--        <dependency>-->
        <!--            <groupId>com.ruoyi</groupId>-->
        <!--            <artifactId>ruoyi-common-datasource</artifactId>-->
        <!--        </dependency>-->
        <!--        &lt;!&ndash; RuoYi Common DataScope &ndash;&gt;-->
        <!--        <dependency>-->
        <!--            <groupId>com.ruoyi</groupId>-->
        <!--            <artifactId>ruoyi-common-datascope</artifactId>-->
        <!--        </dependency>-->
        <!-- RuoYi Common Log -->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common-log</artifactId>
        </dependency>
        <!-- RuoYi Common Swagger -->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common-swagger</artifactId>
        </dependency>
        <!-- 引入Druid依赖,阿里巴巴所提供的数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--rocketmq-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
            <version>2.2.2.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.rocketmq</groupId>
                    <artifactId>rocketmq-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.rocketmq</groupId>
                    <artifactId>rocketmq-acl</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-acl</artifactId>
            <version>4.7.1</version>
        </dependency>
        <!--mongodb-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.huaweicloud.sdk</groupId>
            <artifactId>huaweicloud-sdk-bundle</artifactId>
            <version>3.1.87</version>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-api-order</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-api-chargingPile</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/RuoYiJianGuanApplication.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.jianguan;
import com.huaweicloud.sdk.thirdparty.okio.Sink;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.xml.transform.Source;
/**
 * 账户模块
 * @author ruoyi
 */
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
@EnableScheduling//开启定时任务
public class RuoYiJianGuanApplication {
    public static void main(String[] args) {
        SpringApplication.run(RuoYiJianGuanApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  监管平台模块启动成功   ლ(´ڡ`ლ)゙  \n" +
                " .-------.       ____     __        \n" +
                " |  _ _   \\      \\   \\   /  /    \n" +
                " | ( ' )  |       \\  _. /  '       \n" +
                " |(_ o _) /        _( )_ .'         \n" +
                " | (_,_).' __  ___(_ o _)'          \n" +
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
                " |  | \\ `'   /|   `-'  /           \n" +
                " |  |  \\    /  \\      /           \n" +
                " ''-'   `'-'    `-..-'              ");
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseModel.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.other.api.domain.Operator;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * @author zhibing.pu
 * @Date 2025/1/23 18:33
 */
@Data
public class BaseModel {
    /**
     * 运营商标识
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 参数内容
     */
    @NotNull
    @JsonProperty("Data")
    private String data;
    /**
     * 时间戳
     * yyyyMMddHHmmss
     */
    @NotNull
    @JsonProperty("TimeStamp")
    private Long timeStamp;
    /**
     * 自增序列
     * 4位自增序列取自时间戳,同一秒内按序列自增长,新秒重计。如 0001
     */
    @NotNull
    @JsonProperty("Seq")
    private String seq;
    /**
     * 运营商对象
     */
    @JsonIgnore
    private Operator operator;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseModelJianGuan.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.other.api.domain.Operator;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * @author zhibing.pu
 * @Date 2025/1/23 18:33
 */
@Data
public class BaseModelJianGuan {
    /**
     * 运营商标识
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 参数内容
     */
    @NotNull
    @JsonProperty("Data")
    private String data;
    /**
     * 时间戳
     * yyyyMMddHHmmss
     */
    @NotNull
    @JsonProperty("TimeStamp")
    private String timeStamp;
    /**
     * 自增序列
     * 4位自增序列取自时间戳,同一秒内按序列自增长,新秒重计。如 0001
     */
    @NotNull
    @JsonProperty("Seq")
    private String seq;
    /**
     * 运营商对象
     */
    @JsonIgnore
    private Operator operator;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseRequest.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 公共请求
 * @author zhibing.pu
 * @Date 2025/1/21 17:08
 */
@Data
public class BaseRequest extends BaseModel {
    /**
     * 数字签名
     */
    @NotNull
    @JsonProperty("Sig")
    private String sig;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseRequestJianGuan.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 公共请求
 * @author zhibing.pu
 * @Date 2025/1/21 17:08
 */
@Data
public class BaseRequestJianGuan extends BaseModelJianGuan {
    /**
     * 数字签名
     */
    @NotNull
    @JsonProperty("Sig")
    private String sig;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/BaseResult.java
New file
@@ -0,0 +1,46 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.other.api.domain.Operator;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 公共返回结果
 * @author zhibing.pu
 * @Date 2025/1/21 15:54
 */
@Data
public class BaseResult extends BaseModel {
    /**
     * 参数编码
     * -1:系统繁忙,此时请求方稍后重试
     * 0:请求成功
     * 4001:签名错误
     * 4002:Token错误
     * 4003:POST参数不合法,缺少必需的
     * 4004:请求的业务参数不合法
     * 500:系统错误
     */
    @NotNull
    @JsonProperty("Ret")
    private Integer ret;
    /**
     * 错误信息描述
     */
    @NotNull
    @JsonProperty("Msg")
    private String msg;
    /**
     * 签名
     */
    @NotNull
    @JsonProperty("Sig")
    private String sig;
    /**
     * 运营商对象
     */
    private Operator operator;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ChargeDetail.java
New file
@@ -0,0 +1,61 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
/**
 * 充电明细信息
 * @author zhibing.pu
 * @Date 2025/1/21 16:40
 */
@Data
public class ChargeDetail {
    /**
     * 开始时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    @JsonProperty("DetailStartTime")
    private String detailStartTime;
    /**
     * 结束时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    @JsonProperty("DetailEndTime")
    private String detailEndTime;
    /**
     * 时段电价
     */
    @Null
    @JsonProperty("ElecPrice")
    private BigDecimal elecPrice;
    /**
     * 时段服务费价格
     */
    @Null
    @JsonProperty("SevicePrice")
    private BigDecimal sevicePrice;
    /**
     * 时段充电量
     */
    @Null
    @JsonProperty("DetailPower")
    private BigDecimal detailPower;
    /**
     * 时段电费
     */
    @Null
    @JsonProperty("DetailElecMoney")
    private BigDecimal detailElecMoney;
    /**
     * 时段服务费
     */
    @Null
    @JsonProperty("DetailSeviceMoney")
    private BigDecimal detailSeviceMoney;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorInfo.java
New file
@@ -0,0 +1,112 @@
package com.ruoyi.jianguan.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
/**
 * 充电设备接口
 * @author zhibing.pu
 * @Date 2025/1/21 14:03
 */
@Data
public class ConnectorInfo {
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口名称
     */
    @NotNull
    @JsonProperty("ConnectorName")
    private String connectorName;
    /**
     * 1:车辆充电设备接口
     * 2:换电站内的电池箱充电设备接口
     */
    @Null
    @JsonProperty("EquipmentClassification")
    private Integer equipmentClassification;
    /**
     * 充电设备接口类型
     */
    @NotNull
    @JsonProperty("ConnectorType")
    private Integer connectorType;
    /**
     * 额定电压上限
     */
    @NotNull
    @JsonProperty("VoltageUpperLimits")
    private BigDecimal voltageUpperLimits;
    /**
     * 额定电压下限
     */
    @NotNull
    @JsonProperty("VoltageLowerLimits")
    private BigDecimal voltageLowerLimits;
    /**
     * 额定电流
     */
    @NotNull
    @JsonProperty("Current")
    private Integer current;
    /**
     * 额定功率
     */
    @NotNull
    @JsonProperty("Power")
    private BigDecimal power;
    /**
     * 车位号
     */
    @Null
    @JsonProperty("ParkNo")
    private String parkNo;
    /**
     * 国家标准
     * 1:2011
     * 2:2015
     * 3:兼容2011和2015
     */
    @NotNull
    @JsonProperty("NationalStandard")
    private Integer nationalStandard;
    /**
     * 枪二维码
     */
    @Null
    @JsonProperty("QRCode")
    private String QRCode;
    @Null
    @JsonProperty("ConstantVoltageUpperLimits")
    private BigDecimal constantVoltageUpperLimits;
    @Null
    @JsonProperty("ConstantVoltageLowerLimits")
    private BigDecimal constantVoltageLowerLimits;
    @Null
    @JsonProperty("ConstantCurrentUpperLimits")
    private BigDecimal constantCurrentUpperLimits;
    @Null
    @JsonProperty("ConstantCurrentLowerLimits")
    private BigDecimal constantCurrentLowerLimits;
    @NotNull
    @JsonProperty("AuxPower")
    private Integer auxPower;
    @NotNull
    @TableField("OpreateStatus")
    private Integer opreateStatus;
    @Null
    @TableField("OpreateHours")
    private String opreateHours;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatsInfo.java
New file
@@ -0,0 +1,49 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 充电设备接口统计信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:24
 */
@Data
public class ConnectorStatsInfo {
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口累计电量
     */
    @NotNull
    @JsonProperty("ConnectorElectricity")
    private BigDecimal connectorElectricity;
    /**
     * 充电设备接口累
     * 计充电时长
     */
    @NotNull
    @JsonProperty("ConnectorTotalChargeTime")
    private Integer ConnectorTotalChargeTime;
    /**
     * 充电设备接口累
     * 计充电次数
     */
    @NotNull
    @JsonProperty("ConnectorTotalChargeNum")
    private Integer ConnectorTotalChargeNum;
    /**
     * 充电设备接口累
     * 计告警数量
     */
    @NotNull
    @JsonProperty("ConnectorTotalWarningNum")
    private Integer ConnectorTotalWarningNum;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatusInfo.java
New file
@@ -0,0 +1,78 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * 充电设备接口状态
 * @author zhibing.pu
 * @Date 2025/1/21 14:53
 */
@Data
public class ConnectorStatusInfo {
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口状态
     * 0:离网
     * 1:空闲
     * 2:占用(未充电)
     * 3:占用(充电中)
     * 4:占用(预约锁定)
     * 255:故障
     */
    @NotNull
    @JsonProperty("Status")
    private Integer status;
    /**
     * 车位状态
     * 0:未知
     * 10:空闲
     * 50:占用
     */
    @Null
    @JsonProperty("ParkStatus")
    private Integer parkStatus;
    /**
     * 地锁状态
     * 0:未知
     * 10:已解锁
     * 50:已上锁
     */
    @Null
    @JsonProperty("LookStatus")
    private Integer lookStatus;
    @JsonProperty("ConnectorStatusInfo")
    private ConnectorStatusInfo connectorStatusInfo;
    @JsonProperty("OperatorID")
    private String OperatorID;
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    @JsonProperty("StationID")
    private String StationID;
    @JsonProperty("EquipmentID")
    private String EquipmentID;
    /**
     * 1:车辆充电设备接口
     * 2:换电站内的电池箱充
     * 电设备接口
     */
    @JsonProperty("EquipmentClassification")
    private Integer EquipmentClassification;
    /**
     * 本次状态变化的时间,
     * 格式“yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("UpdateTime")
    private String UpdateTime;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/ConnectorStatusInfo1.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * 充电设备接口状态
 * @author zhibing.pu
 * @Date 2025/1/21 14:53
 */
@Data
public class ConnectorStatusInfo1 {
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口状态
     * 0:离网
     * 1:空闲
     * 2:占用(未充电)
     * 3:占用(充电中)
     * 4:占用(预约锁定)
     * 255:故障
     */
    @NotNull
    @JsonProperty("Status")
    private Integer status;
    /**
     * 车位状态
     * 0:未知
     * 10:空闲
     * 50:占用
     */
    @Null
    @JsonProperty("ParkStatus")
    private Integer parkStatus;
    /**
     * 地锁状态
     * 0:未知
     * 10:已解锁
     * 50:已上锁
     */
    @Null
    @JsonProperty("LookStatus")
    private Integer lookStatus;
    private ConnectorStatusInfo1 ConnectorStatusInfo;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/EquipmentInfo.java
New file
@@ -0,0 +1,98 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电设备信息
 * @author zhibing.pu
 * @Date 2025/1/21 13:51
 */
@Data
public class EquipmentInfo {
    /**
     * 设备编号
     */
    @NotNull
    @JsonProperty("EquipmentID")
    private String equipmentID;
    /**
     * 设备生产商组织机构代码
     */
    @Null
    @JsonProperty("ManufacturerID")
    private String manufacturerID;
    /**
     * 设备唯一
     * 编码
     */
    @Null
    @JsonProperty("EquipmentUniqueNumber")
    private String equipmentUniqueNumber;
    /**
     * 设备生产商名称
     */
    @Null
    @JsonProperty("ManufacturerName")
    private String manufacturerName;
    /**
     * 设备型号
     */
    @Null
    @JsonProperty("EquipmentModel")
    private String equipmentModel;
    /**
     * 设备生产日期
     * YYYY-MM-DD
     */
    @Null
    @JsonProperty("ProductionDate")
    private String productionDate;
    /**
     * 设备类型
     */
    @NotNull
    @JsonProperty("EquipmentType")
    private Integer equipmentType;
    /**
     * 充电设备接口信息列表
     */
    @NotNull
    @JsonProperty("ConnectorInfos")
    private List<ConnectorInfo> connectorInfos;
    /**
     * 充电设备经度
     */
    @Null
    @JsonProperty("EquipmentLng")
    private BigDecimal equipmentLng;
    /**
     * 充电设备纬度
     */
    @Null
    @JsonProperty("EquipmentLat")
    private BigDecimal equipmentLat;
    /**
     * 充电设备总功率
     */
    @NotNull
    @JsonProperty("Power")
    private BigDecimal power;
    /**
     * 充电设备名称
     */
    @Null
    @JsonProperty("EquipmentName")
    private String equipmentName;
    /**
     * 设备分类
     */
    @NotNull
    @JsonProperty("EquipmentClassification")
    private Integer equipmentClassification;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/EquipmentStatsInfo.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电设备统计信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:22
 */
@Data
public class EquipmentStatsInfo {
    /**
     * 设备编码
     */
    @NotNull
    @JsonProperty("EquipmentID")
    private String equipmentID;
    /**
     * 充电设备接口累计电量
     */
    @NotNull
    @JsonProperty("EquipmentElectricity")
    private BigDecimal equipmentElectricity;
    /**
     * 设备分类 1:车辆充电设备
     * 2:换电站内的电池
     * 箱充电设备
     */
    @NotNull
    @JsonProperty("EquipmentClassification")
    private Integer equipmentClassification;
    /**
     * 充电设备累计充电时长 单位分钟
     */
    @NotNull
    @JsonProperty("EquipmentTotalChargeTime")
    private Long equipmentTotalChargeTime;
    /**
     * 充电设备累计充
     * 电次数
     */
    @NotNull
    @JsonProperty("EquipmentTotalChargeNum")
    private Integer equipmentTotalChargeNum;
    /**
     * 充电设备累计充
     * 电次数
     */
    @NotNull
    @JsonProperty("EquipmentTotalWarningNum")
    private Integer equipmentTotalWarningNum;
    /**
     * 充电设备接口统计信息列表
     */
    @NotNull
    @JsonProperty("ConnectorStatsInfos")
    private List<ConnectorStatsInfo> connectorStatsInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationChargeOrderInfo.java
New file
@@ -0,0 +1,106 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
import java.util.List;
/**
 * 推送充电订单信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:39
 */
@Data
public class NotificationChargeOrderInfo {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 开始充电时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 结束充电时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 累计充电量
     */
    @NotNull
    @JsonProperty("TotalPower")
    private BigDecimal totalPower;
    /**
     * 总电费
     */
    @NotNull
    @JsonProperty("TotalElecMoney")
    private BigDecimal totalElecMoney;
    /**
     * 总服务费
     */
    @NotNull
    @JsonProperty("TotalSeviceMoney")
    private BigDecimal totalSeviceMoney;
    /**
     * 累计总金额
     */
    @NotNull
    @JsonProperty("TotalMoney")
    private BigDecimal totalMoney;
    /**
     * 充电结束原因
     * 0:用户手动停止充电
     * 1:客户归属地运营商平台停止充电
     * 2:BMS停止充电
     * 3:充电机设备故障
     * 4:连接器断开
     * 5·99:自定义
     */
    @NotNull
    @JsonProperty("StopReason")
    private Integer stopReason;
    /**
     * 时段数 N
     * 0·32
     */
    @Null
    @JsonProperty("SumPeriod")
    private Integer sumPeriod;
    /**
     * 充电明细信息
     */
    @Null
    @JsonProperty("ChargeDetails")
    private List<ChargeDetail> chargeDetails;
    /**
     * 占位费
     */
    @Null
    @JsonProperty("TotalDelayMoney")
    private BigDecimal totalDelayMoney;
    /**
     * 车辆识别码
     */
    @Null
    @JsonProperty("VIN")
    private String VIN;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationChargeOrderInfoResult.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送充电订单信息返回记过
 * @author zhibing.pu
 * @Date 2025/1/21 15:49
 */
@Data
public class NotificationChargeOrderInfoResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 确认结果
     * 0;成功
     * 1:争议交易
     * 2·99:自定义
     */
    @JsonProperty("ConfirmResult")
    private Integer confirmResult;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationEquipChargeStatusResult.java
New file
@@ -0,0 +1,29 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送充电状态结果
 * @author zhibing.pu
 * @Date 2025/1/21 16:48
 */
@Data
public class NotificationEquipChargeStatusResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStartCharge.java
New file
@@ -0,0 +1,44 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送启动充电结果
 * @author zhibing.pu
 * @Date 2025/1/22 18:40
 */
@Data
public class NotificationStartCharge {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    @JsonProperty("StartChargeSeqStat")
    private Integer startChargeSeqStat;
    /**
     * 充电设别接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电启动时间
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStartChargeResult.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送启动充电结果返回值
 * @author zhibing.pu
 * @Date 2025/1/22 18:47
 */
@Data
public class NotificationStartChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:接收失败
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStationStatusResult.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 设备状态变化推动返回结果
 * @author zhibing.pu
 * @Date 2025/1/21 14:58
 */
@Data
public class NotificationStationStatusResult {
    /**
     * 状态
     * 0:接收
     * 1:丢弃/忽略,不需要重试
     */
    @NotNull
    @JsonProperty("Status")
    private Integer status;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStopCharge.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送停止充电结果应答
 * @author zhibing.pu
 * @Date 2025/1/23 9:17
 */
@Data
public class NotificationStopCharge {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:接收失败
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/NotificationStopChargeResult.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送停止充电结果
 * @author zhibing.pu
 * @Date 2025/1/23 9:13
 */
@Data
public class NotificationStopChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    @JsonProperty("StartChargeSeqStat")
    private Integer startChargeSeqStat;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3:此设备已停止充电
     * 4`9:自定义
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/OperatorInfo.java
New file
@@ -0,0 +1,52 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * 基础设施运营商信息
 * @author zhibing.pu
 * @Date 2025/1/21 11:49
 */
@Data
public class OperatorInfo {
    /**
     * 运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 运营商名称
     */
    @NotNull
    @JsonProperty("OperatorName")
    private String operatorName;
    /**
     * 运营商电话1
     */
    @NotNull
    @JsonProperty("OperatorTel1")
    private String operatorTel1;
    /**
     * 运营商电话2
     */
    @Null
    @JsonProperty("OperatorTel2")
    private String operatorTel2;
    /**
     * 运营商注册地址
     */
    @Null
    @JsonProperty("OperatorRegAddress")
    private String operatorRegAddress;
    /**
     * 备注
     */
    @Null
    @JsonProperty("OperatorNote")
    private String operatorNote;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PlaceHolder.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
 * 占位费信息
 * @author zhibing.pu
 * @Date 2025/1/26 9:29
 */
@Data
public class PlaceHolder {
    /**
     * 免费时长
     */
    @NotNull
    @JsonProperty("FreeTime")
    private Integer freeTime;
    /**
     * 嘴阀占位费
     */
    @NotNull
    @JsonProperty("MaxFee")
    private BigDecimal maxFee;
    /**
     * 生效开始时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    @JsonProperty("EffectStartTime")
    private String effectStartTime;
    /**
     * 生效结束时间
     */
    @NotNull
    @JsonProperty("EffectEndTime")
    private String effectEndTime;
    /**
     * 占位费价格
     */
    @NotNull
    @JsonProperty("PlaceHolderPrices")
    private List<PlaceHolderPrice> placeHolderPrices;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PlaceHolderPrice.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 占位费价格
 * @author zhibing.pu
 * @Date 2025/1/26 9:33
 */
@Data
public class PlaceHolderPrice {
    /**
     * 开始时段
     * HH:mm
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 结束时段
     * HH:mm
     */
    @NotNull
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 单价
     */
    @NotNull
    @JsonProperty("Price")
    private BigDecimal price;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/PolicyInfo.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 计费信息
 * @author zhibing.pu
 * @Date 2025/1/21 16:10
 */
@Data
public class PolicyInfo {
    /**
     * 时段起始时间点
     * HHmmss
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 时段电费
     */
    @NotNull
    @JsonProperty("ElecPrice")
    private BigDecimal elecPrice;
    /**
     * 时段服务费
     */
    @NotNull
    @JsonProperty("SevicePrice")
    private BigDecimal sevicePrice;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipAuth.java
New file
@@ -0,0 +1,27 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求设备认证
 * @author zhibing.pu
 * @Date 2025/1/22 16:15
 */
@Data
public class QueryEquipAuth {
    /**
     * 设备认证流水
     */
    @NotNull
    @JsonProperty("EquipAuthSeq")
    private String equipAuthSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipAuthResult.java
New file
@@ -0,0 +1,45 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求设备认证返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 16:16
 */
@Data
public class QueryEquipAuthResult {
    /**
     * 设备认证流水号
     */
    @NotNull
    @JsonProperty("EquipAuthSeq")
    private String equipAuthSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备尚未插枪
     * 2:设备检测失败
     * 3·99:自定义
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipBusinessPolicy.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 查询业务策略信息
 * @author zhibing.pu
 * @Date 2025/1/21 16:03
 */
@Data
public class QueryEquipBusinessPolicy {
    /**
     * 业务策略查询流水号
     * 格式”运营商ID+唯一编号“。27字符
     */
    @NotNull
    @JsonProperty("EquipBizSeq")
    private String equipBizSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipBusinessPolicyResult.java
New file
@@ -0,0 +1,58 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 查询业务策略信息结果
 * @author zhibing.pu
 * @Date 2025/1/21 16:05
 */
@Data
public class QueryEquipBusinessPolicyResult {
    /**
     * 业务策略查询流水号
     */
    @NotNull
    @JsonProperty("EquipBizSeq")
    private String equipBizSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:此充电桩业务策略不存在
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
    /**
     * 时段数N
     * 0`32
     */
    @NotNull
    @JsonProperty("SumPeriod")
    private Integer sumPeriod;
    /**
     * 计策信息
     */
    @NotNull
    @JsonProperty("PolicyInfos")
    private List<PolicyInfo> policyInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipChargeStatus.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * 查询充电状态
 * @author zhibing.pu
 * @Date 2025/1/21 16:17
 */
@Data
public class QueryEquipChargeStatus {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 抢号
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 车辆识别码
     */
    @Null
    @JsonProperty("VIN")
    private String VIN;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryEquipChargeStatusResult.java
New file
@@ -0,0 +1,150 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
import java.util.List;
/**
 * 查询充电状态结果
 * @author zhibing.pu
 * @Date 2025/1/21 15:58
 */
@Data
public class QueryEquipChargeStatusResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    @JsonProperty("StartChargeSeqStat")
    private Integer startChargeSeqStat;
    /**
     * 充电设备接口编号
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 充电设备接口状态
     * 1:空闲
     * 2:占用(未充电)
     * 3:占用(充电中)
     * 4:占用(预约锁定)
     * 255:故障
     */
    @NotNull
    @JsonProperty("ConnectorStatus")
    private Integer connectorStatus;
    /**
     * A相电流
     */
    @NotNull
    @JsonProperty("CurrentA")
    private BigDecimal currentA;
    /**
     * B相电流
     */
    @Null
    @JsonProperty("CurrentB")
    private BigDecimal currentB;
    /**
     * C相电流
     */
    @Null
    @JsonProperty("CurrentC")
    private BigDecimal currentC;
    /**
     * A相电压
     */
    @NotNull
    @JsonProperty("VoltageA")
    private BigDecimal voltageA;
    /**
     * B相电压
     */
    @Null
    @JsonProperty("VoltageB")
    private BigDecimal voltageB;
    /**
     * C相电压
     */
    @Null
    @JsonProperty("VoltageC")
    private BigDecimal voltageC;
    /**
     * 电池剩余电量
     */
    @NotNull
    @JsonProperty("Soc")
    private BigDecimal soc;
    /**
     * 开始充电时间
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 本次采样时间
     */
    @NotNull
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 累计充电量
     */
    @NotNull
    @JsonProperty("TotalPower")
    private BigDecimal totalPower;
    /**
     * 累计电费
     */
    @Null
    @JsonProperty("ElecMoney")
    private BigDecimal elecMoney;
    /**
     * 累计服务费
     */
    @Null
    @JsonProperty("SeviceMoney")
    private BigDecimal seviceMoney;
    /**
     * 累计总金额
     */
    @Null
    @JsonProperty("TotalMoney")
    private BigDecimal totalMoney;
    /**
     * 时段数N
     * 0`32
     */
    @Null
    @JsonProperty("SumPeriod")
    private Integer sumPeriod;
    /**
     * 充电明细信息
     */
    @Null
    @JsonProperty("ChargeDetails")
    private List<ChargeDetail> chargeDetails;
    /**
     * 车辆识别码
     */
    @Null
    @JsonProperty("VIN")
    private String VIN;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStartCharge.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
/**
 * 请求启动充电
 * @author zhibing.pu
 * @Date 2025/1/22 16:59
 */
@Data
public class QueryStartCharge {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 二维码其他信息
     */
    @NotNull
    @JsonProperty("QRCode")
    private String QRCode;
    /**
     * 充电余额
     */
    @NotNull
    @JsonProperty("ChargingAmt")
    private BigDecimal chargingAmt;
    /**
     * 充电车牌号
     */
    @Null
    @JsonProperty("PlateNum")
    private String plateNum;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStartChargeResult.java
New file
@@ -0,0 +1,56 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求启动充电返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 17:02
 */
@Data
public class QueryStartChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    @JsonProperty("StartChargeSeqStat")
    private Integer startChargeSeqStat;
    /**
     * 充电设别接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3`9:自定义
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStats.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 查询统计信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:11
 */
@Data
public class QueryStationStats {
    /**
     * 充电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 统计开始时间
     * yyyy-MM-dd
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 统计结束时间
     * yyyy-MM-dd
     */
    @NotNull
    @JsonProperty("EndTime")
    private String endTime;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatsResult.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 查询统计信息结果
 * @author zhibing.pu
 * @Date 2025/1/21 15:16
 */
@Data
public class QueryStationStatsResult {
    /**
     * 充电站统计信息
     */
    @NotNull
    @JsonProperty("StationStats")
    private StationStatsInfo stationStats;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatus.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 设备接口状态查询
 * @author zhibing.pu
 * @Date 2025/1/21 15:01
 */
@Data
public class QueryStationStatus {
    /**
     * 充电站ID列表
     * 数组长度不超过50
     */
    @NotNull
    @JsonProperty("StationIDs")
    private List<String> stationIDs;
    /**
     * 运营商服务平台ID,字符9位
     * 数组长度不超过50
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationStatusResult.java
New file
@@ -0,0 +1,25 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
 * 设备接口状态查询返回结果
 * @author zhibing.pu
 * @Date 2025/1/21 15:04
 */
@Data
public class QueryStationStatusResult {
    /**
     * 结果总数
     */
    @JsonProperty("Total")
    private Integer total;
    /**
     * 设备接口状态列表
     */
    @JsonProperty("StationStatusInfos")
    private List<StationStatusInfo> stationStatusInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationsInfo.java
New file
@@ -0,0 +1,49 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.Null;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2025/1/21 14:41
 */
@Data
public class QueryStationsInfo {
    /**
     * 上次查询时间
     * yyyy-MM-dd HH:mm:ss
     */
    @Null
    @JsonProperty("LastQueryTime")
    private String lastQueryTime;
    /**
     * 查询页码
     * 默认1
     */
    @Null
    @JsonProperty("PageNo")
    private Integer pageNo;
    /**
     * 每页数量
     * 默认10
     */
    @Null
    @JsonProperty("PageSize")
    private Integer pageSize;
    /**
     * 运营商ID
     */
    @Null
    @JsonProperty("OperatorID")
    private String OperatorID;
    /**
     * 充电站ID列表
     */
    @Null
    @JsonProperty("StationIDs")
    private List<String> StationIDs;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStationsInfoResult.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 公共返回结果
 * @author zhibing.pu
 * @Date 2025/1/21 14:44
 */
@Data
public class QueryStationsInfoResult {
    /**
     * 当前页数
     */
    @NotNull
    @JsonProperty("PageNo")
    private Integer pageNo;
    /**
     * 页码总数
     */
    @NotNull
    @JsonProperty("PageCount")
    private Integer pageCount;
    /**
     * 总记录条数
     */
    @NotNull
    @JsonProperty("ItemSize")
    private Integer itemSize;
    /**
     * 充电站信息列表
     */
    @NotNull
    @JsonProperty("StationInfos")
    private List<StationInfo> stationInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStopCharge.java
New file
@@ -0,0 +1,27 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求停止充电
 * @author zhibing.pu
 * @Date 2025/1/22 19:56
 */
@Data
public class QueryStopCharge {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String connectorID;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryStopChargeResult.java
New file
@@ -0,0 +1,52 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求停止充电返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 19:58
 */
@Data
public class QueryStopChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    @JsonProperty("StartChargeSeq")
    private String startChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    @JsonProperty("StartChargeSeqStat")
    private Integer startChargeSeqStat;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3:此设备已停止充电
     * 4`9:自定义
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryToken.java
New file
@@ -0,0 +1,27 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 获取token
 * @author zhibing.pu
 * @Date 2025/1/23 17:13
 */
@Data
public class QueryToken {
    /**
     * 运营商标识
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 运营商秘钥
     */
    @NotNull
    @JsonProperty("OperatorSecret")
    private String operatorSecret;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/QueryTokenResult.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 获取token返回结果
 * @author zhibing.pu
 * @Date 2025/1/23 17:15
 */
@Data
public class QueryTokenResult {
    /**
     * 运营商标识
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 成功状态
     * 0:成功
     * 1:失败
     */
    @NotNull
    @JsonProperty("SuccStat")
    private Integer succStat;
    /**
     * 获取的凭证
     */
    @NotNull
    @JsonProperty("AccessToken")
    private String accessToken;
    /**
     * 凭证有效期,秒
     */
    @NotNull
    @JsonProperty("TokenAvailableTime")
    private Long tokenAvailableTime;
    /**
     * 失败原因
     * 0:无
     * 1:无此运营商
     * 2:秘钥错误
     * 3`9自定义
     */
    @NotNull
    @JsonProperty("FailReason")
    private Integer failReason;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationInfo.java
New file
@@ -0,0 +1,375 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电站信息
 * @author zhibing.pu
 * @Date 2025/1/21 11:54
 */
@Data
public class StationInfo {
    /**
     * 充电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 充电站唯一编码
     */
    @NotNull
    @JsonProperty("StationUniqueNumber")
    private String stationUniqueNumber;
    /**
     * 运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 设备所属方ID
     * 设备所属运营平台组织机构代码
     */
    @NotNull
    @JsonProperty("EquipmentOwnerID")
    private String equipmentOwnerID;
    /**
     * 充电站名称
     */
    @NotNull
    @JsonProperty("StationName")
    private String stationName;
    /**
     * 充电站国家代码
     */
    @NotNull
    @JsonProperty("CountryCode")
    private String countryCode;
    /**
     * 充电站省市辖区编码
     */
    @NotNull
    @JsonProperty("AreaCode")
    private String areaCode;
    /**
     * 充电站所在县以下行政区划代码
     */
    @NotNull
    @JsonProperty("AreaCodeCountryside")
    private String areaCodeCountryside;
    /**
     * 详细地址
     */
    @NotNull
    @JsonProperty("Address")
    private String address;
    /**
     * 站点电话
     */
    @Null
    @JsonProperty("StationTel")
    private String stationTel;
    /**
     * 站点电话
     */
    @NotNull
    @JsonProperty("ServiceTel")
    private String serviceTel;
    /**
     * 站点分类(1:充电站,2:换电站,3:充换电一体站)
     */
    @NotNull
    @JsonProperty("StationClassification")
    private Integer stationClassification;
    /**
     * 通用类型(1:通用,2:非通用)
     */
    @NotNull
    @JsonProperty("GeneralApplicationType")
    private Integer generalApplicationType;
    /**
     * 站点类型
     */
    @NotNull
    @JsonProperty("StationType")
    private Integer stationType;
    /**
     * 站点状态
     */
    @NotNull
    @JsonProperty("StationStatus")
    private Integer stationStatus;
    /**
     * 车位数量,0:未知
     */
    @NotNull
    @JsonProperty("ParkNums")
    private Integer parkNums;
    /**
     * 经度(保留6位小数)
     */
    @NotNull
    @JsonProperty("StationLng")
    private BigDecimal stationLng;
    /**
     * 纬度(保留6位小数)
     */
    @NotNull
    @JsonProperty("StationLat")
    private BigDecimal stationLat;
    /**
     * 站点引导
     */
    @Null
    @JsonProperty("SiteGuide")
    private String siteGuide;
    /**
     * 建设场所
     */
    @NotNull
    @JsonProperty("Construction")
    private Integer construction;
    /**
     * 站点照片
     * 字符串数组
     */
    @Null
    @JsonProperty("Pictures")
    private List<String> pictures;
    /**
     * 使用车型描述
     */
    @Null
    @JsonProperty("MatchCars")
    private String matchCars;
    /**
     * 服务车型描述
     */
    @Null
    @JsonProperty("SwapMatchCars")
    private List<String> swapMatchCars;
    /**
     * 车位楼层及数量描述
     */
    @Null
    @JsonProperty("ParkInfo")
    private String parkInfo;
    /**
     * 营业时间
     */
    @Null
    @JsonProperty("BusineHours")
    private String busineHours;
    /**
     * 7*24小时营业
     * 0:否
     * 1:是
     */
    @Null
    @JsonProperty("RoundTheClock")
    private Integer roundTheClock;
    /**
     * 停车费类型
     * 0:免费
     * 1:不免费
     * 2:限时免费停车
     * 3:充电限时减免
     * 255:参考场地实际收费标准
     */
    @Null
    @JsonProperty("ParkType")
    private Integer parkType;
    /**
     * 充电电费率描述
     */
    @Null
    @JsonProperty("ElectricityFee")
    private String electricityFee;
    /**
     * 服务费率描述
     */
    @Null
    @JsonProperty("ServiceFee")
    private String serviceFee;
    /**
     * 停车费率描述
     */
    @Null
    @JsonProperty("ParkFee")
    private String parkFee;
    /**
     * 支付方式:刷卡、线上、现金
     */
    @Null
    @JsonProperty("Payment")
    private String payment;
    /**
     * 是否支持预约
     */
    @Null
    @JsonProperty("SupportOrder")
    private Integer supportOrder;
    /**
     * 备注
     */
    @Null
    @JsonProperty("Remark")
    private String remark;
    /**
     * 电费类型
     * 1:商业用电
     * 2:普通工业用电
     * 3:大工业用电
     * 4:其他用电
     */
    @JsonProperty("ElectricityType")
    private Integer electricityType;
    /**
     * 报装类型,是否独立报装
     * 0:否
     * 1:是
     */
    @JsonProperty("BusinessExpandType")
    private Integer businessExpandType;
    /**
     * 报装电源容量
     */
    @JsonProperty("Capacity")
    private BigDecimal capacity;
    /**
     * 站点额定总功率
     */
    @JsonProperty("RatedPower")
    private BigDecimal ratedPower;
    /**
     * 峰谷分时
     * 0:否
     * 1:是
     */
    @JsonProperty("PeriodFee")
    private Integer periodFee;
    /**
     * 正式投运时间 yyyy-MM-dd
     */
    @JsonProperty("OfficialRunTime")
    private String officialRunTime;
    /**
     * 充换电站方位
     * 1:地面-停车场
     * 2:地面-路侧
     * 3:地下停车场
     * 4:立体式停车楼
     */
    @JsonProperty("StationOrientation")
    private Integer stationOrientation;
    /**
     * 充换电站建设面积
     */
    @JsonProperty("StationArea")
    private BigDecimal stationArea;
    /**
     * 充换电站人工值守
     * 0:无
     * 1:有
     */
    @JsonProperty("HavePerson")
    private Integer havePerson;
    /**
     * 视频监控配套情况
     * 0:无
     * 1:有
     */
    @JsonProperty("VideoMonitor")
    private Integer videoMonitor;
    /**
     * 周边配套设施
     * 1:卫生间
     * 2:便利店
     * 3:餐厅
     * 4:休息室
     * 5:雨棚
     */
    @JsonProperty("SupportingFacilities")
    private List<Integer> supportingFacilities;
    /**
     * 是否有小票机
     * 0:无
     * 1:有
     */
    @JsonProperty("PrinterFlag")
    private Integer printerFlag;
    /**
     * 是否有道闸
     * 0:无
     * 1:有
     */
    @JsonProperty("BarrierFlag")
    private Integer barrierFlag;
    /**
     * 是否有地锁
     * 0:无
     * 1:有
     */
    @JsonProperty("ParkingLockFlag")
    private Integer parkingLockFlag;
    /**
     * 充电设备信息列表
     */
    @NotNull
    @JsonProperty("EquipmentInfos")
    private List<EquipmentInfo> equipmentInfos;
    /**
     * 占位费描述
     */
    @Null
    @JsonProperty("OvertimeFee")
    private String overtimeFee;
    /**
     * 占位费信息
     */
    @Null
    @JsonProperty("PlaceHolder")
    private PlaceHolder placeHolder;
    /**
     * 设备所属方名称
     */
    @JsonProperty("EquipmentOwnerName")
    private String equipmentOwnerName;
    /**
     * 供电局用户编号
     */
    @JsonProperty("ResidentNo")
    private String residentNo;
    /**
     * 供电类型
     * 1:直供电
     * 2:转供电
     */
    @JsonProperty("SupplyType")
    private Integer supplyType;
    /**
     * 表号
     */
    @JsonProperty("WattHourMeterNo")
    private String wattHourMeterNo;
    /**
     * 外电功率
     */
    @JsonProperty("ForwardPower")
    private String forwardPower;
    /**
     * 充电站全省唯一备案号
     */
    @JsonProperty("RecordUniqueNo")
    private String recordUniqueNo;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatsInfo.java
New file
@@ -0,0 +1,99 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电站统计信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:17
 */
@Data
public class StationStatsInfo {
    /**
     * 充电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 设备所属方ID
     * 设备所属运营平台组织机构代码
     */
    @NotNull
    @JsonProperty("EquipmentOwnerID")
    private String equipmentOwnerID;
    /**
     * 运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 站点分类 1:充电站
     * 2:换电站
     * 3:充换电一体站
     */
    @NotNull
    @JsonProperty("StationClassification")
    private Integer stationClassification;
    /**
     * 统计的开始时间
     * yyyy-MM-dd
     */
    @NotNull
    @JsonProperty("StartTime")
    private String startTime;
    /**
     * 统计的结束时间
     * yyyy-MM-dd
     */
    @NotNull
    @JsonProperty("EndTime")
    private String endTime;
    /**
     * 充电站累计电量 kw/h
     */
    @NotNull
    @JsonProperty("StationElectricity")
    private BigDecimal stationElectricity;
    /**
     * 充换电站累计
     * 充电量
     */
    @NotNull
    @JsonProperty("StationTotalChargeEnergy")
    private BigDecimal stationTotalChargeEnergy;
    /**
     * 充换电站累计
     * 告警数量
     */
    @NotNull
    @JsonProperty("StationTotalWarningNum")
    private Integer stationTotalWarningNum;
    /**
     充换电站累计
     其他电量
     */
    @NotNull
    @JsonProperty("StationTotalOtherEnergy")
    private BigDecimal stationTotalOtherEnergy;
    /**
     充换电站累计
     充电次数
     */
    @NotNull
    @JsonProperty("StationTotalChargeNum")
    private Integer stationTotalChargeNum;
    /**
     * 充电设备统计信息列表
     */
    @NotNull
    @JsonProperty("EquipmentStatsInfos")
    private List<EquipmentStatsInfo> equipmentStatsInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatsInfoResult.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.jianguan.model;
import lombok.Data;
import java.util.List;
/**
 * 充电站统计信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:17
 */
@Data
public class StationStatsInfoResult {
    private List<StationStatsInfo> stationStatsInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/StationStatusInfo.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 充电站状态信息
 * @author zhibing.pu
 * @Date 2025/1/21 15:07
 */
@Data
public class StationStatusInfo {
    /**
     * 充电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String stationID;
    /**
     * 充电设备接口状态列表
     */
    @JsonProperty("ConnectorStatusInfos")
    private List<ConnectorStatusInfo> connectorStatusInfos;
    @JsonProperty("OperatorID")
    private String OperatorID;
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupChargeOrderInfo.java
New file
@@ -0,0 +1,145 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 推送充电订单信息
 * 此接口用于数据提供方向数据需求方推送充电订单信息;充电
 * 订单在充电结束时实时推送,同一订单只可推送一次,禁止重复推
 * 送;推送失败时将推送失败的数据按小时级频率重试推送,直到推
 * 送成功。
 */
@Data
public class SupChargeOrderInfo {
    /**
     * 充换电平台运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String OperatorID;
    /**
     * 充换电服务运营商ID,
     * 所属方为个人时填写
     * 999999999
     */
    @NotNull
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    /**
     * 充换电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String StationID;
    /**
     * 充电设备编码
     */
    @NotNull
    @JsonProperty("EquipmentID")
    private String EquipmentID;
    /**
     * 充电订单号
     * 格式“运营商ID+唯一
     * 编号”,不超过64个字
     * 符
     */
    @NotNull
    @JsonProperty("OrderNo")
    private String OrderNo;
    /**
     * 充电订单状态
     * 1、启动中
     * 2、充电中
     * 3、停止中
     * 4、充电完成
     * 5、订单挂起
     * 6、充电异常结束
     * 7、启动失败
     */
    @NotNull
    @JsonProperty("OrderStatus")
    private Integer OrderStatus;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String ConnectorID;
    /**
     * 设备接口分类
     * 1:车辆充电设备接口
     * 2:换电站内的电池箱
     * 充电设备接口
     */
    @NotNull
    @JsonProperty("EquipmentClassification")
    private Integer EquipmentClassification = 1;
    /**
     * 推送时间
     * yyyy-MM-dd HH:mm:ss ,充电设备推送给运
     */
    @NotNull
    @JsonProperty("PushTimeStamp")
    private String PushTimeStamp;
    /**
     * 开始充电时间
     */
    @NotNull
    @JsonProperty("StartTime")
    private String StartTime;
    /**
     * 本次采样时间
     */
    @NotNull
    @JsonProperty("EndTime")
    private String EndTime;
    /**
     * 累计充电量 小数点后4位
     */
    @NotNull
    @JsonProperty("TotalPower")
    private BigDecimal TotalPower;
    /**
     * 总电费
     */
    @NotNull
    @JsonProperty("TotalElecMoney")
    private BigDecimal TotalElecMoney;
    /**
     * 总服务费
     */
    @NotNull
    @JsonProperty("TotalServiceMoney")
    private BigDecimal TotalServiceMoney;
    /**
     * 累计总金额
     */
    @NotNull
    @JsonProperty("TotalMoney")
    private BigDecimal TotalMoney;
    /**
     * 充电结束原因
     * 0:用户手动停止充电
     * 1:客户归属地运营商平台停止充电
     * 2:BMS停止充电
     * 3:充电机设备故障
     * 4:连接器断开
     * 5~99: 自定义
     */
    @NotNull
    @JsonProperty("StopReason")
    private Integer StopReason;
    /**
     * 充电结束原因描
     * 述
     */
    @NotNull
    @JsonProperty("StopDesc")
    private String StopDesc;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupConnectorPowerInfo.java
New file
@@ -0,0 +1,25 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * 充电设备接口功率信息
 */
@Data
public class SupConnectorPowerInfo {
    @JsonProperty("ConnectorID")
    private String ConnectorID;
    @JsonProperty("EquipmentClassification")
    private Integer EquipmentClassification;
    @JsonProperty("DataTime")
    private String DataTime;
    @JsonProperty("ConnectorRealTimePower")
    private BigDecimal ConnectorRealTimePower;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupEquipChargeStatus.java
New file
@@ -0,0 +1,134 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 推送充电状态信息
 * 此接口用于数据提供方向数据需求方推送充电设备的充电状态
 * 开始充电实时推送一次、充电过程中50-60秒推送一
 * 次、充电结束实时推送一次
 */
@Data
public class SupEquipChargeStatus {
    /**
     * 充换电平台运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String OperatorID;
    /**
     * 充换电服务运营商ID,
     * 所属方为个人时填写
     * 999999999
     */
    @NotNull
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    /**
     * 充换电站ID
     */
    @NotNull
    @JsonProperty("StationID")
    private String StationID;
    /**
     * 充电设备编码
     */
    @NotNull
    @JsonProperty("EquipmentID")
    private String EquipmentID;
    /**
     * 充电订单号
     * 格式“运营商ID+唯一
     * 编号”,不超过64个字
     * 符
     */
    @NotNull
    @JsonProperty("OrderNo")
    private String OrderNo;
    /**
     * 充电订单状态
     * 1、启动中
     * 2、充电中
     * 3、停止中
     * 4、充电完成
     * 5、订单挂起
     * 6、充电异常结束
     * 7、启动失败
     */
    @NotNull
    @JsonProperty("OrderStatus")
    private Integer OrderStatus;
    /**
     * 充电设备接口编码
     */
    @NotNull
    @JsonProperty("ConnectorID")
    private String ConnectorID;
    /**
     * 设备接口分类
     * 1:车辆充电设备接口
     * 2:换电站内的电池箱
     * 充电设备接口
     */
    @NotNull
    @JsonProperty("EquipmentClassification")
    private Integer EquipmentClassification = 1;
    /**
     * 推送时间
     * yyyy-MM-dd HH:mm:ss ,充电设备推送给运
     */
    @NotNull
    @JsonProperty("PushTimeStamp")
    private String PushTimeStamp;
    /**
     * 充电设备接口状态 ConnectorStatus
     * 0:离网
     * 1:空闲
     * 2: 占用(未充电)
     * 3: 占用(充电中)
     * 4: 占用(预约锁定)
     * 255:故障
     */
    @NotNull
    @JsonProperty("ConnectorStatus")
    private Integer ConnectorStatus;
    /**
     * A相电流
     * 小数点后4
     * 位
     */
    @NotNull
    @JsonProperty("CurrentA")
    private BigDecimal CurrentA;
    /**
     * 电池剩余电量 小数点后1
     * 位
     */
    @NotNull
    @JsonProperty("SOC")
    private BigDecimal SOC;
    /**
     * 开始充电时间
     */
    @NotNull
    @JsonProperty("StartTime")
    private String StartTime;
    /**
     * 本次采样时间
     */
    @NotNull
    @JsonProperty("EndTime")
    private String EndTime;
    /**
     * 累计充电量 小数点后4位
     */
    @NotNull
    @JsonProperty("TotalPower")
    private BigDecimal TotalPower;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupEquipmentPowerInfo.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充电设备功率信息
 */
@Data
public class SupEquipmentPowerInfo {
    @JsonProperty("EquipmentID")
    private String EquipmentID;
    @JsonProperty("EquipmentClassification")
    private Integer EquipmentClassification;
    @JsonProperty("DataTime")
    private String DataTime;
    @JsonProperty("EquipRealTimePower")
    private BigDecimal EquipRealTimePower;
    @JsonProperty("ConnectorPowerInfos")
    private List<SupConnectorPowerInfo> ConnectorPowerInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationInfo.java
New file
@@ -0,0 +1,210 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.integration.drainage.SupSwapEquipmentInfo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
 * 充换电站信息
 */
@Data
public class SupStationInfo {
    // 充换电站ID
    @JsonProperty("StationID")
    private String StationID;
    // 充换电站唯一编码
    @JsonProperty("StationUniqueNumber")
    private String StationUniqueNumber;
    //平台运营商
    //ID
    @JsonProperty("OperatorID")
    private String OperatorID;
    //充换电服务
    //运营商ID
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    //充换电站名
    //称
    @JsonProperty("StationName")
    private String StationName;
    //充换电站国
    //家代码
    @JsonProperty("CountryCode")
    private String CountryCode;
    //充换电站省
    //市辖区编码
    @JsonProperty("AreaCode")
    private String AreaCode;
    //详细地址
    @JsonProperty("Address")
    private String Address;
    //充换电站所
    //在县以下行
    //政区划代码
    @JsonProperty("AreaCodeCountryside")
    private String AreaCodeCountryside;
    // 站点电话
    @JsonProperty("StationTel")
    private String StationTel;
    // 服务电话
    @JsonProperty("ServiceTel")
    private String ServiceTel;
    // 站点分类
    @JsonProperty("StationClassification")
    private Integer StationClassification;
    //通用类型
    @JsonProperty("GeneralApplicationType")
    private Integer GeneralApplicationType;
    //站点类型
    @JsonProperty("StationType")
    private Integer StationType;
    //站点状态
    @JsonProperty("StationStatus")
    private Integer StationStatus;
    //车位数量
    @JsonProperty("ParkNums")
    private Integer ParkNums;
    //经度
    @JsonProperty("StationLng")
    private BigDecimal StationLng;
    //纬度
    @JsonProperty("StationLat")
    private BigDecimal StationLat;
    //站点引导
    @JsonProperty("SiteGuide")
    private String SiteGuide;
    //建设场所
    @JsonProperty("Construction")
    private Integer Construction;
    //站点照片
    @JsonProperty("Pictures")
    private List<String> Pictures;
    //使用车型描
    //述
    @JsonProperty("MatchCars")
    private String MatchCars;
    //服务车型描
    //述
    @JsonProperty("SwapMatchCars")
    private List<String> SwapMatchCars;
    //车位楼层及
    //数量描述
    @JsonProperty("ParkInfo")
    private String ParkInfo;
    //营业时间
    @JsonProperty("BusineHours")
    private String BusineHours;
    //7*24小时营
    //业
    @JsonProperty("RoundTheClock")
    private Integer RoundTheClock;
    //停车费类型
    @JsonProperty("ParkType")
    private Integer ParkType;
    //停车费描述
    @JsonProperty("ParkFee")
    private String ParkFee;
    //支付方式
    @JsonProperty("Payment")
    private String Payment;
    //是否支持预
    //约
    @JsonProperty("SupportOrder")
    private Integer SupportOrder;
    //备注
    @JsonProperty("Remark")
    private String Remark;
    //电费类型
    @JsonProperty("ElectricityType")
    private Integer ElectricityType;
    //报装类型
    @JsonProperty("BusinessExpandType")
    private Integer BusinessExpandType;
    //报装电源容
    //量
    @JsonProperty("Capacity")
    private BigDecimal Capacity;
    //站点额定总
    //功率
    @JsonProperty("RatedPower")
    private BigDecimal RatedPower;
    //峰谷分时
    @JsonProperty("PeriodFee")
    private Integer PeriodFee;
    //正式投运时
    //间
    @JsonProperty("OfficialRunTime")
    private String OfficialRunTime;
    //充换电站方
    //位
    @JsonProperty("StationOrientation")
    private Integer StationOrientation;
    //充换电站建
    //设面积
    @JsonProperty("StationArea")
    private BigDecimal StationArea;
    //充换电站人
    //工值守
    @JsonProperty("HavePerson")
    private Integer HavePerson;
    //视频监控配
    //套情况
    @JsonProperty("VideoMonitor")
    private Integer VideoMonitor;
    //周边配套设
    // 施
    @JsonProperty("SupportingFacilities")
    private List<Integer> SupportingFacilities;
    //是否有小票
    //机
    @JsonProperty("PrinterFlag")
    private Integer PrinterFlag;
    //是否有道闸
    @JsonProperty("BarrierFlag")
    private Integer BarrierFlag;
    //是否有地锁
    @JsonProperty("ParkingLockFlag")
    private Integer ParkingLockFlag;
    //充电设备信
    //息列表
    @JsonProperty("EquipmentInfos")
    private List<EquipmentInfo> EquipmentInfos;
    //换电设备信
    //息
    @JsonProperty("SwapEquipmentInfos")
    private List<SupSwapEquipmentInfo> SwapEquipmentInfos;
    //充电电费描
    //述
    @JsonProperty("ElectricityFee")
    private String ElectricityFee;
    //设备所属方
    //名称
    @JsonProperty("EquipmentOwnerName")
    private String EquipmentOwnerName;
    //供电局用户
    //编号
    @JsonProperty("ResidentNo")
    private String ResidentNo;
    //供电类型
    @JsonProperty("SupplyType")
    private Integer SupplyType;
    //表号
    @JsonProperty("WattHourMeterNo")
    private String WattHourMeterNo;
    //外电功率
    @JsonProperty("ForwardPower")
    private BigDecimal ForwardPower;
    //服务费描述
    @JsonProperty("ServiceFee")
    private String ServiceFee;
    //充电站全省
    //唯一备案号
    @JsonProperty("RecordUniqueNo")
    private String RecordUniqueNo;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationInfoResult.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
 * 充换电站信息
 */
@Data
public class SupStationInfoResult {
    @JsonProperty("SupStationInfo")
    private StationInfo SupStationInfo;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationPowerInfo.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
 * 推送充换电站实时功率
 */
@Data
public class SupStationPowerInfo {
    @NotNull
    @JsonProperty("OperatorID")
    private String OperatorID;
    @JsonProperty("EquipmentOwnerID")
    private String EquipmentOwnerID;
    @JsonProperty("StationID")
    private String StationID;
    @JsonProperty("StationClassification")
    private Integer StationClassification;
    @JsonProperty("DataTime")
    private String DataTime;
    @JsonProperty("StationRealTimePower")
    private BigDecimal StationRealTimePower;
    @JsonProperty("EquipmentPowerInfos")
    private List<SupEquipmentPowerInfo> EquipmentPowerInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SupStationPowerInfoResult.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * 推送充换电站实时功率
 */
@Data
public class SupStationPowerInfoResult implements Serializable {
    @JsonProperty("SupStationPowerInfos")
    private List<SupStationPowerInfo> SupStationPowerInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfo.java
New file
@@ -0,0 +1,22 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2025/2/19 9:36
 */
@Data
public class SuperviseQueryOperatorInfo {
    /**
     * 查询页码
     */
    @JsonProperty("PageNo")
    private Integer pageNo;
    /**
     * 每页数量
     */
    @JsonProperty("PageSize")
    private Integer pageSize;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfoResult.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * @author zhibing.pu
 * @Date 2025/2/19 9:39
 */
@Data
public class SuperviseQueryOperatorInfoResult {
    /**
     * 运营商ID
     */
    @NotNull
    @JsonProperty("OperatorID")
    private String operatorID;
    /**
     * 运营商统一社会信用代码
     */
    @NotNull
    @JsonProperty("OperatorUSCID")
    private String operatorUSCID;
    /**
     * 运营商名称
     */
    @NotNull
    @JsonProperty("OperatorName")
    private String operatorName;
    /**
     * 运营商电话1
     */
    @NotNull
    @JsonProperty("OperatorTel1")
    private String operatorTel1;
    /**
     * 运营商电话2
     */
    @Null
    @JsonProperty("OperatorTel2")
    private String operatorTel2;
    /**
     * 运营商注册地址
     */
    @Null
    @JsonProperty("OperatorRegAddress")
    private String operatorRegAddress;
    /**
     * 备注信息
     */
    @Null
    @JsonProperty("OperatorNote")
    private String operatorNote;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/model/SuperviseQueryOperatorInfoResultPage.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.jianguan.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2025/2/19 9:39
 */
@Data
public class SuperviseQueryOperatorInfoResultPage {
    /**
     * 查询页码
     */
    @JsonProperty("PageNo")
    private Integer pageNo;
    /**
     * 每页数量
     */
    @JsonProperty("PageCount")
    private Integer pageCount;
    /**
     * 每页数量
     */
    @JsonProperty("ItemSize")
    private Integer itemSize;
    /**
     * 数据
     */
    @JsonProperty("OperatorInfos")
    private List<SuperviseQueryOperatorInfoResult> operatorInfos;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/BaseMessage.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.jianguan.rocket.base;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * 消息实体,所有消息都需要继承此类
 */
@Data
public abstract class BaseMessage {
    /**
     * 业务键,用于RocketMQ控制台查看消费情况
     */
    protected String key;
    /**
     * 发送消息来源,用于排查问题
     */
    protected String source = "";
    /**
     * 发送时间
     */
    protected LocalDateTime sendTime = LocalDateTime.now();
    /**
     * 重试次数,用于判断重试次数,超过重试次数发送异常警告
     */
    protected Integer retryTimes = 0;
    /**
     * 服务id
     */
    protected String serviceId;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/ChargingOrderMessage.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.jianguan.rocket.base;
import lombok.Data;
/**
 * 充电桩计费模型请求
 **/
@Data
public class ChargingOrderMessage extends BaseMessage {
    private String orderNumber;// 订单编号
    private String soc;// soc
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/GunStatusMessage.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.jianguan.rocket.base;
import lombok.Data;
/**
 * 充电桩计费模型请求
 **/
@Data
public class GunStatusMessage extends BaseMessage {
    private String fullNumber;// 枪完整编码
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/base/JianGuanMessage.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.jianguan.rocket.base;
import com.ruoyi.jianguan.model.ConnectorStatusInfo;
import com.ruoyi.jianguan.model.SupChargeOrderInfo;
import com.ruoyi.jianguan.model.SupEquipChargeStatus;
import lombok.Data;
@Data
public class JianGuanMessage extends BaseMessage {
    // 充电设备状态message
    private GunStatusMessage gunStatusMessage;
    // 推送充电订单状态/充电订单信息message
    private ChargingOrderMessage orderMessage;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/EnvironmentIsolationConfig.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.jianguan.rocket.configuration;
import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.StringUtils;
public class EnvironmentIsolationConfig implements BeanPostProcessor {
    private RocketEnhanceProperties rocketEnhanceProperties;
    public EnvironmentIsolationConfig(RocketEnhanceProperties rocketEnhanceProperties) {
        this.rocketEnhanceProperties = rocketEnhanceProperties;
    }
    /**
     * 在装载Bean之前实现参数修改
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DefaultRocketMQListenerContainer) {
            DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
            if (rocketEnhanceProperties.isEnabledIsolation() && StringUtils.hasText(rocketEnhanceProperties.getEnvironment())) {
                container.setTopic(String.join("_", container.getTopic(), rocketEnhanceProperties.getEnvironment()));
            }
            return container;
        }
        return bean;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketEnhanceProperties.java
New file
@@ -0,0 +1,13 @@
package com.ruoyi.jianguan.rocket.configuration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "rocketmq.enhance")
@Data
public class RocketEnhanceProperties {
    private boolean enabledIsolation;
    private String environment;
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketMQEnhanceAutoConfiguration.java
New file
@@ -0,0 +1,61 @@
package com.ruoyi.jianguan.rocket.configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.ruoyi.jianguan.rocket.util.RocketMQEnhanceTemplate;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import java.util.List;
@Configuration
@EnableConfigurationProperties(RocketEnhanceProperties.class)
public class RocketMQEnhanceAutoConfiguration {
    /**
     * 注入增强的RocketMQEnhanceTemplate
     */
    @Bean
    public RocketMQEnhanceTemplate rocketMQEnhanceTemplate(RocketMQTemplate rocketMQTemplate){
        return new RocketMQEnhanceTemplate(rocketMQTemplate);
    }
    /**
     * 解决RocketMQ Jackson不支持Java时间类型配置
     * 源码参考:{@link org.apache.rocketmq.spring.autoconfigure}
     */
    @Bean
    @Primary
    public RocketMQMessageConverter enhanceRocketMQMessageConverter(){
        RocketMQMessageConverter converter = new RocketMQMessageConverter();
        CompositeMessageConverter compositeMessageConverter = (CompositeMessageConverter) converter.getMessageConverter();
        List<MessageConverter> messageConverterList = compositeMessageConverter.getConverters();
        for (MessageConverter messageConverter : messageConverterList) {
            if(messageConverter instanceof MappingJackson2MessageConverter){
                MappingJackson2MessageConverter jackson2MessageConverter = (MappingJackson2MessageConverter) messageConverter;
                ObjectMapper objectMapper = jackson2MessageConverter.getObjectMapper();
                objectMapper.registerModules(new JavaTimeModule());
            }
        }
        return converter;
    }
    /**
     * 环境隔离配置
     */
    @Bean
    @ConditionalOnProperty(name="rocketmq.enhance.enabledIsolation", havingValue="true")
    public EnvironmentIsolationConfig environmentSetup(RocketEnhanceProperties rocketEnhanceProperties){
        return new EnvironmentIsolationConfig(rocketEnhanceProperties);
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/configuration/RocketMQMessageConverter.java
New file
@@ -0,0 +1,46 @@
package com.ruoyi.jianguan.rocket.configuration;
import org.springframework.messaging.converter.*;
import org.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
public class RocketMQMessageConverter {
    private static final boolean JACKSON_PRESENT;
    private static final boolean FASTJSON_PRESENT;
    static {
        ClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader();
        JACKSON_PRESENT = ClassUtils.isPresent("com.fasterxml.jackson,databind.ObjectMapper", classLoader)
                && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
        FASTJSON_PRESENT = ClassUtils.isPresent("com.alibaba.fastjson.JSON", classLoader)
                && ClassUtils.isPresent("com.alibaba.fastjson.support.config.FastJsonConfig", classLoader);
    }
    private final CompositeMessageConverter messageConverter;
    public RocketMQMessageConverter(){
        List<MessageConverter> messageConverters = new ArrayList<>();
        ByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter();
        byteArrayMessageConverter.setContentTypeResolver(null);
        messageConverters.add(byteArrayMessageConverter);
        messageConverters.add(new StringMessageConverter());
        if (JACKSON_PRESENT) {
            messageConverters.add(new MappingJackson2MessageConverter());
        }
        if(FASTJSON_PRESENT) {
            try {
                messageConverters.add(
                        (MessageConverter) ClassUtils.forName(
                                "com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter", ClassUtils.getDefaultClassLoader()).newInstance());
            } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) {
            }
        }
        messageConverter = new CompositeMessageConverter(messageConverters);
    }
    public MessageConverter getMessageConverter(){ return messageConverter; }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/constant/EnhanceMessageConstant.java
New file
@@ -0,0 +1,14 @@
package com.ruoyi.jianguan.rocket.constant;
public class EnhanceMessageConstant {
    /**
     * 延时等级
     */
    public static final int FIVE_SECOND=5000;
    /**
     * 消息前缀
     */
    public static final String RETRY_PREFIX="retry_";
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/produce/ChargingMessageListener.java
New file
@@ -0,0 +1,262 @@
package com.ruoyi.jianguan.rocket.produce;
import com.ruoyi.chargingPile.api.feignClient.AccountingStrategyDetailClient;
import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.integration.api.model.*;
import com.ruoyi.jianguan.model.ConnectorStatusInfo;
import com.ruoyi.jianguan.model.SupChargeOrderInfo;
import com.ruoyi.jianguan.model.SupEquipChargeStatus;
import com.ruoyi.jianguan.rocket.base.ChargingOrderMessage;
import com.ruoyi.jianguan.rocket.base.GunStatusMessage;
import com.ruoyi.jianguan.rocket.base.JianGuanMessage;
import com.ruoyi.jianguan.rocket.util.EnhanceMessageHandler;
import com.ruoyi.jianguan.util.SendTagConstant;
import com.ruoyi.jianguan.util.TCECSuperviseUtil;
import com.ruoyi.order.api.feignClient.ChargingOrderClient;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.other.api.domain.Operator;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.Date;
@Slf4j
@Component
@RocketMQMessageListener(
        messageModel = MessageModel.CLUSTERING,
        consumerGroup = "jianguan_message",
        topic = "jianguan_message",
        selectorExpression = "jianguan_message",
        consumeThreadMax = 64 //默认是64个线程并发消息,配置 consumeThreadMax 参数指定并发消费线程数,避免太大导致资源不够
)
public class ChargingMessageListener extends EnhanceMessageHandler<JianGuanMessage> implements RocketMQListener<JianGuanMessage> {
    @Resource
    private ChargingOrderClient chargingOrderClient;
    @Resource
    private AccountingStrategyDetailClient accountingStrategyDetailClient;
    @Resource
    private ChargingPileClient chargingPileClient;
    @Resource
    private ChargingGunClient chargingGunClient;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private TCECSuperviseUtil tcecSuperviseUtil;
    private final static String operatorId = "906171535";
    @StreamListener("input")
    @Override
    protected void handleMessage(JianGuanMessage message) throws Exception {
        log.info("rocket收到的消息内容:{}", message);
        String serviceId = message.getServiceId();
        if (!StringUtils.hasLength(serviceId)) {
            return;
        }
        log.info("rocket收到的消息内容:{}   {}", serviceId, message);
        switch (serviceId) {
            case SendTagConstant.GUN_STATUS:
                GunStatusMessage gunStatusMessage = message.getGunStatusMessage();
                log.info("推送充电设备接口状态:{}", gunStatusMessage);
                TChargingGun chargingGun = chargingGunClient.getChargingGunByFullNumber(gunStatusMessage.getFullNumber()).getData();
                if (chargingGun!=null){
                    ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
                    connectorStatusInfo.setOperatorID(operatorId);
                    connectorStatusInfo.setEquipmentOwnerID(operatorId);
                    connectorStatusInfo.setStationID(String.valueOf(chargingGun.getSiteId()));
                    connectorStatusInfo.setEquipmentID(String.valueOf(chargingGun.getChargingPileId()));
                    connectorStatusInfo.setConnectorID(chargingGun.getFullNumber());
                    if (chargingGun.getEquipmentClassification()!=null){
                        connectorStatusInfo.setEquipmentClassification(chargingGun.getEquipmentClassification());
                    }else {
                        connectorStatusInfo.setEquipmentClassification(1);
                    }
                    switch (chargingGun.getStatus()){
                        case 1:
                            connectorStatusInfo.setStatus(0);
                            break;
                        case 2:
                            connectorStatusInfo.setStatus(1);
                            break;
                        case 3:
                            connectorStatusInfo.setStatus(2);
                            break;
                        case 4:
                            connectorStatusInfo.setStatus(3);
                            break;
                        case 5:
                            connectorStatusInfo.setStatus(3);
                            break;
                        case 6:
                            connectorStatusInfo.setStatus(4);
                            break;
                        case 7:
                            connectorStatusInfo.setStatus(255);
                            break;
                    }
                    connectorStatusInfo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    tcecSuperviseUtil.notificationStationStatus(new Operator(), connectorStatusInfo);
                }
                break;
            case SendTagConstant.ORDER_INFO:
                ChargingOrderMessage orderInfoMessage = message.getOrderMessage();
                log.info("推送充电订单信息:{}", orderInfoMessage);
                TChargingOrder chargingOrder1 = chargingOrderClient.getOrderByCode(orderInfoMessage.getOrderNumber()).getData();
                SupChargeOrderInfo supChargeOrderInfo = new SupChargeOrderInfo();
                supChargeOrderInfo.setOperatorID(operatorId);
                supChargeOrderInfo.setEquipmentOwnerID(operatorId);
                supChargeOrderInfo.setStationID(String.valueOf(chargingOrder1.getSiteId()));
                supChargeOrderInfo.setEquipmentID(String.valueOf(chargingOrder1.getChargingPileId()));
                supChargeOrderInfo.setOrderNo(operatorId+chargingOrder1.getCode());
                TChargingGun chargingGun1 = chargingGunClient.getChargingGunById(chargingOrder1.getChargingGunId()).getData();
                supChargeOrderInfo.setConnectorID(chargingGun1.getFullNumber());
                supChargeOrderInfo.setEquipmentClassification(1);
                supChargeOrderInfo.setPushTimeStamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                supChargeOrderInfo.setStartTime(chargingOrder1.getStartTime() != null ? chargingOrder1.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
                supChargeOrderInfo.setEndTime(chargingOrder1.getEndTime() != null ? chargingOrder1.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
                supChargeOrderInfo.setTotalPower(chargingOrder1.getElectrovalence());
                supChargeOrderInfo.setTotalElecMoney(chargingOrder1.getElectrovalence());
                supChargeOrderInfo.setTotalServiceMoney(chargingOrder1.getServiceCharge());
                supChargeOrderInfo.setTotalMoney(chargingOrder1.getOrderAmount());
                switch (chargingOrder1.getEndMode()){
                    case 0:
                        supChargeOrderInfo.setStopReason(5);
                        supChargeOrderInfo.setStopDesc("异常终止");
                        break;
                    case 1:
                        supChargeOrderInfo.setStopReason(0);
                        supChargeOrderInfo.setStopDesc("用户手动停止充电");
                        break;
                    case 2:
                        supChargeOrderInfo.setStopReason(1);
                        supChargeOrderInfo.setStopDesc("客户归属地运营商平台停止充电");
                        break;
                    case 3:
                        supChargeOrderInfo.setStopReason(1);
                        supChargeOrderInfo.setStopDesc("费用不足中止");
                        break;
                }
                tcecSuperviseUtil.notificationChargeOrderInfo(new Operator(), supChargeOrderInfo);
                break;
            case SendTagConstant.ORDER_STATUS:
                ChargingOrderMessage orderStatusMessage = message.getOrderMessage();
                log.info("推送充电订单状态:{}", orderStatusMessage);
                TChargingOrder chargingOrder2 = chargingOrderClient.getOrderByCode(orderStatusMessage.getOrderNumber()).getData();
                SupEquipChargeStatus supEquipChargeStatus = new SupEquipChargeStatus();
                supEquipChargeStatus.setOperatorID(operatorId);
                supEquipChargeStatus.setEquipmentOwnerID(operatorId);
                supEquipChargeStatus.setStationID(String.valueOf(chargingOrder2.getSiteId()));
                supEquipChargeStatus.setEquipmentID(String.valueOf(chargingOrder2.getChargingPileId()));
                supEquipChargeStatus.setOrderNo(operatorId+chargingOrder2.getCode());
                switch (chargingOrder2.getStatus()){
                    case 2:
                        supEquipChargeStatus.setConnectorStatus(1);
                        break;
                    case 3:
                        supEquipChargeStatus.setConnectorStatus(2);
                        break;
                    case 4:
                        supEquipChargeStatus.setConnectorStatus(3);
                        break;
                    case 5:
                        supEquipChargeStatus.setConnectorStatus(4);
                        break;
                }
                TChargingGun chargingGun2 = chargingGunClient.getChargingGunById(chargingOrder2.getChargingGunId()).getData();
                supEquipChargeStatus.setConnectorID(chargingGun2.getFullNumber());
                supEquipChargeStatus.setEquipmentClassification(1);
                supEquipChargeStatus.setPushTimeStamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                switch (chargingGun2.getStatus()){
                    case 1:
                        supEquipChargeStatus.setConnectorStatus(0);
                        break;
                    case 2:
                        supEquipChargeStatus.setConnectorStatus(1);
                        break;
                    case 3:
                        supEquipChargeStatus.setConnectorStatus(2);
                        break;
                    case 4:
                        supEquipChargeStatus.setConnectorStatus(3);
                        break;
                    case 5:
                        supEquipChargeStatus.setConnectorStatus(3);
                        break;
                    case 6:
                        supEquipChargeStatus.setConnectorStatus(4);
                        break;
                    case 7:
                        supEquipChargeStatus.setConnectorStatus(255);
                        break;
                }
                supEquipChargeStatus.setCurrentA(chargingOrder2.getCurrent());
                supEquipChargeStatus.setSOC(StringUtils.hasLength(orderStatusMessage.getSoc())?new BigDecimal(orderStatusMessage.getSoc()):new BigDecimal("1"));
                supEquipChargeStatus.setStartTime(chargingOrder2.getStartTime() != null ? chargingOrder2.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
                supEquipChargeStatus.setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                supEquipChargeStatus.setTotalPower(chargingOrder2.getElectrovalence());
                tcecSuperviseUtil.notificationSupEquipChargeStatus(new Operator(), supEquipChargeStatus);
                break;
        }
    }
    @Override
    protected void handleMaxRetriesExceeded(JianGuanMessage message) {
        // 当超过指定重试次数消息时此处方法会被调用
        // 生产中可以进行回退或其他业务操作
        log.error("消息消费失败,请执行后续处理");
    }
    /**
     * 是否执行重试机制
     */
    @Override
    protected boolean isRetry() {
        return true;
    }
    @Override
    protected boolean throwException() {
        // 是否抛出异常,false搭配retry自行处理异常
        return false;
    }
    /**
     * 若需要处理消息过滤,在父级中进行统一处理,或者在此处实现之后,自行处理
     *
     * @param message 待处理消息
     * @return true: 本次消息被过滤,false:不过滤
     */
    @Override
    protected boolean filter(JianGuanMessage message) {
        // 此处可做消息过滤
        return false;
    }
    /**
     * 监听消费消息,不需要执行业务处理,委派给父类做基础操作,父类做完基础操作后会调用子类的实际处理类型
     */
    @Override
    public void onMessage(JianGuanMessage message) {
        super.dispatchMessage(message);
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/util/EnhanceMessageHandler.java
New file
@@ -0,0 +1,151 @@
package com.ruoyi.jianguan.rocket.util;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.jianguan.rocket.base.BaseMessage;
import com.ruoyi.jianguan.rocket.constant.EnhanceMessageConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import javax.annotation.Resource;
@Slf4j
public abstract class EnhanceMessageHandler<T extends BaseMessage> {
    /**
     * 默认重试次数
     */
    private static final int MAX_RETRY_TIMES = 3;
    /**
     * 延时等级
     */
    private static final int DELAY_LEVEL = EnhanceMessageConstant.FIVE_SECOND;
    @Resource
    private RocketMQEnhanceTemplate rocketMQEnhanceTemplate;
    /**
     * 消息处理
     *
     * @param message 待处理消息
     * @throws Exception 消费异常
     */
    protected abstract void handleMessage(T message) throws Exception;
    /**
     * 超过重试次数消息,需要启用isRetry
     *
     * @param message 待处理消息
     */
    protected abstract void handleMaxRetriesExceeded(T message);
    /**
     * 是否需要根据业务规则过滤消息,去重逻辑可以在此处处理
     * @param message 待处理消息
     * @return true: 本次消息被过滤,false:不过滤
     */
    protected boolean filter(T message) {
        return false;
    }
    /**
     * 是否异常时重复发送
     *
     * @return true: 消息重试,false:不重试
     */
    protected abstract boolean isRetry();
    /**
     * 消费异常时是否抛出异常
     * 返回true,则由rocketmq机制自动重试
     * false:消费异常(如果没有开启重试则消息会被自动ack)
     */
    protected abstract boolean throwException();
    /**
     * 最大重试次数
     *
     * @return 最大重试次数,默认5次
     */
    protected int getMaxRetryTimes() {
        return MAX_RETRY_TIMES;
    }
    /**
     * isRetry开启时,重新入队延迟时间
     * @return -1:立即入队重试
     */
    protected int getDelayLevel() {
        return DELAY_LEVEL;
    }
    /**
     * 使用模板模式构建消息消费框架,可自由扩展或删减
     */
    public void dispatchMessage(T message) {
        // 基础日志记录被父类处理了
        log.info("消费者收到消息[{}]", JSONObject.toJSON(message));
        if (filter(message)) {
            log.info("消息id{}不满足消费条件,已过滤。",message.getKey());
            return;
        }
        // 超过最大重试次数时调用子类方法处理
        if (message.getRetryTimes() > getMaxRetryTimes()) {
            handleMaxRetriesExceeded(message);
            return;
        }
        try {
            long now = System.currentTimeMillis();
            handleMessage(message);
            long costTime = System.currentTimeMillis() - now;
            log.info("消息{}消费成功,耗时[{}ms]", message.getKey(),costTime);
        } catch (Exception e) {
            log.error("消息{}消费异常", message.getKey(),e);
            // 是捕获异常还是抛出,由子类决定
            if (throwException()) {
                //抛出异常,由DefaultMessageListenerConcurrently类处理
                throw new RuntimeException(e);
            }
            //此时如果不开启重试机制,则默认ACK了
            if (isRetry()) {
                handleRetry(message);
            }
        }
    }
    protected void handleRetry(T message) {
        // 获取子类RocketMQMessageListener注解拿到topic和tag
        RocketMQMessageListener annotation = this.getClass().getAnnotation(RocketMQMessageListener.class);
        if (annotation == null) {
            return;
        }
        //重新构建消息体
        String messageSource = message.getSource();
        if(!messageSource.startsWith(EnhanceMessageConstant.RETRY_PREFIX)){
            message.setSource(EnhanceMessageConstant.RETRY_PREFIX + messageSource);
        }
        message.setRetryTimes(message.getRetryTimes() + 1);
        SendResult sendResult;
        try {
            // 如果消息发送不成功,则再次重新发送,如果发送异常则抛出由MQ再次处理(异常时不走延迟消息)
            sendResult = rocketMQEnhanceTemplate.send(annotation.topic(), annotation.selectorExpression(), message, getDelayLevel());
        } catch (Exception ex) {
            // 此处捕获之后,相当于此条消息被消息完成然后重新发送新的消息
            //由生产者直接发送
            throw new RuntimeException(ex);
        }
        // 发送失败的处理就是不进行ACK,由RocketMQ重试
        if (sendResult.getSendStatus() != SendStatus.SEND_OK) {
            throw new RuntimeException("重试消息发送失败");
        }
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/rocket/util/RocketMQEnhanceTemplate.java
New file
@@ -0,0 +1,82 @@
package com.ruoyi.jianguan.rocket.util;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.jianguan.rocket.base.BaseMessage;
import com.ruoyi.jianguan.rocket.configuration.RocketEnhanceProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RocketMQEnhanceTemplate {
    private final RocketMQTemplate template;
    @Resource
    private RocketEnhanceProperties rocketEnhanceProperties;
    public RocketMQTemplate getTemplate() {
        return template;
    }
    /**
     * 根据系统上下文自动构建隔离后的topic
     * 构建目的地
     */
    public String buildDestination(String topic, String tag) {
        topic = reBuildTopic(topic);
        return topic + ":" + tag;
    }
    /**
     * 根据环境重新隔离topic
     * @param topic 原始topic
     */
    private String reBuildTopic(String topic) {
        if(rocketEnhanceProperties.isEnabledIsolation() && StringUtils.hasText(rocketEnhanceProperties.getEnvironment())){
            return topic +"_" + rocketEnhanceProperties.getEnvironment();
        }
        return topic;
    }
    /**
     * 发送同步消息
     */
    public <T extends BaseMessage> SendResult send(String topic, String tag, T message) {
        // 注意分隔符
        return send(buildDestination(topic,tag), message);
    }
    public <T extends BaseMessage> SendResult send(String destination, T message) {
        // 设置业务键,此处根据公共的参数进行处理
        // 更多的其它基础业务处理...
        Message<T> sendMessage = MessageBuilder.withPayload(message).setHeader(RocketMQHeaders.TAGS, message.getKey()).build();
        SendResult sendResult = template.syncSend(destination, sendMessage);
        // 此处为了方便查看给日志转了json,根据选择选择日志记录方式,例如ELK采集
        log.info("[{}]同步消息[{}]发送结果[{}]", destination, JSONObject.toJSON(message), JSONObject.toJSON(sendResult));
        return sendResult;
    }
    /**
     * 发送延迟消息
     */
    public <T extends BaseMessage> SendResult send(String topic, String tag, T message, int delayLevel) {
        return send(buildDestination(topic,tag), message, delayLevel);
    }
    public <T extends BaseMessage> SendResult send(String destination, T message, int delayLevel) {
        Message<T> sendMessage = MessageBuilder.withPayload(message).setHeader(RocketMQHeaders.TAGS, message.getKey()).build();
        SendResult sendResult = template.syncSend(destination, sendMessage, 3000, delayLevel);
        log.info("[{}]延迟等级[{}]消息[{}]发送结果[{}]", destination, delayLevel, JSONObject.toJSON(message), JSONObject.toJSON(sendResult));
        return sendResult;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/AESUtil.java
New file
@@ -0,0 +1,107 @@
package com.ruoyi.jianguan.util;
import com.ruoyi.common.core.utils.StringUtils;
import org.springframework.util.Base64Utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * 定义AES加密解密工具类
 */
public class AESUtil {
    private static final String KEY_ALGORITHM = "AES";//加密方式
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";//默认的加密算法
    private static final String KEY = "1234567890abcdef";//密码
    private static final String IV_PARAMETER = "1234567890abcdef";//偏移量
    private static final String CHARSET = "UTF-8";//编码
    /**
     * 加密操作
     * @param content  待加密内容
     * @return
     * @throws Exception
     */
    public static String encrypt(String content) {
        return encrypt(content, KEY, IV_PARAMETER);
    }
    /**
     * 加密操作
     * @param content  待加密内容
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String key, String iv_parameter) {
        try {
            if(StringUtils.isEmpty(content)){
                return content;
            }
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            byte[] raw = key.getBytes(CHARSET);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(iv_parameter.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(content.getBytes(CHARSET));
            return Base64Utils.encodeToString(encrypted);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    public static String decrypt(String content) {
        return decrypt(content, KEY, IV_PARAMETER);
    }
    /**
     *解密操作
     * @param content 待解密内容
     * @return
     * @throws Exception
     */
    public static String decrypt(String content, String key, String iv_parameter) {
        try {
            if(StringUtils.isEmpty(content)){
                return content;
            }
            byte[] raw = key.getBytes(CHARSET);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(iv_parameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = Base64Utils.decodeFromString(content);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, CHARSET);
            return originalString;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
    public static void main(String[] ages){
//        String encrypt = AESUtil.encrypt("{\"OperatorSecret\":\"cn51EeFQDTSMsn11R1ZNsYSEYBxDYcKK\",\"OperatorID\":\"MA25CNM38\"}", "YPFVz1OvAS4nSwLW", "5tLoP60aR9QUB5Mx");
//        System.err.println(encrypt);
        String travel = AESUtil.decrypt("9gVnNqAh9O7IuqqbyD8G1ukK86O3g0bUBLzM1LJL060bNjPJCtW0wWRjr756abxIm+nOuKkjMy7/DYScMcnl2KSYJJJb6Xc4Aza8L24Mp/UKQyW6Fe9m+ThDVUfMwvn7U2OxHDXniBUdmpNi2Ex9uHa/R18H2ka0DCv/bKCm/F4KTfz48Et/1L64JTTmj7l4the0Wr7KGiVewPIEE03LF5lF+h9j0W8czC6Gx5UJOMU=", "YPFVz1OvAS4nSwLW", "5tLoP60aR9QUB5Mx");
        System.err.println(travel);
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/AesEncryption.java
New file
@@ -0,0 +1,55 @@
package com.ruoyi.jianguan.util;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
/**
 * 充电桩交互的数据的加密解密
 */
public class AesEncryption {
    /**
     * 加密
     * @param key
     * @param iv
     * @param data
     * @return
     */
    public static String encrypt(String key, String iv, String data) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(data.getBytes());
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 解密
     * @param key
     * @param iv
     * @param encryptedData
     * @return
     */
    public static String decrypt(String key, String iv, String encryptedData) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
            return new String(decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/HMacMD5Util.java
New file
@@ -0,0 +1,122 @@
package com.ruoyi.jianguan.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HMacMD5Util {
    /**
     * 加签
     * @param operatorId
     * @param timeStamp
     * @param data
     * @param seq
     * @param SigSecret
     * @return
     */
    public static String getHMacMD5(String operatorId,String timeStamp, String data, String seq,String SigSecret) {
        String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString();
        byte[] macMD5 = HMacMD5Util.getHMacMD5Bytes(SigSecret.getBytes(), m.getBytes());
        return HMacMD5Util.bytesToHexString(macMD5);
    }
    /**
    * HmacMd5的计算公式为:HMAC(K,M) = H(K⊕opad∣H(K⊕ipad∣M))
    * 其中:K是密钥(byte[] key),长度可为64字节(后面涉及描述都是以字节byte进行),若小于该长度,在密钥后面用0(即0x00)补齐。
    * M是消息内容(byte[] m);
    * H是散列函数(此处采用MD5);
    * opad和ipad分别是由若干个0x5c和0x36组成的字符串;
    * ⊕表示异或运算;
    * ∣表示连接操作。
    **/
    private static byte[] getHMacMD5Bytes(byte[] key, byte[] m) {
        try {
            //定义长度
            int length = 64;
            //定义opad和ipad
            byte[] opad = new byte[length];
            byte[] ipad = new byte[length];
            for (int i = 0; i < 64; i++) {
                opad[i] = 0x5C;
                ipad[i] = 0x36;
            }
            byte[] actualKey = key;
            byte[] keyArr = new byte[length];
            //如果密钥长度,大于64字节,就使用MD5算法计算其散列值,作为密钥
            if (key.length > length) {
                actualKey = md5(key);
            }
            for (int i = 0; i < actualKey.length; i++) {
                keyArr[i] = actualKey[i];
            }
            //如果密钥长度不足64字节,就使用0x00补齐到64字节
            if (actualKey.length < length) {
            for (int i = key.length; i < length; i++)
                keyArr[i] = 0x00;
            }
            //使用密钥和ipad进行异或运算【K⊕ipad】
            byte[] kIpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
            }
            //将待加密数据M追加到kIpadXorResult后面【K⊕ipad∣M】
            byte[] firstAppendResult = new byte[kIpadXorResult.length + m.length];
            for (int i = 0; i < kIpadXorResult.length; i++) {
                firstAppendResult[i] = kIpadXorResult[i];
            }
            for (int i = 0; i < m.length; i++) {
                firstAppendResult[i + keyArr.length] = m[i];
            }
            //做MD5运算【H(K⊕ipad∣M)】
            byte[] firstHashResult = md5(firstAppendResult);
            //使用密钥和opad进行异或运算【K⊕opad】
            byte[] kOpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
            }
            //将firstHashResult追加到kOpadXorResult后面【K⊕opad∣H(K⊕ipad∣M)】
            byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
            for (int i = 0; i < kOpadXorResult.length; i++) {
                secondAppendResult[i] = kOpadXorResult[i];
            }
            for (int i = 0; i < firstHashResult.length; i++) {
                secondAppendResult[kOpadXorResult.length + i] = firstHashResult[i];
            }
            //做MD5运算【H(K⊕opad∣H(K⊕ipad∣M))】
            return md5(secondAppendResult);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
    * MD5(产生出一个128位(16字节)的散列值)
    **/
    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }
    /**
    * HEX转化为字符串
    **/
    private static String bytesToHexString(byte[] m) {
        StringBuilder stringBuilder = new StringBuilder();
        if (m == null || m.length <= 0) {
            return null;
        }
        for (int i = 0; i < m.length; i++) {
            int v = m[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString().toUpperCase();
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SendTagConstant.java
New file
@@ -0,0 +1,22 @@
package com.ruoyi.jianguan.util;
/**
 * @author xiaochen
 * @Date 2024/8/22 15:28
 */
public class SendTagConstant {
    /**
     * 推送充电设备接口状态信息
     */
    public static final String GUN_STATUS ="gun_status";
    /**
     * 推送充电状态信息
     */
    public static final String ORDER_STATUS ="order_status";
    /**
     * 推送充电订单信息
     */
    public static final String ORDER_INFO = "order_info";
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SequenceGenerator.java
New file
@@ -0,0 +1,56 @@
package com.ruoyi.jianguan.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class SequenceGenerator {
    private final ConcurrentHashMap<Long, AtomicInteger> counterMap = new ConcurrentHashMap<>();
    public synchronized String getNextSequence() {
        long currentTimestamp = System.currentTimeMillis() / 1000; // 获取当前秒级时间戳
        AtomicInteger counter = counterMap.get(currentTimestamp);
        if (counter == null) {
            counter = new AtomicInteger(1); // 新的一秒,初始化计数器为1
            counterMap.put(currentTimestamp, counter);
        } else {
            counter.incrementAndGet(); // 同一秒内,计数器递增
        }
        // 生成四位序列号
        String sequence = String.format("%04d", counter.get());
        return sequence;
    }
    public static void main(String[] args) {
        SequenceGenerator generator = new SequenceGenerator();
        // 测试生成多个序列号
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.getNextSequence());
            try {
                Thread.sleep(100); // 模拟同一秒内的多次调用
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 模拟进入新的一秒
        try {
            Thread.sleep(1100); // 等待超过1秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再次生成序列号
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.getNextSequence());
            try {
                Thread.sleep(100); // 模拟同一秒内的多次调用
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/SignUtil.java
New file
@@ -0,0 +1,205 @@
package com.ruoyi.jianguan.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
 * 签名工具
 * @author zhibing.pu
 * @Date 2025/1/23 11:30
 */
public class SignUtil {
    /*************************************快电******************************************/
    /**
     * 签名算法
     *
     * @param aValue 加密的原文,即源数据
     * @param aKey   密钥 这是针对一条字符串进行加密的方法
     */
    public static String hmacSign (String aValue, String aKey) {
        byte k_ipad[] = new byte[64];
        byte k_opad[] = new byte[64];
        byte keyb[];
        byte value[];
        try {
            keyb = aKey.getBytes("UTF-8");
            value = aValue.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            keyb = aKey.getBytes();
            value = aValue.getBytes();
        }
        Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
        Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
        for (int i = 0; i < keyb.length; i++) {
            k_ipad[i] = (byte) (keyb[i] ^ 0x36);
            k_opad[i] = (byte) (keyb[i] ^ 0x5c);
        }
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        md.update(k_ipad);
        md.update(value);
        byte dg[] = md.digest();
        md.reset();
        md.update(k_opad);
        md.update(dg, 0, 16);
        dg = md.digest();
        return toHex(dg);
    }
    public static String toHex (byte input[]) {
        if (input == null) {
            return null;
        }
        StringBuffer output = new StringBuffer(input.length * 2);
        for (int i = 0; i < input.length; i++) {
            int current = input[i] & 0xff;
            if (current < 16) {
                output.append("0");
            }
            output.append(Integer.toString(current, 16));
        }
        return output.toString().toUpperCase();
    }
    /*************************************新电途******************************************/
    /**
     * HmacMd5的计算公式为:HMAC(K,M) = H(K⊕opad∣H(K⊕ipad∣M))
     * 其中:K是密钥(byte[] key),长度可为64字节(后面涉及描述都是以字节byte进行),若小于该长度,在密钥后面用0(即0x00)补齐。
     * M是消息内容(byte[] m);
     * H是散列函数(此处采用MD5);
     * opad和ipad分别是由若干个0x5c和0x36组成的字符串;
     * ⊕表示异或运算;
     * ∣表示连接操作。
     **/
    public static byte[] getHMacMD5Bytes(byte[] key, byte[] m) {
        try {
            //定义长度
            int length = 64;
            //定义opad和ipad
            byte[] opad = new byte[length];
            byte[] ipad = new byte[length];
            for (int i = 0; i < length; i++) {
                opad[i] = 0x5C;
                ipad[i] = 0x36;
            }
            byte[] actualKey = key;
            byte[] keyArr = new byte[length];
            //如果密钥长度,大于64字节,就使用MD5算法计算其散列值,作为密钥
            if (key.length > length) {
                actualKey = md5(key);
            }
            for (int i = 0; i < actualKey.length; i++) {
                keyArr[i] = actualKey[i];
            }
            //如果密钥长度不足64字节,就使用0x00补齐到64字节
            if (actualKey.length < length) {
                for (int i = key.length; i < length; i++) {
                    keyArr[i] = 0x00;
                }
            }
            //使用密钥和ipad进行异或运算【K⊕ipad】
            byte[] kIpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
            }
            //将待加密数据M追加到kIpadXorResult后面【K⊕ipad∣M】
            byte[] firstAppendResult = new byte[kIpadXorResult.length + m.length];
            for (int i = 0; i < kIpadXorResult.length; i++) {
                firstAppendResult[i] = kIpadXorResult[i];
            }
            for (int i = 0; i < m.length; i++) {
                firstAppendResult[i + keyArr.length] = m[i];
            }
            //做MD5运算【H(K⊕ipad∣M)】
            byte[] firstHashResult = md5(firstAppendResult);
            //使用密钥和opad进行异或运算【K⊕opad】
            byte[] kOpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
            }
            //将firstHashResult追加到kOpadXorResult后面【K⊕opad∣H(K⊕ipad∣M)】
            byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
            for (int i = 0; i < kOpadXorResult.length; i++) {
                secondAppendResult[i] = kOpadXorResult[i];
            }
            for (int i = 0; i < firstHashResult.length; i++) {
                secondAppendResult[kOpadXorResult.length + i] = firstHashResult[i];
            }
            //做MD5运算【H(K⊕opad∣H(K⊕ipad∣M))】
            return md5(secondAppendResult);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * MD5(产生出一个128位(16字节)的散列值)
     **/
    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }
    /**
     * HEX转化为字符串
     **/
    public static String bytesToHexString(byte[] m) {
        StringBuilder stringBuilder = new StringBuilder();
        if (m == null || m.length <= 0) {
            return null;
        }
        for (int i = 0; i < m.length; i++) {
            int v = m[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        //最后得到的签名,统一转化为大写
        return stringBuilder.toString().toUpperCase();
    }
    public static void main(String[] args) {
//        String encrypt = AESUtil.encrypt("{\"total\":1,\"stationStatusInfo\":{\"operationID\":\"123456789\",\"stationID\":\"111111111111111\",\"connectorStatusInfos\":{\"connectorID\":1,\"equipmentID\":\"10000000000000000000001\",\"status\":4,\"currentA\":0,\"currentB\":0,\"currentC\":0,\"voltageA\":0,\"voltageB\":0,\"voltageC\":0,\"soc\":10,}}}");
//        String s = hmacSign(encrypt, "123456789abcdef");
//        System.err.println(s);
        //签名秘钥SigSecret
        String key = "1234567890abcdef";
        //运营商标识OperatorId
        String operatorId = "123456789";
        //参数信息Data
        String data = "il7B0BSEjFdzpyKzfOFpvg/Se1CP802RItKYFPfSLRxJ3jf0bVl9hvYOEktPAYW2nd7S8MBcyHYyacHKbISq5iTmDzG+ivnR+SZJv3USNTYVMz9rCQVSxd0cLlqsJauko79NnwQJbzDTyLooYoIwz75qBOH2/xOMirpeEqRJrF/EQjWekJmGk9RtboXePu2rka+Xm51syBPhiXJAq0GfbfaFu9tNqs/e2Vjja/ltE1M0lqvxfXQ6da6HrThsm5id4ClZFIi0acRfrsPLRixS/IQYtksxghvJwbqOsbIsITail9Ayy4tKcogeEZiOO+4Ed264NSKmk7l3wKwJLAFjCFogBx8GE3OBz4pqcAn/ydA=";
        //时间戳TimeStamp(格式:年月日时分秒)
        String timeStamp = "20160729142400";
        //自增序列Seq
        String seq = "0001";
        //进行字符串拼接、计算
        String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString();
        byte[] hmacMd5 = getHMacMD5Bytes(key.getBytes(), m.getBytes());
        // 打印计算得到的签名Sig
        System.out.println(bytesToHexString(hmacMd5));
    }
}
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/TCECSuperviseUtil.java
New file
@@ -0,0 +1,373 @@
package com.ruoyi.jianguan.util;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.jianguan.model.*;
import com.ruoyi.other.api.domain.Operator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
 * 中电联TCEC标准
 * @author zhibing.pu
 * @Date 2025/1/21 11:48
 */
@Slf4j
@Component
public class TCECSuperviseUtil {
    // 测试环境
//    private static final String OperatorID = "MA01H3BQ2";
//    private static final String OperatorSecret = "f1331ef0b37c2d1b";
//    private static final String SigSecret = "a6fedf0e1b27d6f7";
//    private static final String DataSecret = "50a61b93919c9604";
//    private static final String DataSecretIV = "7c8ac6861661d584";
//    private final static String url = "https://dev-gov-hlht-sc.unievbj.com/evcs/v1.0.0";
    // 正式环境
    private static final String OperatorID = "MA01H3BQ2";
    private static final String OperatorSecret = "a762796b2a8989b8";
    private static final String SigSecret = "52cd107eb677c004";
    private static final String DataSecret = "98f46ab6481d87c4";
    private static final String DataSecretIV = "978170fd1c11a70e";
    private final static String url = "https://hlht-dipper-sc.unievbj.com/evcs/v1.0.0";
    private final static String query_token = "/query_token";
    private static final String OurDataSecret = "50a61b93919c9605";
    private static final String OurDataSecretIV = "7c8ac6861661d585";
    private static final String OurSigSecret = "a6fedf0e1b27d6f6";
    private static final String OurOperatorID = "MA01H3BQ3";
    private static final String OurOperatorSecret = "f1331ef0b37c2d1a";
    @Autowired
    private RedisService redisService;
    public static final String TOKEN_KEY = "charge_token:";
    /**
     * 获取token
     */
    /**
     * 推送充电设备接口状态信息
     */
    private final static String supervise_notification_station_status = "/supervise_notification_station_status";
    /**
     *推送充电状态信息
     */
    private final static String supervise_notification_equip_charge_status = "/supervise_notification_equip_charge_status";
    /**
     *推送充电订单信息
     */
    private final static String supervise_notification_charge_order_info = "/supervise_notification_charge_order_info";
    private final static String supervise_notification_operation_stats_info = "/supervise_notification_operation_stats_info";
    private final static String supervise_notification_realtime_power_info = "/supervise_notification_realtime_power_info";
    private final static String supervise_notification_station_info = "/supervise_notification_station_info";
 /** 获取token
         */
//    public String queryToken(){
//        String token = redisService.getCacheObject(TOKEN_KEY);
//        if(StringUtils.hasLength(token)){
//            return token;
//        }
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("OperatorID", OperatorID);
//        jsonObject.put("OperatorSecret", OperatorSecret);
//        String params = jsonObject.toJSONString();
//        // 参数加密
//        String data = AesEncryption.encrypt(DataSecret, DataSecretIV, params);
//        // 获取签名
//        String timeStamp = System.currentTimeMillis() + "";
//        SequenceGenerator generator = new SequenceGenerator();
//        String nextSequence = generator.getNextSequence();
//        String hmacMD5 = HMacMD5Util.getHMacMD5(OperatorID,timeStamp, data,nextSequence,SigSecret);
//        jsonObject = new JSONObject();
//        jsonObject.put("OperatorID", OperatorID);
//        jsonObject.put("Data", data);
//        jsonObject.put("TimeStamp", timeStamp);
//        jsonObject.put("Seq", nextSequence);
//        jsonObject.put("Sig", hmacMD5);
//        String result = HttpUtils.sendPost(url+query_token, jsonObject.toJSONString());
//        String string = JSONObject.parseObject(result).getString("Data");
//        String decrypt = AesEncryption.decrypt(DataSecret, DataSecretIV, string);
//        JSONObject tokenResult = JSONObject.parseObject(decrypt);
//        token = tokenResult.getString("AccessToken");
//        Integer TokenAvailableTime = tokenResult.getInteger("TokenAvailableTime");
//        redisService.setCacheObject(TOKEN_KEY,token, (long) (TokenAvailableTime - 60), TimeUnit.SECONDS);
//        return token;
//    }
    public String queryToken(){
        HttpRequest post = HttpUtil.createPost(url + query_token);
        JSONObject info = new JSONObject();
        info.put("OperatorID", "906171535");
        info.put("OperatorSecret", OperatorSecret);
        Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        post.contentType("application/json;charset=utf-8");
        BaseRequestJianGuan baseRequest = new BaseRequestJianGuan();
        baseRequest.setOperatorID("906171535");
        baseRequest.setTimeStamp(timeStamp+"");
        baseRequest.setSeq("0001");
        String jsonString = JacksonUtils.toJson(info);
        SequenceGenerator generator = new SequenceGenerator();
        String nextSequence = generator.getNextSequence();
        String data = AesEncryption.encrypt(DataSecret, DataSecretIV,jsonString);
        String hmacMD5 = HMacMD5Util.getHMacMD5("906171535",timeStamp+"", data,nextSequence,SigSecret);
        baseRequest.setData(data);
        baseRequest.setSig(hmacMD5);
        String request_json = JacksonUtils.toJson(baseRequest);
        log.info("获取三方平台授权token请求地址:" + post.getUrl());
        log.info("获取三方平台授权token请求参数:" + request_json);
        log.info("获取三方平台授权token请求Data:" + jsonString);
        post.body(request_json);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("获取三方平台授权token失败:" + execute.body());
            return null;
        }
        log.info("获取三方平台授权token响应参数:" + execute.body());
        BaseResult baseResult = JSON.parseObject(execute.body(), BaseResult.class);
        Integer Ret = baseResult.getRet();
        if(0 != Ret){
            log.error("获取三方平台授权token失败:" + baseResult.getMsg());
            return null;
        }
        //解密参数
        String decrypt = AESUtil.decrypt(baseResult.getData(), DataSecret, DataSecretIV);
        log.info("获取三方平台授权token响应Data:" + decrypt);
        QueryTokenResult queryTokenResult = JSON.parseObject(decrypt, QueryTokenResult.class);
        String token = queryTokenResult.getAccessToken();
//        Long tokenAvailableTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) + queryTokenResult.getTokenAvailab
        return token;
    }
    /**
     * 设备状态变化推送
     * @param info
     */
    public NotificationStationStatusResult notificationStationStatus(Operator operator, ConnectorStatusInfo info) {
        HttpRequest post = HttpUtil.createPost(url+supervise_notification_station_status);
        buildBody(post, info, operator);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送三方平台设备状态失败:" + execute.body());
            return null;
        }
        log.info("推送三方平台设备状态响应:" + execute.body());
        BaseResult baseResult = JSON.parseObject(execute.body(), BaseResult.class);
        Integer Ret = baseResult.getRet();
        if(0 != Ret){
            log.error("推送三方平台设备状态失败:" + baseResult.getMsg());
            return null;
        }
        //解密参数
        String decrypt = AESUtil.decrypt(baseResult.getData(), DataSecret, DataSecretIV);
        log.info("推送三方平台设备状态Data:" + decrypt);
        NotificationStationStatusResult notificationStationStatusResult = JSON.parseObject(decrypt, NotificationStationStatusResult.class);
        return notificationStationStatusResult;
    }
    /**
     * 推动充电状态
     * @param info
     * @return
     */
    public NotificationEquipChargeStatusResult notificationSupEquipChargeStatus(Operator operator, SupEquipChargeStatus info){
        HttpRequest post = HttpUtil.createPost(url+supervise_notification_equip_charge_status);
        buildBody(post, info, operator);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送三方平台充电状态失败:" + execute.body());
            return null;
        }
        log.info("推送三方平台充电状态响应:" + execute.body());
        BaseResult baseResult = JSON.parseObject(execute.body(), BaseResult.class);
        Integer Ret = baseResult.getRet();
        if(0 != Ret){
            log.error("推送三方平台充电状态失败:" + baseResult.getMsg());
            return null;
        }
        //解密参数
        String decrypt = AESUtil.decrypt(baseResult.getData(), DataSecret, DataSecretIV);
        log.info("推送三方平台充电状态Data:" + decrypt);
        NotificationEquipChargeStatusResult notificationEquipChargeStatusResult = JSON.parseObject(decrypt, NotificationEquipChargeStatusResult.class);
        return notificationEquipChargeStatusResult;
    }
    /**
     * 推送充电订单信息
     * @param info
     * @return
     */
    public NotificationChargeOrderInfoResult notificationChargeOrderInfo(Operator operator, SupChargeOrderInfo info){
        HttpRequest post = HttpUtil.createPost(url+supervise_notification_charge_order_info);
        if (info.getOrderStatus()!=null){
            switch (info.getOrderStatus()){
                case -1:
                    info.setOrderStatus(7);
                    break;
                case 0:
                    info.setOrderStatus(7);
                    break;
                case 1:
                    info.setOrderStatus(1);
                    break;
                case 2:
                    info.setOrderStatus(1);
                    break;
                case 3:
                    info.setOrderStatus(2);
                    break;
                case 4:
                    info.setOrderStatus(3);
                    break;
                case 5:
                    info.setOrderStatus(4);
                    break;
            }
        }else{
            info.setOrderStatus(5);
        }
        buildBody(post, info, operator);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送三方平台充电订单信息失败:" + execute.body());
            return null;
        }
        log.info("推送三方平台充电订单信息响应:" + execute.body());
        BaseResult baseResult = JSON.parseObject(execute.body(), BaseResult.class);
        Integer Ret = baseResult.getRet();
        if(0 != Ret){
            log.error("推送三方平台充电订单信息失败:" + baseResult.getMsg());
            return null;
        }
        //解密参数
        String decrypt = AESUtil.decrypt(baseResult.getData(), DataSecret, DataSecretIV);
        log.info("推送三方平台充电订单信息Data:" + decrypt);
        NotificationChargeOrderInfoResult notificationChargeOrderInfoResult = JSON.parseObject(decrypt, NotificationChargeOrderInfoResult.class);
        return notificationChargeOrderInfoResult;
    }
    /**
     * 构建请求参数和消息头
     * @param post
     * @param
     */
    public void buildBody(HttpRequest post, Object o, Operator operator){
        Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        post.contentType("application/json;charset=utf-8");
        post.header("Authorization", "Bearer " + queryToken());
        BaseRequestJianGuan baseRequest = new BaseRequestJianGuan();
        baseRequest.setOperatorID("906171535");
        baseRequest.setTimeStamp(timeStamp+"");
        baseRequest.setSeq("0001");
        // 使用 Jackson 转换为 JSON
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(MapperFeature.USE_ANNOTATIONS); // 启用注解支持
        String jsonString = null;
        try {
            jsonString = objectMapper.writeValueAsString(o);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String encrypt = AesEncryption.encrypt(DataSecret, DataSecretIV,jsonString);
//        String encrypt = AesEncryption.encrypt(DataSecret, DataSecretIV,jsonString);
        baseRequest.setData(encrypt);
        baseRequest.setOperator(operator);
        SequenceGenerator generator = new SequenceGenerator();
        String nextSequence = generator.getNextSequence();
        String hmacMD5 = HMacMD5Util.getHMacMD5("906171535",timeStamp+"", encrypt,nextSequence,SigSecret);
//        String hmacMD5 = HMacMD5Util.getHMacMD5(OperatorID,timeStamp, data,nextSequence,OurSigSecret);
        baseRequest.setSig(hmacMD5);
        String request_json = JacksonUtils.toJson(baseRequest);
        post.body(request_json);
        log.info("推送三方平台请求地址:" + post.getUrl());
        log.info("推送三方平台请求参数:" + request_json);
        log.info("推送三方平台请求Data:" + jsonString);
    }
    /**
     * 构建请求参数和消息头
     * @param post
     * @param
     */
    public void buildBodyStatus(HttpRequest post, SupStationPowerInfoResult info, Operator operator){
        Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        post.contentType("application/json;charset=utf-8");
        post.header("Authorization", "Bearer " + queryToken());
        BaseRequestJianGuan baseRequest = new BaseRequestJianGuan();
        baseRequest.setOperatorID("906171535");
        baseRequest.setTimeStamp(timeStamp+"");
        baseRequest.setSeq("0001");
        String request_json1 = JacksonUtils.toJson(info);
        String encrypt = AesEncryption.encrypt(DataSecret, DataSecretIV,request_json1);
//        String encrypt = AesEncryption.encrypt(DataSecret, DataSecretIV,jsonString);
        baseRequest.setData(encrypt);
        baseRequest.setOperator(operator);
        SequenceGenerator generator = new SequenceGenerator();
        String nextSequence = generator.getNextSequence();
        String hmacMD5 = HMacMD5Util.getHMacMD5("906171535",timeStamp+"", encrypt,nextSequence,SigSecret);
//        String hmacMD5 = HMacMD5Util.getHMacMD5(OperatorID,timeStamp, data,nextSequence,OurSigSecret);
        baseRequest.setSig(hmacMD5);
        String request_json = JacksonUtils.toJson(baseRequest);
        post.body(request_json);
        log.info("推送三方平台请求地址:" + post.getUrl());
        log.info("推送三方平台请求参数:" + request_json);
        log.info("推送三方平台请求Data:" + request_json1);
    }
    public static void main(String[] args) {
        BaseModel model = new BaseModel();
        model.setOperatorID("MA01H3BQ2");
        model.setData("AoArdDDcmHcmOMkCLHodTpY1xLtt9yhLqxvKPyfdlmEOBj1LJnQM+Z4JOZllt3Pj9rubfgxJ51zMAfzquQegJzHGAT9Y7JrKFzFe6jGtXo0=");
        model.setTimeStamp(20250205120800L);
        model.setSeq("0001");
        Operator operator = new Operator();
        operator.setName("XinDianTu");
        operator.setSigSecret("S94xUpTpOIlLJBk8");
        model.setOperator(operator);
        String key = operator.getSigSecret();
        String m = new StringBuilder(model.getOperatorID()).append(model.getData()).append(model.getTimeStamp()).append(model.getSeq()).toString();
        byte[] hmacMd5 = SignUtil.getHMacMD5Bytes(key.getBytes(), m.getBytes());
        // 打印计算得到的签名Sig
        String s = SignUtil.bytesToHexString(hmacMd5);
        System.err.println(s);
//        BaseModel model = new BaseModel();
//        model.setOperatorID("MA25CNM38");
//        model.setData("xQYYEPiwoc4JENnQsF50qP6Tmnj7uU/AshWn3QbIgrMIk8zvFpy6fWLIiLzQHcLPFCihqH1uzoNhGVNcS8Wvf5gIx9+cWJvYtjwtsjAGMEwNQ6y+rF1jjKnqCNcQbHbhqJ2l76sD54QCFKyenKxymrXri19bDV8hizn3nBw+jcHBtqKHWzjdSHwPDWPIw4rXnrbWLya2PXVgYtVg93WPtliw+0xsqW0BxJamE70/Ilbg4wB5fOAOvXmbLFI+v9jRjpcA7ImhprqPMYkXYAfa2QlICrJEBK7DfpJvRMzKzeT90kOAITqIqFvbfV0ti+greRqToLP6ni4o6w3ID42UmKasIpLTnx+qtR4bVTBTRuDzXvNXDA92RqHaJO21xbSen1eHN/yGfrchBIM0gmav7EpaYAerfU4ubnmJ6xujR6okYepJwBD5DiSIrObfS+GWVPRekvnjvm7BC02NXTrGKA==");
//        model.setTimeStamp(20250205161426L);
//        model.setSeq("0001");
//        Operator operator = new Operator();
//        operator.setOurOperatorId("2921700136");
//        operator.setOurSigSecret("KBm5J2fbGzyhX023");
//        model.setOperator(operator);
//        String key = operator.getOurSigSecret();
//
//        String m = new StringBuilder(operator.getOurOperatorId()).append(model.getData()).append(model.getTimeStamp()).append(model.getSeq()).toString();
//        byte[] hmacMd5 = SignUtil.getHMacMD5Bytes(key.getBytes(), m.getBytes());
//        // 打印计算得到的签名Sig
//        String s = SignUtil.bytesToHexString(hmacMd5);
//        System.err.println(s);
    }
}
ruoyi-service/ruoyi-jianguan/src/main/resources/logback.xml
New file
@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/data/log/app/ruoyi-integration"/>
    <!--0. 日志格式和颜色渲染 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--1. 输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/all.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
        <logger name="org.springframework.web" level="info"/>
        <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
    -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!-- 4  最终的策略:
                 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
    <springProfile name="dev">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
    </springProfile>
    <springProfile name="test">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
    <springProfile name="prod">
        <root level="info">
            <!-- 生产环境最好不配置console写文件 -->
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
</configuration>
ruoyi-service/ruoyi-jianguan/src/main/resources/mybatis-config.xml
New file
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration  PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 打印查询语句 不会写入到日志文件中-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--<setting name="logImpl" value="LOG4J" />-->
        <!-- 控制全局缓存(二级缓存),按美团技术团队的说法,尽量别用缓存机制 emmmm.... -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <!-- <setting name="lazyLoadingEnabled" value="true"/> -->
        <setting name="mapUnderscoreToCamelCase" value="false"/><!--是否将map下划线方式转为驼峰式命名-->
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <!-- <setting name="aggressiveLazyLoading" value="false"/>-->
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- 关于mybatis的一二级缓存 请参照:https://tech.meituan.com/2018/01/19/mybatis-cache.html -->
        <!-- 一级缓存范围默认:SESSION ,此范围在复杂应用场景中可能会出现脏读数据-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--<setting name="localCacheScope" value="STATEMENT"/>-->
        <setting name="localCacheScope" value="STATEMENT"/>
    </settings>
</configuration>