“mitao”
2026-02-03 a617006079e833b174f3223dee1e0266aa3ac2d8
Merge remote-tracking branch 'origin/master'

# Conflicts:
# xp-api/src/main/java/com/xiaopeng/api/model/account/XpOperationsUser.java
# xp-api/src/main/java/com/xiaopeng/api/model/account/XpOperationsUserNotification.java
# xp-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java
# xp-api/src/main/java/com/xiaopeng/api/model/maintenance/XpVehicle.java
# xp-api/src/main/java/com/xiaopeng/api/model/operation/XpAgreementAppUser.java
# xp-api/src/main/java/com/xiaopeng/api/model/operation/XpElectronicFence.java
# xp-api/src/main/java/com/xiaopeng/api/model/operation/XpElectronicFenceArea.java
# xp-api/src/main/java/com/xiaopeng/api/model/operation/XpPoint.java
# xp-api/src/main/java/com/xiaopeng/api/model/operation/XpRegion.java
# xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/TokenController.java
# xp-service/xp-account/src/main/java/com/xiaopeng/account/mapper/XpOperationsUserMapper.java
# xp-service/xp-account/src/main/java/com/xiaopeng/account/mapper/XpOperationsUserNotificationMapper.java
# xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java
# xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserServiceImpl.java
# xp-service/xp-account/src/main/resources/mapper/account/XpOperationsUserMapper.xml
# xp-service/xp-account/src/main/resources/mapper/account/XpOperationsUserNotificationMapper.xml
# xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpTaskMapper.java
# xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpVehicleMapper.java
# xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
# xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/impl/XpVehicleServiceImpl.java
# xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpTaskMapper.xml
# xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpVehicleMapper.xml
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpPointController.java
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpPointMapper.java
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpRegionMapper.java
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
# xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java
# xp-service/xp-operation/src/main/resources/mapper/operation/XpPointMapper.xml
# xp-service/xp-operation/src/main/resources/mapper/operation/XpRegionMapper.xml
2个文件已删除
2 文件已重命名
39个文件已添加
48个文件已修改
2442 ■■■■■ 已修改文件
pom.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginCodeDTO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginGetAgreementByTypeDTO.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginGetCodeDTO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginPasswordDTO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/dto/operation/UpdatePasswordDTO.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/factory/operation/SysLogClientFallbackFactory.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/feignClient/operation/SysLogClient.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/model/operation/XpRegion.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/vo/account/LoginOperationUser.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/vo/operation/XpElectronicFenceVo.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/java/com/xiaopeng/api/vo/operation/XpPointsVo.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/SecurityConstants.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/UserConstants.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/VerificationCodeConstants.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/dto/ServiceNameConstantsEnum.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/utils/JwtUtils.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-datascope/src/main/java/com/xiaopeng/common/datascope/aspect/DataScopeAspect.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-log/src/main/java/com/xiaopeng/common/log/service/AsyncLogService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/annotation/EnableCustomConfig.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/annotation/EnableRyFeignClients.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/aspect/PreAuthorizeAspect.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/service/TokenService.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-gateway/src/main/java/com/xiaopeng/gateway/GatewayApplication.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-gateway/src/main/java/com/xiaopeng/gateway/RuoYiGatewayApplication.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-gateway/src/main/java/com/xiaopeng/gateway/config/CaptchaConfig.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-modules/xp-file/src/main/resources/logback.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-modules/xp-job/src/main/resources/logback.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/AccountApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/TokenController.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/SysLoginService.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/XpOperationsUserNotificationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/XpOperationsUserService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysLoginService.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysPasswordService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysRecordLogService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/vo/AddCompanyUserDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-account/src/main/java/com/xiaopeng/account/vo/CompanyUserVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-automaticPilot/src/main/java/com/xiaopeng/automaticPilot/AutomaticPilotApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-itinerary/src/main/java/com/xiaopeng/itinerary/ItineraryApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/MaintenanceApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/controller/WorkbenchController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpTaskMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/query/WorkBenchQuery.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/XpVehicleService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/vo/WorkBenchVO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpTaskMapper.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/MapApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/controller/ElectronicFenceController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/mapper/XpElectronicFenceAreaMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/mapper/XpElectronicFenceMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/XpElectronicFenceAreaService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/XpElectronicFenceService.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceAreaServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/java/com/xiaopeng/map/vo/GeoFencingPolygon.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/resources/mapper/XpElectronicFenceAreaMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-map/src/main/resources/mapper/XpElectronicFenceMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/OperationApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/IndexMapController.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/SysOperlogController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpAgreementUserController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpBannerController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpOpenCityController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpPointController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/dto/NearestDto.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpPointMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpRegionMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/query/PointMapQuery.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/XpPointService.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/XpRegionService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/utils/XpPricingUtil.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/utils/map/FastDistanceCalculator.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/vo/NearestNextVo.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/vo/NearestVo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/resources/mapper/operation/XpPointMapper.xml 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-operation/src/main/resources/mapper/operation/XpRegionMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-order/src/main/java/com/xiaopeng/order/OrderApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-payment/src/main/java/com/xiaopeng/payment/PaymentApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-pushMessage/src/main/java/com/xiaopeng/pushMessage/PushMessageApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-remoteDriving/src/main/java/com/xiaopeng/remoteDriving/RemoteDrivingApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-vehicleConvoy/src/main/java/com/xiaopeng/vehicleConvoy/VehicleConvoyApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-service/xp-vehicleConvoy/src/main/resources/bootstrap.yml 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -13,7 +13,7 @@
    <parent>
        <groupId>com.xiaopeng.logan</groupId>
        <artifactId>logan-parent</artifactId>
        <version>2.2.0</version>
        <version>2.3.5</version>
    </parent>
    <properties>
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginCodeDTO.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.api.dto.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP验证码登录DTO")
public class AppLoginCodeDTO implements Serializable {
    @ApiModelProperty(value = "账号")
    private String phoneNumber;
    @ApiModelProperty(value = "验证码")
    private String verificationCode;
}
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginGetAgreementByTypeDTO.java
New file
@@ -0,0 +1,15 @@
package com.xiaopeng.api.dto.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP获取协议DTO")
public class AppLoginGetAgreementByTypeDTO implements Serializable {
    @ApiModelProperty(value = "类型 1=用户服务协议 2=平台隐私政策 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明")
    private Integer contentType;
}
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginGetCodeDTO.java
New file
@@ -0,0 +1,17 @@
package com.xiaopeng.api.dto.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP获取手机验证码DTO")
public class AppLoginGetCodeDTO implements Serializable {
    @ApiModelProperty(value = "账号", required = true)
    private String phoneNumber;
    @ApiModelProperty(value = "验证码类型 1登录 2忘记密码 3修改密码", required = true)
    private Integer codeType;
}
xp-api/src/main/java/com/xiaopeng/api/dto/operation/AppLoginPasswordDTO.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.api.dto.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP账号密码登录DTO")
public class AppLoginPasswordDTO implements Serializable {
    @ApiModelProperty(value = "账号")
    private String phoneNumber;
    @ApiModelProperty(value = "密码")
    private String password;
}
xp-api/src/main/java/com/xiaopeng/api/dto/operation/UpdatePasswordDTO.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.api.dto.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP修改密码DTO")
public class UpdatePasswordDTO implements Serializable {
    @ApiModelProperty(value = "账号",required = true)
    private String phoneNumber;
    @ApiModelProperty(value = "验证码",required = true)
    private String verificationCode;
    @ApiModelProperty(value = "新密码",required = true)
    private String newPassword;
    @ApiModelProperty(value = "确认密码",required = true)
    private String confirmPassword;
}
xp-api/src/main/java/com/xiaopeng/api/factory/operation/SysLogClientFallbackFactory.java
New file
@@ -0,0 +1,24 @@
package com.xiaopeng.api.factory.operation;
import com.xiaopeng.api.feignClient.operation.SysLogClient;
import com.xiaopeng.api.model.operation.SysOperLog;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SysLogClientFallbackFactory implements FallbackFactory<SysLogClient> {
    @Override
    public SysLogClient create(Throwable cause) {
        return new SysLogClient(){
            @Override
            public R saveLog(SysOperLog sysOperLog) {
                log.error("保存系统日志记录失败:{}", cause.getMessage());
                return R.fail("保存系统日志记录失败");
            }
        };
    }
}
xp-api/src/main/java/com/xiaopeng/api/feignClient/operation/SysLogClient.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.api.feignClient.operation;
import com.xiaopeng.api.factory.operation.SysLogClientFallbackFactory;
import com.xiaopeng.api.model.operation.SysOperLog;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
@FeignClient(contextId = "SysLogClient", value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, fallbackFactory = SysLogClientFallbackFactory.class)
public interface SysLogClient {
    /**
     * 保存系统日志
     * @param sysOperLog
     */
    @PostMapping("/operlog/saveLog")
    R saveLog(SysOperLog sysOperLog);
}
xp-api/src/main/java/com/xiaopeng/api/model/operation/XpRegion.java
@@ -1,55 +1,61 @@
package com.xiaopeng.api.model.operation;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * <p>
 * 省市区三级联动
 * 省市管理
 * </p>
 *
 * @author mitao
 * @since 2026-02-03
 * @author xiaochen
 * @since 2024-02-29
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("xp_region")
@ApiModel(value="XpRegion对象", description="省市区三级联动")
@ApiModel(value="TRegion对象", description="省市管理")
public class XpRegion implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private Long id;
    @ApiModelProperty(value = "城市名称")
    @TableField("name")
    private String name;
    @ApiModelProperty(value = "城市代码")
    @TableField("code")
    private String code;
    private String citycode;
    @ApiModelProperty(value = "城市code")
    @TableField("cityCode")
    private String cityCode;
    @ApiModelProperty(value = "父级ID")
    private Integer parentId;
    @TableField("parentId")
    private Long parentId;
    @ApiModelProperty(value = "英文名称")
    @TableField("english")
    private String english;
    @ApiModelProperty(value = "首字母")
    @TableField("initial")
    private String initial;
    private String lat;
    private String lon;
    private String lat;
}
xp-api/src/main/java/com/xiaopeng/api/vo/account/LoginOperationUser.java
New file
@@ -0,0 +1,169 @@
package com.xiaopeng.api.vo.account;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsUser;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
/**
 * 运维用户信息
 *
 * @author ruoyi
 */
public class LoginOperationUser implements Serializable
{
    private static final long serialVersionUID = 1L;
    /**
     * 用户唯一标识
     */
    private String token;
    /**
     * 用户名id
     */
    private Long id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 登录时间
     */
    private Long loginTime;
    /**
     * 过期时间
     */
    private Long expireTime;
    /**
     * 登录IP地址
     */
    private String ipaddr;
    /**
     * 权限列表
     */
    private Set<String> permissions;
    /**
     * 角色列表
     */
    private Set<String> roles;
    /**
     * 用户信息
     */
    private XpOperationsUser xpOperationsUser;
    /**
     * 用户类型(系统用户,小程序用户)
     */
    private String userType;
    public String getToken()
    {
        return token;
    }
    public void setToken(String token)
    {
        this.token = token;
    }
    public Long getId()
    {
        return id;
    }
    public void setId(Long id)
    {
        this.id = id;
    }
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public Long getLoginTime()
    {
        return loginTime;
    }
    public void setLoginTime(Long loginTime)
    {
        this.loginTime = loginTime;
    }
    public Long getExpireTime()
    {
        return expireTime;
    }
    public void setExpireTime(Long expireTime)
    {
        this.expireTime = expireTime;
    }
    public String getIpaddr()
    {
        return ipaddr;
    }
    public void setIpaddr(String ipaddr)
    {
        this.ipaddr = ipaddr;
    }
    public Set<String> getPermissions()
    {
        return permissions;
    }
    public void setPermissions(Set<String> permissions)
    {
        this.permissions = permissions;
    }
    public Set<String> getRoles()
    {
        return roles;
    }
    public void setRoles(Set<String> roles)
    {
        this.roles = roles;
    }
    public XpOperationsUser getXpOperationsUser()
    {
        return xpOperationsUser;
    }
    public void setXpOperationsUser(XpOperationsUser xpOperationsUser)
    {
        this.xpOperationsUser = xpOperationsUser;
    }
    public String getUserType() {
        return userType;
    }
    public void setUserType(String userType) {
        this.userType = userType;
    }
}
xp-api/src/main/java/com/xiaopeng/api/vo/operation/XpElectronicFenceVo.java
New file
@@ -0,0 +1,21 @@
package com.xiaopeng.api.vo.operation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel("电子围栏开放区域Vo")
public class XpElectronicFenceVo {
    @ApiModelProperty(value = "id")
    private Long id;
    @ApiModelProperty(value = "围栏名称")
    private String name;
    @ApiModelProperty(value = "多边形顶点坐标数组")
    private List<XpPointsVo> points;
}
xp-api/src/main/java/com/xiaopeng/api/vo/operation/XpPointsVo.java
New file
@@ -0,0 +1,12 @@
package com.xiaopeng.api.vo.operation;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel("经纬度信息Vo")
public class XpPointsVo {
    private Double lat;
    private Double lng;
}
xp-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
com.xiaopeng.api.factory.operation.SysLogClientFallbackFactory
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/SecurityConstants.java
@@ -10,7 +10,7 @@
    /**
     * 用户ID字段
     */
    public static final String DETAILS_USER_ID = "user_id";
    public static final String DETAILS_USER_ID = "id";
    /**
     * 用户名字段
@@ -36,7 +36,11 @@
     * 用户标识
     */
    public static final String USER_KEY = "user_key";
    /**
     * 运维人员用户表示
     */
    public static final String OPERATION_USER_KEY = "operation_user_key";
    /**
     * 用户类型(system/applet)
     */
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/UserConstants.java
@@ -74,7 +74,7 @@
    /**
     * 密码长度限制
     */
    public static final int PASSWORD_MIN_LENGTH = 5;
    public static final int PASSWORD_MIN_LENGTH = 11;
    public static final int PASSWORD_MAX_LENGTH = 40;
}
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/VerificationCodeConstants.java
New file
@@ -0,0 +1,18 @@
package com.xiaopeng.common.core.constant;
/**
 * 验证码类型常量信息
 *
 * @author ruoyi
 */
public class VerificationCodeConstants
{
    /** 是否为系统默认(是) */
    public static final String LOGIN_CODE = "loginCode_";
    /** 是否菜单外链(是) */
    public static final String  FORGET_PASSWORD_CODE= "forgetPasswordCode_";
    /** 是否菜单外链(否) */
    public static final String UPDATE_PASSWORD_CODE = "updatePasswordCode_";
}
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/dto/ServiceNameConstantsEnum.java
New file
@@ -0,0 +1,53 @@
package com.xiaopeng.common.core.dto;
/**
 * 服务名称常量枚举类
 */
public interface ServiceNameConstantsEnum {
    /**
     * 账户服务
     */
    String XP_ACCOUNT_SERVICE = "xp-account";
    /**
     * 自动驾驶服务
     */
    String XP_AUTOMATIC_PILOT_SERVICE = "xp-automaticPilot";
    /**
     * 行程服务
     */
    String XP_ITINERARY_SERVICE = "xp-itinerary";
    /**
     * 运维服务
     */
    String XP_MAINTENANCE_SERVICE = "xp-maintenance";
    /**
     * 地图服务
     */
    String XP_MAP_SERVICE = "xp-map";
    /**
     * 运营服务
     */
    String XP_OPERATION_SERVICE = "xp-operation";
    /**
     * 订单服务
     */
    String XP_ORDER_SERVICE = "xp-order";
    /**
     * 支付服务
     */
    String XP_PAYMENT_SERVICE = "xp-payment";
    /**
     * 推送服务
     */
    String XP_PUSH_MESSAGE_SERVICE = "xp-pushMessage";
    /**
     * 远程驾驶服务
     */
    String XP_REMOTE_DRIVING_SERVICE = "xp-remoteDriving";
    /**
     * 车辆车队服务
     */
    String XP_VEHICLE_CONVOY_SERVICE = "xp-vehicleConvoy";
}
xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/utils/JwtUtils.java
@@ -51,6 +51,17 @@
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.USER_KEY);
    }
    /**
     * 根据令牌获取运维用户标识
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getOperationUserKey(String token)
    {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.OPERATION_USER_KEY);
    }
    /**
     * 根据令牌获取用户标识
xp-common/xp-common-datascope/src/main/java/com/xiaopeng/common/datascope/aspect/DataScopeAspect.java
@@ -2,6 +2,10 @@
import java.util.ArrayList;
import java.util.List;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.vo.account.LoginUser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -12,8 +16,6 @@
import com.xiaopeng.common.core.web.domain.BaseEntity;
import com.xiaopeng.common.datascope.annotation.DataScope;
import com.xiaopeng.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
/**
 * 数据过滤处理
xp-common/xp-common-log/src/main/java/com/xiaopeng/common/log/service/AsyncLogService.java
@@ -1,8 +1,9 @@
package com.xiaopeng.common.log.service;
import com.xiaopeng.api.feignClient.operation.SysLogClient;
import com.xiaopeng.api.model.operation.SysOperLog;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.xiaopeng.common.core.constant.SecurityConstants;
import javax.annotation.Resource;
@@ -13,14 +14,15 @@
 */
@Service
public class AsyncLogService {
    @Resource
    private RemoteLogService remoteLogService;
    private SysLogClient sysLogClient;
    /**
     * 保存系统日志记录
     */
    @Async
    public void saveSysLog(SysOperLog sysOperLog) throws Exception {
        remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER);
        sysLogClient.saveLog(sysOperLog);
    }
}
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/annotation/EnableCustomConfig.java
@@ -20,7 +20,7 @@
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 指定要扫描的Mapper类的包的路径
@MapperScan("com.ruoyi.**.mapper")
@MapperScan("com.xiaopeng.**.mapper")
// 开启线程异步执行
@EnableAsync
// 自动加载类
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/annotation/EnableRyFeignClients.java
@@ -17,7 +17,7 @@
{
    String[] value() default {};
    String[] basePackages() default { "com.ruoyi" };
    String[] basePackages() default { "com.xiaopeng" };
    Class<?>[] basePackageClasses() default {};
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/aspect/PreAuthorizeAspect.java
@@ -31,9 +31,9 @@
    /**
     * 定义AOP签名 (切入所有使用鉴权注解的方法)
     */
    public static final String POINTCUT_SIGN = " @annotation(com.ruoyi.common.security.annotation.RequiresLogin) || "
            + "@annotation(com.ruoyi.common.security.annotation.RequiresPermissions) || "
            + "@annotation(com.ruoyi.common.security.annotation.RequiresRoles)";
    public static final String POINTCUT_SIGN = " @annotation(com.xiaopeng.common.security.annotation.RequiresLogin) || "
            + "@annotation(com.xiaopeng.common.security.annotation.RequiresPermissions) || "
            + "@annotation(com.xiaopeng.common.security.annotation.RequiresRoles)";
    /**
     * 声明AOP签名
xp-common/xp-common-security/src/main/java/com/xiaopeng/common/security/service/TokenService.java
@@ -5,6 +5,7 @@
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.common.core.exception.auth.NotLoginException;
import com.xiaopeng.api.vo.account.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
@@ -65,7 +66,34 @@
        rspMap.put("expires_in", expireTime);
        return rspMap;
    }
    /**
     * 运维人员创建令牌
     * @param userInfo
     * @return
     */
    public Map<String, Object> createOperationUserToken(LoginOperationUser userInfo) {
        String token = IdUtils.fastUUID();
        Long userId = userInfo.getXpOperationsUser().getId();
        String userName = userInfo.getXpOperationsUser().getPhoneNumber();
        userInfo.setToken(token);
        userInfo.setId(userId);
        userInfo.setUsername(userName);
        userInfo.setIpaddr(IpUtils.getIpAddr());
        refreshTokenOperationUser(userInfo);
        // Jwt存储信息
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(SecurityConstants.OPERATION_USER_KEY, token);
        claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
        claimsMap.put(SecurityConstants.USER_TYPE, "operation");
        claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
        // 接口返回信息
        Map<String, Object> rspMap = new HashMap<String, Object>();
        rspMap.put("access_token", JwtUtils.createToken(claimsMap));
        rspMap.put("expires_in", expireTime);
        return rspMap;
    }
    /**
     * 获取用户身份信息
     *
@@ -78,7 +106,20 @@
        }
        return loginUser;
    }
    /**
     * 获取运维人员登录信息
     *
     * @return 用户信息
     */
    public LoginOperationUser getLoginOperationUser() {
        LoginOperationUser loginUser = getLoginOperationUser(ServletUtils.getRequest());
        if (loginUser == null) {
            throw new NotLoginException("令牌已过期,请重新登录!");
        }
        return loginUser;
    }
    /**
     * 获取用户身份信息
     *
@@ -88,6 +129,16 @@
        // 获取请求携带的令牌
        String token = SecurityUtils.getToken(request);
        return getLoginUser(token);
    }
    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public LoginOperationUser getLoginOperationUser(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = SecurityUtils.getToken(request);
        return getLoginOperationUser(token);
    }
    
    /**
@@ -100,6 +151,23 @@
        try {
            if (StringUtils.isNotEmpty(token)) {
                String userkey = JwtUtils.getUserKey(token);
                user = redisService.getCacheObject(getTokenKey(userkey));
                return user;
            }
        } catch (Exception e) {
        }
        return user;
    }
    /**
     * 获取运维用户身份信息
     *
     * @return 用户信息
     */
    public LoginOperationUser getLoginOperationUser(String token) {
        LoginOperationUser user = null;
        try {
            if (StringUtils.isNotEmpty(token)) {
                String userkey = JwtUtils.getOperationUserKey(token);
                user = redisService.getCacheObject(getTokenKey(userkey));
                return user;
            }
@@ -152,6 +220,18 @@
        String tokenKey = getTokenKey(loginUser.getToken());
        redisService.setCacheObject(tokenKey, loginUser, expireTime, TimeUnit.MINUTES);
    }
    /**
     * 刷新运维APP端令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshTokenOperationUser(LoginOperationUser loginUser) {
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String tokenKey = getTokenKey(loginUser.getToken());
        redisService.setCacheObject(tokenKey, loginUser, expireTime, TimeUnit.MINUTES);
    }
    
    private String getTokenKey(String token) {
        return ACCESS_TOKEN + token;
xp-gateway/src/main/java/com/xiaopeng/gateway/GatewayApplication.java
New file
@@ -0,0 +1,19 @@
package com.xiaopeng.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
 * 网关启动程序
 *
 * @author ruoyi
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  网关启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-gateway/src/main/java/com/xiaopeng/gateway/RuoYiGatewayApplication.java
File was deleted
xp-gateway/src/main/java/com/xiaopeng/gateway/config/CaptchaConfig.java
@@ -62,7 +62,7 @@
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
        // 验证码文本生成器
        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.xiaopeng.gateway.config.KaptchaTextCreator");
        // 验证码文本字符间距 默认为2
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
        // 验证码文本字符长度 默认为5
xp-modules/xp-file/src/main/resources/logback.xml
@@ -58,7 +58,7 @@
    </appender>
    <!-- 系统模块日志级别控制  -->
    <logger name="com.ruoyi" level="info" />
    <logger name="com.xiaopeng" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
xp-modules/xp-job/src/main/resources/logback.xml
@@ -58,7 +58,7 @@
    </appender>
    <!-- 系统模块日志级别控制  -->
    <logger name="com.ruoyi" level="info" />
    <logger name="com.xiaopeng" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
xp-service/xp-account/src/main/java/com/xiaopeng/account/AccountApplication.java
@@ -25,6 +25,6 @@
public class AccountApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  账户模块启动成功   ლ(´ڡ`ლ)゙  ");
        System.out.println("(♥◠‿◠)ノ゙  账户模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/TokenController.java
@@ -4,14 +4,24 @@
import javax.servlet.http.HttpServletRequest;
import com.xiaopeng.account.service.ISysUserService;
import com.xiaopeng.account.service.SysLoginService;
import com.xiaopeng.account.service.XpOperationsUserService;
import com.xiaopeng.account.service.impl.SysLoginService;
import com.xiaopeng.account.vo.LoginBody;
import com.xiaopeng.account.vo.RegisterBody;
import com.xiaopeng.api.dto.operation.AppLoginCodeDTO;
import com.xiaopeng.api.dto.operation.AppLoginGetCodeDTO;
import com.xiaopeng.api.dto.operation.AppLoginPasswordDTO;
import com.xiaopeng.api.dto.operation.UpdatePasswordDTO;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.SysRoleBak;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.api.vo.account.LoginUser;
import com.xiaopeng.common.core.constant.VerificationCodeConstants;
import com.xiaopeng.common.redis.service.RedisService;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,6 +35,7 @@
import com.xiaopeng.common.security.utils.SecurityUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * token 控制
@@ -33,7 +44,6 @@
 */
@Slf4j
@RestController
@RequestMapping("/base/v1")
public class TokenController {
    @Autowired
    private TokenService tokenService;
@@ -43,20 +53,22 @@
    @Resource
    private ISysUserService sysUserService;
    @ApiOperation(value = "用户登录", tags = "管理后台-用户登录")
    @PostMapping("/login")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> login(@RequestBody LoginBody form, HttpServletRequest request) {
        // 用户登录
        LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword(), request);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", tokenService.createToken(userInfo));
        List<SysRole> roles = userInfo.getSysUser().getRoles();
        if(CollectionUtils.isEmpty(roles)){
    @Resource
    private XpOperationsUserService xpOperationsUserService;
    @Autowired
    private RedisService redisService;
    @ApiOperation(value = "用户登录", tags = "管理后台-用户登录")
    @PostMapping("login")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> login(@RequestBody LoginBody form, HttpServletRequest request) {
        // 用户登录
        LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword(), request);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", tokenService.createToken(userInfo));
        List<SysRole> roles = userInfo.getSysUser().getRoles();
        if (CollectionUtils.isEmpty(roles)) {
            return R.fail("请关联角色!");
        }
        map.put("roleName",roles.get(0).getRoleName());
@@ -65,39 +77,118 @@
        SysUser sysUser = new SysUser();
        sysUser.setId(userInfo.getSysUser().getId());
        sysUserService.updateById(sysUser);
        return R.ok(map);
    }
    @DeleteMapping("logout")
    public R<?> logout(HttpServletRequest request) {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isNotEmpty(token)) {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            sysLoginService.logout(username, request);
        return R.ok(map);
    }
    @ApiOperation(value = "账号密码登录", tags = {"运维APP登录"})
    @PostMapping("base/v1/operationPasswordLogin")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> operationPasswordLogin(@RequestBody AppLoginPasswordDTO appLoginPasswordDTO, HttpServletRequest request) {
        // 用户登录
        LoginOperationUser userInfo = sysLoginService.operationPasswordLogin(appLoginPasswordDTO.getPhoneNumber(), appLoginPasswordDTO.getPassword(), request);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", tokenService.createOperationUserToken(userInfo));
        List<SysRole> roles = userInfo.getXpOperationsUser().getRoles();
        if (CollectionUtils.isEmpty(roles)) {
            return R.fail("请关联角色!");
        }
        map.put("roleName", roles.get(0).getRoleName());
        map.put("info", userInfo);
        return R.ok(map);
    }
    @ApiOperation(value = "手机验证码登录", tags = {"运维APP登录"})
    @PostMapping("base/v1/verificationCodeLogin")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> verificationCodeLogin(@RequestBody AppLoginCodeDTO appLoginCodeDTO, HttpServletRequest request) {
        // 用户登录
        LoginOperationUser userInfo = sysLoginService.verificationCodeLogin(appLoginCodeDTO.getPhoneNumber(), appLoginCodeDTO.getVerificationCode(), request);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", tokenService.createOperationUserToken(userInfo));
        List<SysRole> roles = userInfo.getXpOperationsUser().getRoles();
        if (CollectionUtils.isEmpty(roles)) {
            return R.fail("请关联角色!");
        }
        map.put("roleName", roles.get(0).getRoleName());
        map.put("info", userInfo);
        return R.ok(map);
    }
    @ApiOperation(value = "获取手机验证码", tags = {"运维APP登录"})
    @PostMapping("base/v1/getVerificationCode")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> verificationCodeLogin(@RequestBody AppLoginGetCodeDTO appLoginPasswordDTO) {
        XpOperationsUser xpOperationsUser = xpOperationsUserService.lambdaQuery()
                .eq(XpOperationsUser::getPhoneNumber, appLoginPasswordDTO.getPhoneNumber())
                .last("limit 1").one();
        if (xpOperationsUser == null) {
            return R.fail("账号不存在!");
        }
        if (!xpOperationsUser.getStatus()) {
            return R.fail("账号已禁用!");
        }
        // todo 后续补充验证码
        // 生成6位数短信验证码
        String code = String.valueOf((int) (Math.random() * 1000000));
        String codeType = "";
        switch (appLoginPasswordDTO.getCodeType()) {
            case 1:
                codeType = VerificationCodeConstants.LOGIN_CODE;
                break;
            case 2:
                codeType = VerificationCodeConstants.FORGET_PASSWORD_CODE;
                break;
            case 3:
                codeType = VerificationCodeConstants.UPDATE_PASSWORD_CODE;
                break;
        }
        redisService.setCacheObject(codeType+appLoginPasswordDTO.getPhoneNumber(), code, 60L, TimeUnit.SECONDS);
        return R.ok();
    }
    @ApiOperation(value = "修改密码", tags = {"运维APP登录"})
    @PostMapping("base/v1/updatePassword")
    @GlobalTransactional(rollbackFor = Exception.class)//分布式事务
    public R<?> updatePassword(@RequestBody UpdatePasswordDTO updatePasswordDTO, HttpServletRequest request) {
        // 用户登录
        if (sysLoginService.verificationCodeUpdate(updatePasswordDTO, request)){
            return R.ok("修改成功,请重新登录");
        }else{
            return R.fail("修改失败");
        }
        return R.ok();
    }
    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser)) {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }
    @PostMapping("register")
    public R<?> register(@RequestBody RegisterBody registerBody, HttpServletRequest request) {
        // 用户注册
        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword(), request);
        return R.ok();
    }
    @DeleteMapping("logout")
    public R<?> logout(HttpServletRequest request) {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isNotEmpty(token)) {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            sysLoginService.logout(username, request);
        }
        return R.ok();
    }
    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser)) {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }
    @PostMapping("register")
    public R<?> register(@RequestBody RegisterBody registerBody, HttpServletRequest request) {
        // 用户注册
        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword(), request);
        return R.ok();
    }
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/SysLoginService.java
File was deleted
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/XpOperationsUserNotificationService.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
/**
 * <p>
 * 运维人员消息通知表 服务类
 * </p>
 *
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpOperationsUserNotificationService extends IService<XpOperationsUserNotification> {
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/XpOperationsUserService.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.account.XpOperationsUser;
/**
 * <p>
 * 运维人员 服务类
 * </p>
 *
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpOperationsUserService extends IService<XpOperationsUser> {
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysLoginService.java
New file
@@ -0,0 +1,232 @@
package com.xiaopeng.account.service.impl;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.xiaopeng.api.dto.operation.UpdatePasswordDTO;
import com.xiaopeng.account.service.ISysPermissionService;
import com.xiaopeng.account.service.ISysUserService;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.api.model.operation.SysMenu;
import com.xiaopeng.api.vo.account.LoginUser;
import com.xiaopeng.common.core.constant.VerificationCodeConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.constant.UserConstants;
import com.xiaopeng.common.core.enums.UserStatus;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.text.Convert;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.ip.IpUtils;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.common.security.utils.SecurityUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;
/**
 * 登录校验方法
 *
 * @author xiaopeng
 */
@Component
public class SysLoginService {
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private SysRecordLogService recordLogService;
    @Autowired
    private RedisService redisService;
    @Resource
    private ISysPermissionService permissionService;
    @Resource
    private ISysUserService userService;
    @Resource
    private XpOperationsUserService operationsUserService;
    /**
     * 登录
     */
    public LoginUser login(String username, String password, HttpServletRequest request) {
        username = username.trim();
        // 查询用户信息
        SysUser user = userService.selectUserByUserName(username);
        if (StringUtils.isNull(user)) {
            throw new ServiceException("登录失败,请稍后重试");
        }
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        List<SysMenu> menuPermission = permissionService.getMenuPermission(user);
        LoginUser userInfo = new LoginUser();
        userInfo.setSysUser(user);
        userInfo.setRoles(roles);
        userInfo.setPermissions(menuPermission);
        if (StringUtils.isNull(user)) {
            recordLogService.recordLogininfor(request, null, username, Constants.LOGIN_FAIL_STATUS, "登录用户不存在");
            throw new ServiceException("用户名/密码错误");
        }
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "用户/密码必须填写");
            throw new ServiceException("用户/密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "用户密码不在指定范围");
            throw new ServiceException("用户密码不在指定范围");
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "用户名不在指定范围");
            throw new ServiceException("用户名不在指定范围");
        }
        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "很遗憾,访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾,访问IP已被列入系统黑名单");
        }
        if (user.getDeleted()) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "对不起,您的账号已被删除");
            throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_FAIL_STATUS, "用户已停用,请联系管理员");
            throw new ServiceException("对不起,您的账号:" + username + " 已停用");
        }
        passwordService.validate(user, password, request);
        // recordLogService.recordLogininfor(request, user.getId().intValue(), username, Constants.LOGIN_SUCCESS_STATUS, "登录成功");
        return userInfo;
    }
    public void logout(String loginName, HttpServletRequest request) {
        recordLogService.recordLogininfor(request, null, loginName, Constants.LOGIN_SUCCESS_STATUS, "退出成功");
    }
    /**
     * 注册
     */
    public void register(String username, String password, HttpServletRequest request) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            throw new ServiceException("用户/密码必须填写");
        }
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            throw new ServiceException("账户长度必须在2到20个字符之间");
        }
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new ServiceException("密码长度必须在5到20个字符之间");
        }
        // 注册用户信息
        SysUser sysUser = new SysUser();
        sysUser.setNickName(username);
        sysUser.setPassword(SecurityUtils.encryptPassword(password));
//        R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
//
//        if (R.FAIL == registerResult.getCode()) {
//            throw new ServiceException(registerResult.getMsg());
//        }
        recordLogService.recordLogininfor(request, sysUser.getId().intValue(), username, Constants.LOGIN_SUCCESS_STATUS, "注册成功");
    }
    public LoginOperationUser operationPasswordLogin(String phoneNumber, String password, HttpServletRequest request) {
        LoginOperationUser loginOperationUser = new LoginOperationUser();
        phoneNumber = phoneNumber.trim();
        // 查询运维用户信息
        XpOperationsUser operationsUser = operationsUserService.lambdaQuery().eq(
                XpOperationsUser::getPhoneNumber, phoneNumber
        ).last("limit 1").one();
        if (StringUtils.isNull(operationsUser)) {
            throw new ServiceException("账号或密码错误!");
        }
        if (!operationsUser.getStatus()){
            throw new ServiceException("账号已禁用!");
        }
        // todo 查询运维人员角色集合
        // todo 权限集合
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(phoneNumber, password)) {
            throw new ServiceException("用户/验证码必须填写");
        }
        passwordService.validateOperationsUser(operationsUser, password, request);
        loginOperationUser.setXpOperationsUser(operationsUser);
        return loginOperationUser;
    }
    public LoginOperationUser verificationCodeLogin(String phoneNumber, String code, HttpServletRequest request) {
        LoginOperationUser loginOperationUser = new LoginOperationUser();
        phoneNumber = phoneNumber.trim();
        // 查询运维用户信息
        XpOperationsUser operationsUser = operationsUserService.lambdaQuery().eq(
                XpOperationsUser::getPhoneNumber, phoneNumber
        ).last("limit 1").one();
        if (StringUtils.isNull(operationsUser)) {
            throw new ServiceException("验证码错误!");
        }
        if (!operationsUser.getStatus()){
            throw new ServiceException("账号已禁用!");
        }
        if (StringUtils.isAnyBlank(phoneNumber, code)) {
            throw new ServiceException("用户/验证码必须填写");
        }
        String verificationCode = redisService.getCacheObject(VerificationCodeConstants.LOGIN_CODE + phoneNumber);
        if (StringUtils.isBlank(verificationCode)){
            throw new ServiceException("验证码已过期!");
        }
        if (!verificationCode.equals(code)){
            throw new ServiceException("验证码错误!");
        }
        // todo 查询运维人员角色集合
        // todo 权限集合
        loginOperationUser.setXpOperationsUser(operationsUser);
        return loginOperationUser;
    }
    public Boolean verificationCodeUpdate(UpdatePasswordDTO updatePasswordDTO, HttpServletRequest request) {
        String phoneNumber = updatePasswordDTO.getPhoneNumber();
        String code = updatePasswordDTO.getVerificationCode();
        phoneNumber = phoneNumber.trim();
        // 查询运维用户信息
        XpOperationsUser operationsUser = operationsUserService.lambdaQuery().eq(
                XpOperationsUser::getPhoneNumber, phoneNumber
        ).last("limit 1").one();
        if (StringUtils.isNull(operationsUser)) {
            throw new ServiceException("验证码错误!");
        }
        if (!operationsUser.getStatus()){
            throw new ServiceException("账号已禁用!");
        }
        if (StringUtils.isAnyBlank(phoneNumber, code)) {
            throw new ServiceException("用户/验证码必须填写");
        }
        String verificationCode = redisService.getCacheObject(VerificationCodeConstants.UPDATE_PASSWORD_CODE + phoneNumber);
        if (StringUtils.isBlank(verificationCode)){
            throw new ServiceException("验证码已过期!");
        }
        if (!verificationCode.equals(code)){
            throw new ServiceException("验证码错误!");
        }
        if (!updatePasswordDTO.getNewPassword().equals(updatePasswordDTO.getConfirmPassword())){
            throw new ServiceException("新密码和确认密码不一致!");
        }
        operationsUser.setPassword(SecurityUtils.encryptPassword(updatePasswordDTO.getNewPassword()));
        return operationsUserService.updateById(operationsUser);
    }
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysPasswordService.java
File was renamed from xp-service/xp-account/src/main/java/com/xiaopeng/account/service/SysPasswordService.java
@@ -1,8 +1,9 @@
package com.xiaopeng.account.service;
package com.xiaopeng.account.service.impl;
import java.util.concurrent.TimeUnit;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xiaopeng.common.core.constant.CacheConstants;
@@ -77,6 +78,10 @@
    {
        return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
    }
    public boolean matchesOperationsUser(XpOperationsUser user, String rawPassword)
    {
        return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
    }
    public void clearLoginRecordCache(String loginName)
    {
@@ -85,4 +90,32 @@
            redisService.deleteObject(getCacheKey(loginName));
        }
    }
    public void validateOperationsUser(XpOperationsUser operationsUser, String password, HttpServletRequest request) {
        String phoneNumber = operationsUser.getPhoneNumber();
        Integer retryCount = redisService.getCacheObject(getCacheKey(phoneNumber));
        if (retryCount == null)
        {
            retryCount = 0;
        }
        if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
        {
            String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime);
            throw new ServiceException(errMsg);
        }
        if (!matchesOperationsUser(operationsUser, password))
        {
            retryCount = retryCount + 1;
            redisService.setCacheObject(getCacheKey(phoneNumber), retryCount, lockTime, TimeUnit.MINUTES);
            throw new ServiceException("用户名/密码错误");
        }
        else
        {
            clearLoginRecordCache(phoneNumber);
        }
    }
}
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysRecordLogService.java
File was renamed from xp-service/xp-account/src/main/java/com/xiaopeng/account/service/SysRecordLogService.java
@@ -1,4 +1,4 @@
package com.xiaopeng.account.service;
package com.xiaopeng.account.service.impl;
import com.xiaopeng.api.model.operation.SysLoginLog;
import org.springframework.stereotype.Component;
xp-service/xp-account/src/main/java/com/xiaopeng/account/vo/AddCompanyUserDto.java
@@ -1,6 +1,6 @@
package com.xiaopeng.account.vo;
import com.ruoyi.system.api.domain.SysUser;
import com.xiaopeng.api.model.account.SysUser;
import lombok.Data;
import javax.validation.constraints.NotNull;
xp-service/xp-account/src/main/java/com/xiaopeng/account/vo/CompanyUserVo.java
@@ -1,7 +1,6 @@
package com.xiaopeng.account.vo;
//import com.ruoyi.management.api.model.TCompanyShop;
import com.ruoyi.system.api.domain.SysUser;
import com.xiaopeng.api.model.account.SysUser;
import lombok.Data;
import javax.validation.constraints.NotBlank;
xp-service/xp-automaticPilot/src/main/java/com/xiaopeng/automaticPilot/AutomaticPilotApplication.java
@@ -24,6 +24,6 @@
public class AutomaticPilotApplication {
    public static void main(String[] args) {
        SpringApplication.run(AutomaticPilotApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  自动驾驶模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  自动驾驶模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-itinerary/src/main/java/com/xiaopeng/itinerary/ItineraryApplication.java
@@ -24,6 +24,6 @@
public class ItineraryApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItineraryApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  行程模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  行程模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/MaintenanceApplication.java
@@ -24,6 +24,6 @@
public class MaintenanceApplication {
    public static void main(String[] args) {
        SpringApplication.run(MaintenanceApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  运维模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  运维模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/controller/WorkbenchController.java
New file
@@ -0,0 +1,55 @@
package com.xiaopeng.maintenance.controller;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.maintenance.query.WorkBenchQuery;
import com.xiaopeng.maintenance.service.XpTaskService;
import com.xiaopeng.maintenance.vo.WorkBenchVO;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * token 控制
 *
 * @author ruoyi
 */
@Slf4j
@RestController
@Api(tags = "运维APP-工作台")
public class WorkbenchController {
    @Autowired
    private TokenService tokenService;
    @Resource
    private XpTaskService xpTaskService;
    @Autowired
    private RedisService redisService;
    @ApiOperation(value = "工作台")
    @PostMapping("/api/v1/workbench")
    public R<PageInfo<WorkBenchVO>> workbench(@RequestBody WorkBenchQuery query) {
        LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser();
        query.setOperationId(loginOperationUser.getId());
        // 获取任务记录
        PageInfo<WorkBenchVO> pageInfo= xpTaskService.workbench( query);
        return R.ok(pageInfo);
    }
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpTaskMapper.java
@@ -1,16 +1,24 @@
package com.xiaopeng.maintenance.mapper;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.query.WorkBenchQuery;
import com.xiaopeng.maintenance.vo.WorkBenchVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
 * 任务管理 Mapper 接口
 * </p>
 *
 * @author mitao
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpTaskMapper extends BaseMapper<XpTask> {
    List<WorkBenchVO> workbench(@Param("pageInfo") PageInfo<WorkBenchVO> pageInfo, @Param("query")WorkBenchQuery query);
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/query/WorkBenchQuery.java
New file
@@ -0,0 +1,13 @@
package com.xiaopeng.maintenance.query;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "运维APP工作台DTO")
public class WorkBenchQuery extends BasePage {
    @ApiModelProperty(value = "当前登陆人id")
    private Long operationId;
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.maintenance.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.query.WorkBenchQuery;
import com.xiaopeng.maintenance.vo.WorkBenchVO;
/**
 * <p>
 * 任务管理 服务类
 * </p>
 *
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpTaskService extends IService<XpTask> {
    PageInfo<WorkBenchVO> workbench(WorkBenchQuery query);
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/XpVehicleService.java
New file
@@ -0,0 +1,17 @@
package com.xiaopeng.maintenance.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.maintenance.XpVehicle;
/**
 * <p>
 * 车辆管理 服务类
 * </p>
 *
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpVehicleService extends IService<XpVehicle> {
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -1,20 +1,32 @@
package com.xiaopeng.maintenance.service.impl;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.api.mapper.XpTaskMapper;
import com.xiaopeng.api.service.IXpTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.query.WorkBenchQuery;
import com.xiaopeng.maintenance.service.XpTaskService;
import com.xiaopeng.maintenance.vo.WorkBenchVO;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * <p>
 * 任务管理 服务实现类
 * </p>
 *
 * @author mitao
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
@Service
public class XpTaskServiceImpl extends ServiceImpl<XpTaskMapper, XpTask> implements IXpTaskService {
public class XpTaskServiceImpl extends ServiceImpl<XpTaskMapper, XpTask> implements XpTaskService {
    @Override
    public PageInfo<WorkBenchVO> workbench(WorkBenchQuery query) {
        PageInfo<WorkBenchVO> pageInfo = new PageInfo<>(query.getPageCurr(),query.getPageSize());
        List<WorkBenchVO> list = this.baseMapper.workbench(pageInfo,query);
        pageInfo.setRecords( list);
     return pageInfo;
    }
}
xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/vo/WorkBenchVO.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.maintenance.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.xiaopeng.api.model.maintenance.XpTask;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import okhttp3.internal.concurrent.Task;
import java.io.Serializable;
@Data
@ApiModel(value = "运维APP工作台VO")
public class WorkBenchVO extends XpTask {
    @ApiModelProperty(value = "车辆颜色")
    private String vehicleColor;
    @ApiModelProperty(value = "车辆图片")
    private String vehiclePictures;
    @ApiModelProperty(value = "车辆vin码")
    private String vehicleVin;
    @ApiModelProperty(value = "车牌号")
    private String plateNumber;
    @ApiModelProperty(value = "任务类型名称")
    private String taskTypeName;
}
xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpTaskMapper.xml
@@ -2,4 +2,45 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.maintenance.mapper.XpTaskMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.maintenance.XpTask">
        <id column="id" property="id" />
        <result column="task_code" property="taskCode" />
        <result column="task_category" property="taskCategory" />
        <result column="task_type_id" property="taskTypeId" />
        <result column="task_urgency_level" property="taskUrgencyLevel" />
        <result column="task_description" property="taskDescription" />
        <result column="vehicle_location" property="vehicleLocation" />
        <result column="vehicle_id" property="vehicleId" />
        <result column="vehicle_lon" property="vehicleLon" />
        <result column="vehicle_lat" property="vehicleLat" />
        <result column="handle_user_id" property="handleUserId" />
        <result column="handle_time" property="handleTime" />
        <result column="assignee_user_id" property="assigneeUserId" />
        <result column="assignee_time" property="assigneeTime" />
        <result column="report_user_id" property="reportUserId" />
        <result column="report_time" property="reportTime" />
        <result column="status" property="status" />
        <result column="is_deleted" property="isDeleted" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
        <result column="update_by" property="updateBy" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, task_code, task_category, task_type_id, task_urgency_level, task_description, vehicle_location, vehicle_id, vehicle_lon, vehicle_lat, handle_user_id, handle_time, assignee_user_id, assignee_time, report_user_id, report_time, status, is_deleted, create_time, update_time, create_by, update_by
    </sql>
    <select id="workbench" resultType="com.xiaopeng.maintenance.vo.WorkBenchVO">
        select t1.*,t2.vehicle_vin as vehicleVin,t2.plate_number as plateNumber,
               t2.vehicle_color as vehicleColor,t2.vehicle_pictures as vehiclePictures
        from xp_task t1
            left join xp_vehicle t2 on t1.vehicle_id = t2.id
        where t1.handle_user_id = #{query.operationId}
        and t1.status = 1
        and t1.is_deleted = 0
        order by t1.assignee_time asc
    </select>
</mapper>
xp-service/xp-map/pom.xml
@@ -88,6 +88,12 @@
            <version>2.6</version>
            <scope>compile</scope>
        </dependency>
        <!--mongodb-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>
    <build>
xp-service/xp-map/src/main/java/com/xiaopeng/map/MapApplication.java
@@ -24,6 +24,6 @@
public class MapApplication {
    public static void main(String[] args) {
        SpringApplication.run(MapApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  地图模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  地图模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/controller/ElectronicFenceController.java
New file
@@ -0,0 +1,44 @@
package com.xiaopeng.map.controller;
import com.xiaopeng.api.vo.operation.XpElectronicFenceVo;
import com.xiaopeng.common.core.web.controller.BaseController;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/base/v1/mini-program")
@Api(tags = "电子围栏")
public class ElectronicFenceController extends BaseController {
    private final XpElectronicFenceAreaService xpElectronicFenceAreaService;
    public ElectronicFenceController(XpElectronicFenceAreaService xpElectronicFenceAreaService) {
        this.xpElectronicFenceAreaService = xpElectronicFenceAreaService;
    }
    /**
     * 获取地图开放区域围栏
     * @return
     */
    @ApiOperation(value = "获取地图开放区域围栏",tags = {"小程序-获取地图开放区域围栏"},response = XpElectronicFenceVo.class)
    @GetMapping("/cities/list")
    public AjaxResult<List<XpElectronicFenceVo>> citiesList() {
        return success(xpElectronicFenceAreaService.citiesList());
    }
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/mapper/XpElectronicFenceAreaMapper.java
New file
@@ -0,0 +1,17 @@
package com.xiaopeng.map.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
/**
 * <p>
 * 电子围栏区域构成 Mapper 接口
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
public interface XpElectronicFenceAreaMapper extends BaseMapper<XpElectronicFenceArea> {
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/mapper/XpElectronicFenceMapper.java
New file
@@ -0,0 +1,17 @@
package com.xiaopeng.map.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpElectronicFence;
/**
 * <p>
 * 电子围栏 Mapper 接口
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
public interface XpElectronicFenceMapper extends BaseMapper<XpElectronicFence> {
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/XpElectronicFenceAreaService.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.map.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
import com.xiaopeng.api.vo.operation.XpElectronicFenceVo;
import java.util.List;
/**
 * <p>
 * 电子围栏区域构成 服务类
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
public interface XpElectronicFenceAreaService extends IService<XpElectronicFenceArea> {
    List<XpElectronicFenceVo> citiesList();
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/XpElectronicFenceService.java
New file
@@ -0,0 +1,30 @@
package com.xiaopeng.map.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpElectronicFence;
/**
 * <p>
 * 电子围栏 服务类
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
public interface XpElectronicFenceService extends IService<XpElectronicFence> {
    /**
     * 获取电子围栏列表
     */
    List<XpElectronicFenceVo> getXpElectronicFenceList(String cityCode);
    /**
     * 判断当前位置是否在运营区域内
     */
    Boolean isInElectronicFence(Double latitude, Double longitude,String cityCode);
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceAreaServiceImpl.java
New file
@@ -0,0 +1,28 @@
package com.xiaopeng.map.service.serviceimpl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
import com.xiaopeng.api.vo.operation.XpElectronicFenceVo;
import com.xiaopeng.map.mapper.XpElectronicFenceAreaMapper;
import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * <p>
 * 电子围栏区域构成 服务实现类
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
@Service
public class XpElectronicFenceAreaServiceImpl extends ServiceImpl<XpElectronicFenceAreaMapper, XpElectronicFenceArea> implements XpElectronicFenceAreaService {
    @Override
    public List<XpElectronicFenceVo> citiesList() {
        return null;
    }
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
New file
@@ -0,0 +1,82 @@
package com.xiaopeng.map.service.serviceimpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpElectronicFence;
import com.xiaopeng.api.model.operation.XpOpenCity;
import com.xiaopeng.api.vo.operation.XpElectronicFenceVo;
import com.xiaopeng.map.mapper.XpElectronicFenceAreaMapper;
import com.xiaopeng.map.mapper.XpElectronicFenceMapper;
import com.xiaopeng.map.service.XpElectronicFenceService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;
/**
 * <p>
 * 电子围栏 服务实现类
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
@Service
public class XpElectronicFenceServiceImpl extends ServiceImpl<XpElectronicFenceMapper, XpElectronicFence> implements XpElectronicFenceService {
    @Resource
    private XpOpenCityMapper xpOpenCityMapper;
    @Resource
    private XpElectronicFenceAreaMapper xpElectronicFenceAreaMapper;
    @Override
    public List<XpElectronicFenceVo> getXpElectronicFenceList(String cityCode) {
        // 通过code找到电子围栏信息
        // TODO 魔法数字
        List<XpOpenCity> xpOpenCities = xpOpenCityMapper.selectList(new LambdaQueryWrapper<XpOpenCity>().eq(XpOpenCity::getCityCode, cityCode).eq(XpOpenCity::getStatus, 1));
        if (!xpOpenCities.isEmpty()) {
            List<Long> openCityIds = xpOpenCities.stream().map(XpOpenCity::getId).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
    @Override
    public Boolean isInElectronicFence(Double latitude, Double longitude,String cityCode) {
        // 获取所有可用的电子围栏信息
        return null;
    }
    /**
     * 通过一个点位 判断是否在某个电子围栏内
     */
    private static boolean isInElectronicFence(double lon, double lat,List<String> fencePoints) {
        boolean contains = false;
        for (String fencePoint : fencePoints) {
            ArrayList<GeoPolygonUtil.GeoPoint> geoPoints = new ArrayList<>();
            String[] split = fencePoint.split(",");
            for (String lonLat : split) {
                String[] split1 = lonLat.split("_");
                GeoPolygonUtil.GeoPoint geoPoint = new GeoPolygonUtil.GeoPoint(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]));
                geoPoints.add(geoPoint);
            }
            contains = GeoPolygonUtil.contains(lon, lat, geoPoints);
            if(contains){
                // 一旦在范围中直接返回true
                return true;
            }
        }
        return false;
    }
}
xp-service/xp-map/src/main/java/com/xiaopeng/map/vo/GeoFencingPolygon.java
New file
@@ -0,0 +1,36 @@
package com.xiaopeng.map.vo;
import lombok.Data;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
 * 地理围栏-多边形
 * @author zhibing.pu
 * @date 2023/4/29 23:53
 */
@Data
@Document(collection = "geo_fencing")
public class GeoFencingPolygon implements Serializable {
    private static final long serialVersionUID = 4508868382007529971L;
    private String id;
    /**
     * 站点id
     */
    private Integer siteId;
    /**
     * 站点名称
     */
    private String name;
    /**
     * 多边形经纬度
     */
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPolygon geoJsonPolygon;
}
xp-service/xp-map/src/main/resources/mapper/XpElectronicFenceAreaMapper.xml
New file
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.map.mapper.XpElectronicFenceAreaMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.operation.XpElectronicFenceArea">
        <id column="id" property="id" />
        <result column="electronic_id" property="electronicId" />
        <result column="area_name" property="areaName" />
        <result column="area_type" property="areaType" />
        <result column="area_description" property="areaDescription" />
        <result column="area_status" property="areaStatus" />
        <result column="fence_points" property="fencePoints" />
        <result column="is_deleted" property="isDeleted" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
        <result column="update_by" property="updateBy" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, electronic_id, area_name, area_type, area_description, area_status, fence_points, is_deleted, create_time, update_time, create_by, update_by
    </sql>
</mapper>
xp-service/xp-map/src/main/resources/mapper/XpElectronicFenceMapper.xml
New file
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.map.mapper.XpElectronicFenceMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.operation.XpElectronicFence">
        <id column="id" property="id" />
        <result column="electronic_name" property="electronicName" />
        <result column="electronic_number" property="electronicNumber" />
        <result column="status" property="status" />
        <result column="effect_type" property="effectType" />
        <result column="effect_time" property="effectTime" />
        <result column="failure_type" property="failureType" />
        <result column="failure_time" property="failureTime" />
        <result column="operation_strategy" property="operationStrategy" />
        <result column="is_deleted" property="isDeleted" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
        <result column="update_by" property="updateBy" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, electronic_name, electronic_number, status, effect_type, effect_time, failure_type, failure_time, operation_strategy, is_deleted, create_time, update_time, create_by, update_by
    </sql>
</mapper>
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/OperationApplication.java
@@ -24,6 +24,6 @@
public class OperationApplication {
    public static void main(String[] args) {
        SpringApplication.run(OperationApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  运营模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  运营模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/IndexMapController.java
New file
@@ -0,0 +1,57 @@
package com.xiaopeng.operation.controller;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.operation.query.PointMapQuery;
import com.xiaopeng.operation.service.XpPointService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
 * token 控制
 *
 * @author ruoyi
 */
@Slf4j
@RestController
@Api(tags = "运维APP-地图导航")
public class IndexMapController {
    @Autowired
    private TokenService tokenService;
    @Resource
    private XpPointService xpPointService;
    @Autowired
    private RedisService redisService;
    @ApiOperation(value = "地图导航")
    @PostMapping("/api/v1/pointMap")
    public R<PageInfo<XpPoint>> pointMap(@RequestBody PointMapQuery query) {
        LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser();
        query.setOperationId(loginOperationUser.getId());
        // 获取任务记录
        PageInfo<XpPoint> pageInfo= xpPointService.pointMap( query);
        return R.ok(pageInfo);
    }
    @ApiOperation(value = "点位详情")
    @GetMapping("/api/v1/pointDetail")
    public R<XpPoint> pointDetail(@RequestParam(value = "点位id", required = true)Long id) {
        XpPoint xpPoint = xpPointService.getById(id);
        return R.ok(xpPoint);
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/SysOperlogController.java
@@ -4,6 +4,7 @@
import javax.servlet.http.HttpServletResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.security.annotation.Logical;
@@ -88,4 +89,16 @@
    public AjaxResult add(@RequestBody SysOperLog operLog) {
        return toAjax(operLogService.insertOperlog(operLog));
    }
    /**
     * 保存系统日志
     * @param sysOperLog
     * @return
     */
    @PostMapping("/saveLog")
    public R saveLog(@RequestBody SysOperLog sysOperLog) {
        operLogService.save(sysOperLog);
        return R.ok();
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java
@@ -22,11 +22,12 @@
public class XpAgreementController extends BaseController {
    private final XpAgreementService xpAgreementService;
    public XpAgreementController(XpAgreementService xpAgreementService) {
        this.xpAgreementService = xpAgreementService;
    }
    @ApiOperation(value = "获取协议",tags = {"小程序首页"},response = XpAgreementVo.class)
    @ApiOperation(value = "获取协议",tags = {"小程序-首页"},response = XpAgreementVo.class)
    @GetMapping("/privacy/content/{type}")
    public AjaxResult<XpAgreementVo> getContent(@PathVariable Integer type) {
        return success(xpAgreementService.getContentByType(type));
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpAgreementUserController.java
@@ -31,7 +31,7 @@
    /**
     * 用户同意隐私协议/法律条款操作
     */
    @ApiOperation(value = "用户同意隐私协议/法律条款",tags = {"用户协议"})
    @ApiOperation(value = "用户同意隐私协议/法律条款",tags = {"小程序-用户协议"})
    @PostMapping("/privacy/agreement")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public AjaxResult<?> privacyAgreement(@RequestBody XpAgreementAppUserDto dto, HttpServletRequest request) {
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpBannerController.java
@@ -27,8 +27,11 @@
    }
    // 获取banner列表
    @ApiOperation(value = "获取banner",tags = {"小程序首页"},response = XpBannerListVo.class)
    /**
     * 获取banner
     * @return
     */
    @ApiOperation(value = "获取banner",tags = {"小程序-获取banner"},response = XpBannerListVo.class)
    @GetMapping("/getBannerList")
    public AjaxResult<List<XpBannerListVo>> getBannerList() {
        return success(xpBannerService.getXpBannerList());
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpOpenCityController.java
@@ -28,7 +28,11 @@
    @ApiOperation(value = "获取开通城市列表",tags = {"小程序首页"},response = XpOpenCityVo.class)
    /**
     * 获取开通城市列表
     * @return
     */
    @ApiOperation(value = "获取开通城市列表",tags = {"小程序-开通城市列表"},response = XpOpenCityVo.class)
    @GetMapping("/cities/list")
    public AjaxResult<XpOpenCityVo> citiesList() {
        return success(xpOpenCityService.citiesList());
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpPointController.java
@@ -1,20 +1,41 @@
package com.xiaopeng.operation.controller;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.common.core.web.controller.BaseController;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.operation.dto.NearestDto;
import com.xiaopeng.operation.service.XpPointService;
import com.xiaopeng.operation.vo.NearestVo;
import com.xiaopeng.operation.vo.XpOpenCityVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.stereotype.Controller;
import javax.validation.Valid;
/**
 * <p>
 * 点位管理 前端控制器
 * </p>
 *
 * @author mitao
 * @since 2026-02-03
 */
@Controller
@RequestMapping("/xp-point")
public class XpPointController {
@Slf4j
@RestController
@RequestMapping("/base/v1/mini-program")
@Api(tags = "点位模块")
public class XpPointController extends BaseController {
    private final XpPointService xpPointService;
    public XpPointController(XpPointService xpPointService) {
        this.xpPointService = xpPointService;
    }
    /**
     * 获取附近上车站点
     */
    @ApiOperation(value = "获取附近上车站点",tags = {"小程序-附近上车站点"},response = XpPoint.class)
    @RequestMapping("/pickup/nearest")
    public AjaxResult<NearestVo> nearest(@RequestBody @Valid NearestDto dto) {
        return success(xpPointService.nearest(dto));
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java
@@ -1,20 +1,67 @@
package com.xiaopeng.operation.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.operation.service.XpRegionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.stereotype.Controller;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
/**
 * <p>
 * 省市区三级联动 前端控制器
 * 省市管理 前端控制器
 * </p>
 *
 * @author mitao
 * @since 2026-02-03
 */
@Controller
@RequestMapping("/xp-region")
@Api(tags = "省市管理")
@RestController
@RequestMapping("/base/v1/mini-program")
public class XpRegionController {
    private final XpRegionService regionService;
    @Autowired
    public XpRegionController(XpRegionService regionService) {
        this.regionService = regionService;
    }
    /**
     * 查询省市管理
     */
    @ApiOperation(value = "查询省市管理",tags = {"小程序-省市管理"},response = XpRegion.class)
    @GetMapping(value = "/open/t-region/getRegion")
    public R<List<List<XpRegion>>> geXpRegion() {
        return R.ok(regionService.getXpRegion());
    }
    /*
     * 查询市
     */
    @ApiOperation(value = "查询市",tags = {"小程序-查询市"},response = XpRegion.class)
    @PostMapping(value = "/open/t-region/getProvince")
    public R<List<XpRegion>> getProvince() {
        List<XpRegion> list = regionService.list(Wrappers.lambdaQuery(XpRegion.class).ne(XpRegion::getParentId, 0).orderByAsc(XpRegion::getInitial));
        return R.ok(list);
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/dto/NearestDto.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.operation.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "NearestDto", description = "附近上车站点")
public class NearestDto {
    @ApiModelProperty(value = "纬度")
    @NotNull(message = "纬度不能为空")
    private Double latitude;
    @ApiModelProperty(value = "经度")
    @NotNull(message = "经度不能为空")
    private Double longitude;
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpPointMapper.java
@@ -1,16 +1,24 @@
package com.xiaopeng.operation.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.operation.query.PointMapQuery;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
 * 点位管理 Mapper 接口
 * </p>
 *
 * @author mitao
 * @author liu
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpPointMapper extends BaseMapper<XpPoint> {
    List<XpPoint> pointMap(@Param("pageInfo") PageInfo<XpPoint> pageInfo,@Param("query") PointMapQuery query);
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/mapper/XpRegionMapper.java
@@ -1,5 +1,6 @@
package com.xiaopeng.operation.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpRegion;
@@ -8,7 +9,7 @@
 * 省市区三级联动 Mapper 接口
 * </p>
 *
 * @author mitao
 * @author liu
 * @since 2026-02-03
 */
public interface XpRegionMapper extends BaseMapper<XpRegion> {
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/query/PointMapQuery.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.operation.query;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.Data;
@Data
@ApiModel(value = "运维APP地图导航DTO")
public class PointMapQuery extends BasePage {
    @ApiModelProperty(value = "当前登陆人id 前端忽略")
    private Long operationId;
    @ApiModelProperty(value = "点位类型 1=运营点位 2=测试点位")
    private Integer pointType;
    @ApiModelProperty(value = "运营状态 1=待启用 2=启用中 3=已停用 4=已失效")
    private Integer operationStatus;
    @ApiModelProperty(value = "用户当前经度")
    private String lon;
    @ApiModelProperty(value = "用户当前纬度")
    private String lat;
    @ApiModelProperty(value = "点位名称")
    private String pointName;
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/XpPointService.java
New file
@@ -0,0 +1,30 @@
package com.xiaopeng.operation.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.operation.dto.NearestDto;
import com.xiaopeng.operation.vo.NearestVo;
import javax.validation.Valid;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.operation.query.PointMapQuery;
/**
 * <p>
 * 点位管理 服务类
 * </p>
 *
 * @author liu
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
public interface XpPointService extends IService<XpPoint> {
    /**
     * 获取附近上车站点
     */
    NearestVo nearest(@Valid NearestDto dto);
    PageInfo<XpPoint> pointMap(PointMapQuery query);
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/XpRegionService.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.operation.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpRegion;
import java.util.List;
/**
 * <p>
 * 省市区三级联动 服务类
 * </p>
 *
 * @author liu
 * @since 2026-02-03
 */
public interface XpRegionService extends IService<XpRegion> {
    /**
     * 查询省市管理
     * @return
     */
    List<List<XpRegion>> getXpRegion();
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
@@ -1,20 +1,74 @@
package com.xiaopeng.operation.service.impl;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.operation.mapper.XpPointMapper;
import com.xiaopeng.operation.service.IXpPointService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.operation.dto.NearestDto;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.operation.mapper.XpPointMapper;
import com.xiaopeng.operation.query.PointMapQuery;
import com.xiaopeng.operation.service.XpPointService;
import com.xiaopeng.operation.utils.map.FastDistanceCalculator;
import com.xiaopeng.operation.vo.NearestNextVo;
import com.xiaopeng.operation.vo.NearestVo;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
 * 点位管理 服务实现类
 * </p>
 *
 * @author mitao
 * @author liu
 * @author WuGuanFengYue
 * @since 2026-02-03
 */
@Service
public class XpPointServiceImpl extends ServiceImpl<XpPointMapper, XpPoint> implements IXpPointService {
public class XpPointServiceImpl extends ServiceImpl<XpPointMapper, XpPoint> implements XpPointService {
    @Override
    public NearestVo nearest(NearestDto dto) {
        // 获取所有的站点信息
        List<XpPoint> list = list(new LambdaQueryWrapper<XpPoint>().eq(XpPoint::getOperationStatus, 1));
        NearestVo nearestVo = new NearestVo();
        List<NearestNextVo> nearestNextVos = new ArrayList<>();
        for (XpPoint xpPoint : list) {
            // 计算距离 小于1000m的站点
            double v = FastDistanceCalculator.distanceFast(dto.getLatitude(), dto.getLongitude(), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < 1000) {
                NearestNextVo nearestNextVo = new NearestNextVo();
                nearestNextVo.setId(xpPoint.getId());
                nearestNextVo.setName(xpPoint.getPointName());
                nearestNextVo.setLatitude(xpPoint.getPointLat());
                nearestNextVo.setLongitude(xpPoint.getPointLon());
                nearestNextVo.setDistance(v);
                nearestNextVo.setAddress(xpPoint.getPointAddress());
                nearestNextVo.setTime(xpPoint.getParkingTimeLimit());
                nearestNextVos.add(nearestNextVo);
            }
        }
        if (!nearestNextVos.isEmpty()) {
            nearestNextVos = nearestNextVos.stream().sorted(Comparator.comparing(NearestNextVo::getDistance)).collect(Collectors.toList());
        }
        nearestVo.setPoints(nearestNextVos);
        nearestVo.setTotal(nearestNextVos.size());
        return nearestVo;
    }
    @Override
    public PageInfo<XpPoint> pointMap(PointMapQuery query) {
        PageInfo<XpPoint> pageInfo = new PageInfo<>(query.getPageCurr(),query.getPageSize());
        List<XpPoint> list = this.baseMapper.pointMap(pageInfo,query);
        pageInfo.setRecords( list);
        return pageInfo;
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java
@@ -1,20 +1,40 @@
package com.xiaopeng.operation.service.impl;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.operation.mapper.XpRegionMapper;
import com.xiaopeng.operation.service.IXpRegionService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.operation.mapper.XpRegionMapper;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.operation.service.XpRegionService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
 * 省市区三级联动 服务实现类
 * </p>
 *
 * @author mitao
 * @author liu
 * @since 2026-02-03
 */
@Service
public class XpRegionServiceImpl extends ServiceImpl<XpRegionMapper, XpRegion> implements IXpRegionService {
public class XpRegionServiceImpl extends ServiceImpl<XpRegionMapper, XpRegion> implements XpRegionService {
    @Override
    public List<List<XpRegion>> getXpRegion() {
        String[] initials = {"A", "B", "C", "D", "E", "F",
                "G", "H", "I", "J", "K", "L",
                "M", "N", "O", "P", "Q", "R",
                "S", "T", "U", "V", "W", "X", "Y", "Z"};
        List<XpRegion> tRegions = this.baseMapper.selectList(Wrappers.lambdaQuery(XpRegion.class));
        List<List<XpRegion>> result = new ArrayList<>();
        for (String initial : initials) {
            List<XpRegion> init = tRegions.stream().filter(e -> e.getInitial().equals(initial) && !e.getCode().contains("0000")).collect(Collectors.toList());
            result.add(init);
        }
        return result;
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/utils/XpPricingUtil.java
@@ -1,10 +1,6 @@
package com.xiaopeng.operation.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.operation.model.ServerCarModelWarpper;
import com.xiaopeng.operation.model.XpPricing;
import com.xiaopeng.operation.service.XpPricingService;
import com.xiaopeng.operation.utils.map.GDMapElectricFenceUtil;
import com.xiaopeng.operation.utils.map.GDMapGeocodingUtil;
@@ -12,7 +8,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.*;
/**
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/utils/map/FastDistanceCalculator.java
New file
@@ -0,0 +1,33 @@
package com.xiaopeng.operation.utils.map;
public class FastDistanceCalculator {
    private static final double R = 6371.0; // 地球半径(千米)
    private static final double DEG_TO_RAD = Math.PI / 180.0;
    /**
     * 快速近似算法 - 性能极高,误差<0.5%
     * 适合需要大量计算的场景(如KNN、聚类)
     */
    public static double distanceFast(double lat1, double lon1,
                                      double lat2, double lon2) {
        double x = (lon2 - lon1) * DEG_TO_RAD * Math.cos((lat1 + lat2) * 0.5 * DEG_TO_RAD);
        double y = (lat2 - lat1) * DEG_TO_RAD;
        return R * Math.sqrt(x * x + y * y);
    }
    /**
     * 平面近似 - 极高性能,适用于小范围(城市内)
     */
    public static double distanceFlatApprox(double lat1, double lon1,
                                           double lat2, double lon2) {
        // 每度纬度约111km,每度经度随纬度变化
        double kmPerDegreeLat = 111.0;
        double kmPerDegreeLon = 111.0 * Math.cos((lat1 + lat2) * 0.5 * DEG_TO_RAD);
        double dLat = lat2 - lat1;
        double dLon = lon2 - lon1;
        return Math.sqrt(Math.pow(dLat * kmPerDegreeLat, 2) +
                        Math.pow(dLon * kmPerDegreeLon, 2));
    }
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/vo/NearestNextVo.java
New file
@@ -0,0 +1,39 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "NearestNextVo对象", description = "附近站点二级Vo")
public class NearestNextVo {
    @ApiModelProperty(value = "站点id")
    private  Long id;
    @ApiModelProperty(value = "站点名称")
    private  String name;
    @ApiModelProperty(value = "站点经度")
    private  Double latitude;
    @ApiModelProperty(value = "站点纬度")
    private  Double longitude;
    @ApiModelProperty(value = "距离")
    private  Double distance;
    @ApiModelProperty(value = "站点地址")
    private  String address;
    @ApiModelProperty(value = "停车时长")
    private  Integer time;
    @ApiModelProperty(value = "开始时间")
    private  String startTime;
    @ApiModelProperty(value = "结束时间")
    private  String endTime;
}
xp-service/xp-operation/src/main/java/com/xiaopeng/operation/vo/NearestVo.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "NearestNextVo对象", description = "附近站点vo")
public class NearestVo {
    private List<NearestNextVo> points;
    private Integer total;
}
xp-service/xp-operation/src/main/resources/mapper/operation/XpPointMapper.xml
@@ -2,9 +2,69 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.operation.mapper.XpPointMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.operation.XpPoint">
        <id column="id" property="id" />
        <result column="point_name" property="pointName" />
        <result column="point_poi" property="pointPoi" />
        <result column="point_number" property="pointNumber" />
        <result column="operation_status" property="operationStatus" />
        <result column="point_type" property="pointType" />
        <result column="verification_status" property="verificationStatus" />
        <result column="parking_time_limit" property="parkingTimeLimit" />
        <result column="operation_type" property="operationType" />
        <result column="effective_period" property="effectivePeriod" />
        <result column="effective_time_period" property="effectiveTimePeriod" />
        <result column="remarks" property="remarks" />
        <result column="point_pictures" property="pointPictures" />
        <result column="point_lon" property="pointLon" />
        <result column="point_lat" property="pointLat" />
        <result column="is_deleted" property="isDeleted" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
        <result column="update_by" property="updateBy" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, point_name, point_poi, point_number, operation_status, point_type, verification_status, parking_time_limit, operation_type, effective_period, effective_time_period, remarks, point_pictures, point_lon, point_lat, is_deleted, create_time, update_time, create_by, update_by
    </sql>
    <select id="pointMap" resultType="com.xiaopeng.api.model.operation.XpPoint">
        select t1.*,
        ROUND(
        6378.138 * 2 * ASIN(
        SQRT(
        POW(
        SIN(
        (
        #{query.lat} * PI() / 180 - t1.point_lat * PI() / 180
        ) / 2
        ),
        2
        ) + COS(#{query.lat} * PI() / 180) * COS(t1.point_lat * PI() / 180) * POW(
        SIN(
        (
        #{query.lon} * PI() / 180 - t1.point_lon * PI() / 180
        ) / 2
        ),
        2
        )
        )
        ) * 1000
        ) AS distance
               from xp_point t1
        where t1.is_deleted = 0
        <if test="query.pointName != null and query.pointName != ''">
            and t1.point_name like concat('%',#{query.pointName},'%')
        </if>
        <if test="query.pointType != null">
            and t1.point_type = #{query.pointType}
        </if>
        <if test="query.operationStatus != null">
            and t1.operation_status = #{query.operationStatus}
        </if>
        order by distance  asc
    </select>
</mapper>
xp-service/xp-operation/src/main/resources/mapper/operation/XpRegionMapper.xml
@@ -2,9 +2,19 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.operation.mapper.XpRegionMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.operation.XpRegion">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="code" property="code" />
        <result column="citycode" property="citycode" />
        <result column="parent_id" property="parentId" />
        <result column="english" property="english" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, code, citycode, parentId, english, initial, lat, lon
        id, name, code, citycode, parent_id, english
    </sql>
</mapper>
xp-service/xp-order/src/main/java/com/xiaopeng/order/OrderApplication.java
@@ -24,6 +24,6 @@
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  订单模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  订单模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-payment/src/main/java/com/xiaopeng/payment/PaymentApplication.java
@@ -24,6 +24,6 @@
public class PaymentApplication {
    public static void main(String[] args) {
        SpringApplication.run(PaymentApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  支付模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  支付模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-pushMessage/src/main/java/com/xiaopeng/pushMessage/PushMessageApplication.java
@@ -24,6 +24,6 @@
public class PushMessageApplication {
    public static void main(String[] args) {
        SpringApplication.run(PushMessageApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  消息推送模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  消息推送模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-remoteDriving/src/main/java/com/xiaopeng/remoteDriving/RemoteDrivingApplication.java
@@ -24,6 +24,6 @@
public class RemoteDrivingApplication {
    public static void main(String[] args) {
        SpringApplication.run(RemoteDrivingApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  远程驾驶模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  远程驾驶模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-vehicleConvoy/src/main/java/com/xiaopeng/vehicleConvoy/VehicleConvoyApplication.java
@@ -24,6 +24,6 @@
public class VehicleConvoyApplication {
    public static void main(String[] args) {
        SpringApplication.run(VehicleConvoyApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  车辆车队模块启动成功   ლ(´ڡ`ლ)゙ ");
        System.out.println("(♥◠‿◠)ノ゙  车辆车队模块启动成功   ლ(´ڡ`ლ)゙  \n");
    }
}
xp-service/xp-vehicleConvoy/src/main/resources/bootstrap.yml
@@ -56,52 +56,52 @@
    type: nacos
    nacos:
      # 开发环境
#      server-addr: 192.168.110.169:8848
#      namespace: b5290bc2-e3aa-4988-8a7d-9c07e4e073cb
#      group: DEFAULT_GROUP
#      data-id: seata-server.properties
#      username: nacos
#      password: nacos
      # 生产环境
      server-addr: 192.168.0.137:8848,192.168.0.123:8848
      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
      server-addr: 192.168.110.80:8848
      namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
      group: DEFAULT_GROUP
      data-id: seata-server.properties
      username: nacos
      password: nacos
      # 生产环境
#      server-addr: 192.168.0.137:8848,192.168.0.123:8848
#      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
#      group: DEFAULT_GROUP
#      data-id: seata-server.properties
#      username: nacos
#      password: nacos
  registry:
    type: nacos
    nacos:
      application: seata-server
      # 开发环境
#      server-addr: 192.168.110.169:8848
#      namespace: b5290bc2-e3aa-4988-8a7d-9c07e4e073cb
#      group: DEFAULT_GROUP
#      username: nacos
#      password: nacos
      # 生产环境
      server-addr: 192.168.0.137:8848,192.168.0.123:8848
      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
      server-addr: 192.168.110.80:8848
      namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
      group: DEFAULT_GROUP
      username: nacos
      password: nacos
      # 生产环境
#      server-addr: 192.168.0.137:8848,192.168.0.123:8848
#      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
#      group: DEFAULT_GROUP
#      username: nacos
#      password: nacos
  cloud:
    nacos:
      discovery:
        # 开发环境
#        server-addr: 192.168.110.169:8848 # nacos注册中心地址
#        namespace: b5290bc2-e3aa-4988-8a7d-9c07e4e073cb # 命名空间
#        group: DEFAULT_GROUP
#        application: seata-server #Nacos 中 Seata 名称
#        username: nacos
#        password: nacos
        # 生产环境
        server-addr: 192.168.0.137:8848,192.168.0.123:8848
        namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
        server-addr: 192.168.110.80:8848
        namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
        group: DEFAULT_GROUP
        application: seata-server #Nacos 中 Seata 名称
        username: nacos
        password: nacos
        # 生产环境
#        server-addr: 192.168.0.137:8848,192.168.0.123:8848
#        namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
#        group: DEFAULT_GROUP
#        application: seata-server #Nacos 中 Seata 名称
#        username: nacos
#        password: nacos
    sentinel:
      transport:
        dashboard: 192.168.0.137:8080  #  Sentinel控制台地址