puzhibing
2026-02-28 e8cd57fc46fa84b0c095f7e93cb348c014d06eb4
新增管理后台接口,修改小程序流程bug及其他相关功能
1个文件已删除
62个文件已修改
1662 ■■■■■ 已修改文件
sql/seate/application.yml 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserNotificationController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserNotificationService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/SysUserMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/pushMessage/AliPushMessageDTO.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpPointClientFallbackFactory.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/vehicleConvoy/XpFleetOperationsClientFallbackFactory.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpPointClient.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/vehicleConvoy/XpFleetOperationsClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/SysUser.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpScheduling.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpSchedulingDetail.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTaskRule.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpHistoryEndPointsVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpHistoryStartPointsVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/utils/XpPricingUtil.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/TaskScheduleConstants.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpSchedulingDetailController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/SchedulingDetailDto.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/TaskRuleDetailDto.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/InsuranceInspectionScheduleTask.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/RoutinePreparationScheduleTask.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCleanScheduleTask.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCollectionScheduleTask.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleInspectionScheduleTask.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleMaintenanceScheduleTask.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpSchedulingDetailService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java 472 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpSchedulingDetailMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpMapController.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpInvitationCodeController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointManagementController.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpCruisePlanServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderHistoryListVO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/AliPushController.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/PushOrderRouteController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/AliPushUtil.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/constant/I18nKeyConstant.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetOperationsController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages_en_US.properties 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages_zh_CN.properties 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/seate/application.yml
File was deleted
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserController.java
@@ -200,7 +200,7 @@
    }
    @ApiOperation(value = "运维人员管理重置密码", tags = {"管理后台-运维执行"})
    @DeleteMapping("/api/v1/operationsUser/rePassword")
    @PostMapping("/api/v1/operationsUser/rePassword")
    public R<String> rePassword(@RequestBody RePasswordDTO dto) {
        xpOperationsUserService.rePassword(dto);
        return R.ok();
@@ -215,7 +215,7 @@
    @ApiOperation(value = "运维人员管理导出列表", tags = {"管理后台-运维执行"})
    @GetMapping("/api/v1/operationsUser/exportOperationsUser")
    @PostMapping("/api/v1/operationsUser/exportOperationsUser")
    public void exportOperationsUser(@RequestBody XpOperationsUserQuery query, HttpServletResponse response){
        xpOperationsUserService.exportOperationsUser(query, response);
    }
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserNotificationController.java
@@ -11,6 +11,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * <p>
 * 运维人员消息通知表 前端控制器
@@ -70,4 +72,11 @@
        notificationService.lambdaUpdate().set(XpOperationsUserNotification::getReadStatus, 1).eq(XpOperationsUserNotification::getId, notificationId).update();
        return R.ok();
    }
    @PostMapping(value = "/inner/v1/notification/addBatch")
    @ApiOperation(value = "批量添加通知", tags = {"内部接口"})
    public R<?> addNotificationBatch(@RequestBody List<XpOperationsUserNotification> notifications) {
        notificationService.addNotificationBatch(notifications);
        return R.ok();
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserNotificationService.java
@@ -5,6 +5,8 @@
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.common.core.web.page.PageInfo;
import java.util.List;
/**
 * <p>
 * 运维人员消息通知表 服务类
@@ -23,4 +25,10 @@
    PageInfo<XpOperationsUserNotification> selectNotificationPageByUserId(
        XpOperationsUserNotificationPageQuery query
    );
    /**
     * 批量添加通知
     * @param notifications
     */
    void addNotificationBatch(List<XpOperationsUserNotification> notifications);
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java
@@ -7,7 +7,12 @@
import com.xiaopeng.account.service.IXpOperationsUserNotificationService;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.common.core.web.page.PageInfo;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
 * <p>
@@ -43,4 +48,10 @@
        return pageInfo;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @ShardingSphereTransactionType(TransactionType.BASE)
    public void addNotificationBatch(List<XpOperationsUserNotification> notifications) {
        saveBatch(notifications);
    }
}
xp-robotaxi-account-boot/src/main/resources/mapper/account/SysUserMapper.xml
@@ -115,7 +115,7 @@
    <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
        select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1
    </select>
    <select id="getList" resultMap="SysUserResult">
    <select id="getList" resultType="com.xiaopeng.api.model.account.SysUser">
        select su.*,sr.role_name, sur.role_id from sys_user su
        left join sys_user_role sur on su.id= sur.user_id
        left join sys_role sr on sr.id = sur.role_id where 1=1
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/pushMessage/AliPushMessageDTO.java
@@ -2,11 +2,14 @@
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Builder
@Accessors(chain = true)
@ApiModel(value = "ali推送消息AliPushMessageDTO")
public class AliPushMessageDTO implements Serializable {
@@ -22,4 +25,7 @@
    @ApiModelProperty(value = "消息内容")
    private String body;
    @ApiModelProperty(value = "推送类型 NOTICE:表示通知。 MESSAGE:表示消息。")
    private String pushType;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpPointClientFallbackFactory.java
@@ -14,6 +14,7 @@
import com.xiaopeng.api.query.operation.PointPageListListQuery;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import lombok.extern.slf4j.Slf4j;
@@ -23,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@Slf4j
@Component
@@ -101,6 +103,12 @@
                log.error("获取地图点位失败:{}", cause.getMessage());
                return R.ok(new ArrayList<>());
            }
            @Override
            public R<List<XpPoint>> getPointsInfo(Set<Long> points) {
                log.error("获取点位信息失败:{}", cause.getMessage());
                return null;
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/vehicleConvoy/XpFleetOperationsClientFallbackFactory.java
@@ -33,6 +33,13 @@
                log.error("根据人员ID获取车队信息失败 {}",  cause.getMessage());
                return R.fail("根据人员ID获取车队信息失败");
            }
            @Override
            public R<List<Long>> getOperationsIdsByFleetId(Long fleetId) {
                log.error("根据车队ID获取人员信息失败 {}",  cause.getMessage());
                return R.fail("根据车队ID获取人员信息失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpPointClient.java
@@ -14,6 +14,7 @@
import com.xiaopeng.api.query.operation.PointPageListListQuery;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import com.xiaopeng.common.core.web.page.PageInfo;
@@ -22,6 +23,7 @@
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
@FeignClient(contextId = "XpPointClient", value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, fallbackFactory = XpPointClientFallbackFactory.class)
public interface XpPointClient {
@@ -74,6 +76,7 @@
    R<List<XpPoint>> pointMap(@RequestBody PointMapQuery query);
    @PostMapping("/base/v1/mini-program/inner/point/getPointsInfo")
    R<List<XpPoint>> getPointsInfo(@RequestBody Set<Long> points);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/vehicleConvoy/XpFleetOperationsClient.java
@@ -37,4 +37,14 @@
     */
    @GetMapping("/inner/fleet-operations/getFleetIdsByUserId/{userId}")
    R<List<Long>> getFleetIdsByUserId(@PathVariable("userId") Long userId);
    /**
     * 根据车队ID查询关联的运维人员ID列表
     *
     * @param fleetId 车队ID
     * @return 运维人员ID列表
     */
    @GetMapping("/inner/fleet-operations/getOperationsIdsByFleetId/{fleetId}")
    R<List<Long>> getOperationsIdsByFleetId(@PathVariable("fleetId") Long fleetId);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/SysUser.java
@@ -86,6 +86,10 @@
    @TableField(exist = false)
    private Long deptId;
    @ApiModelProperty(value = "角色名称")
    @TableField(exist = false)
    private String roleName;
    public boolean isAdmin()
    {
        return isAdmin(this.id);
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpScheduling.java
@@ -3,6 +3,8 @@
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
@@ -34,7 +36,7 @@
    private Long id;
    @ApiModelProperty(value = "排版日期")
    private LocalDateTime schedulingDate;
    private LocalDate schedulingDate;
    @ApiModelProperty(value = "排版人员id")
    private Long commitUserId;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpSchedulingDetail.java
@@ -3,6 +3,8 @@
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
@@ -46,6 +48,6 @@
    private Boolean isAllDay;
    @ApiModelProperty(value = "计划时间")
    private LocalDateTime planTime;
    private LocalDate planTime;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java
@@ -85,4 +85,6 @@
    @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消")
    private Integer status;
    private String belongUserIds;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTaskRule.java
@@ -4,9 +4,11 @@
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.LocalTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.common.core.web.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -42,7 +44,8 @@
    private Integer vehicleInspectionFrequency;
    @ApiModelProperty(value = "车辆日常检测 任务下放时间")
    private LocalDateTime vehicleInspectionTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleInspectionTime;
    @ApiModelProperty(value = "车辆日常监测 紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer vehicleInspectionLevel;
@@ -51,7 +54,8 @@
    private Boolean vehicleCollection;
    @ApiModelProperty(value = "车辆收车每日时间")
    private LocalDateTime vehicleCollectionTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleCollectionTime;
    @ApiModelProperty(value = "车辆保养周期是否启用")
    private Boolean maintenanceCycle;
@@ -63,7 +67,8 @@
    private Integer maintenanceCycleTimeType;
    @ApiModelProperty(value = "车辆保养周期 任务下放时间")
    private LocalDateTime maintenanceCycleTaskTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime maintenanceCycleTaskTime;
    @ApiModelProperty(value = "车辆保养周期 紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer maintenanceCycleLevel;
@@ -78,7 +83,11 @@
    private Integer chargingStrategyLevel;
    @ApiModelProperty(value = "车身清洁保养周期X")
    private Integer vehicleCleanTime;
    private Integer vehicleCleanCycle;
    @ApiModelProperty(value = "车身清洁保养任务下放时间")
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleCleanTime;
    @ApiModelProperty(value = "车身清洁保养周期X 1=天 2=月")
    private Integer vehicleCleanTimeType;
@@ -87,7 +96,11 @@
    private Integer vehicleCleanLevel;
    @ApiModelProperty(value = "日常整备保养周期X")
    private Integer routineMaintenanceTime;
    private Integer routineMaintenanceCycle;
    @ApiModelProperty(value = "日常整备保养任务下放时间")
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime routineMaintenanceTime;
    @ApiModelProperty(value = "日常整备保养周期X 1=天 2=月")
    private Integer routineMaintenanceTimeType;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpHistoryEndPointsVo.java
@@ -25,4 +25,10 @@
    @ApiModelProperty("站点id")
    private Long id;
    @ApiModelProperty("停靠时间")
    private Integer time;
    private Long electronicAreaId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpHistoryStartPointsVo.java
@@ -25,4 +25,10 @@
    @ApiModelProperty("站点id")
    private Long id;
    @ApiModelProperty("停靠时间")
    private Integer time;
    private Long electronicAreaId;
}
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -15,6 +15,7 @@
com.xiaopeng.api.factory.account.SysUserRoleClientFallbackFactory
com.xiaopeng.api.factory.account.SysUserClientFallbackFactory
com.xiaopeng.api.factory.account.XpOperationUserClientFallbackFactory
com.xiaopeng.api.factory.account.XpOperationUserNotificationClientFallbackFactory
com.xiaopeng.api.factory.operation.XpElectronicClientFallbackFactory
com.xiaopeng.api.factory.operation.XpOpenCityClientFallbackFactory
com.xiaopeng.api.factory.operation.XpCouponClientFallbackFactory
@@ -38,4 +39,5 @@
com.xiaopeng.api.factory.operation.SmsClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpTaskHandleDetailRoutineClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpTaskClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpTaskRuleClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpTaskRuleClientFallbackFactory
com.xiaopeng.api.factory.pushMessage.XpAliPushMessageClientFallbackFactory
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -7,6 +7,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.account.GetUserCouponDto;
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
@@ -468,14 +469,14 @@
        // 根据id获取手机号
        Boolean isPriorityDispatch = false;
        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
        if (xpAppUserR.getCode() == R.SUCCESS) {
            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
            if (count > 0) {
                isPriorityDispatch = true;
            }
        }
        Boolean isPriorityDispatch = true;
//        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
//        if (xpAppUserR.getCode() == R.SUCCESS) {
//            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
//            if (count > 0) {
//                isPriorityDispatch = true;
//            }
//        }
        // 生成订单数据
        XpOrder xpOrder = new XpOrder();
@@ -709,7 +710,7 @@
            dto.setMessage("{\"type\":\"VEHICLE_LOCATION\",\"content\":\"{\\\"orderId\\\":\\\"" + orderId + "\\\",\\\"lon\\\":113.385848,\\\"lat\\\":23.156841}\",\"timestamp\":\"176569945845456\"}");
            xpPushMessageClient.sendVehicleLocation(dto);
            //发送车辆到达起点的轨迹
            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
            OrderRouteAndFareDto routeAndFareDto = new OrderRouteAndFareDto();
            LonLatDto destination = new LonLatDto();
            destination.setLongitude(xpOrder.getStartLon());
            destination.setLatitude(xpOrder.getStartLat());
@@ -718,8 +719,9 @@
            origin.setLongitude(113.385848);
            origin.setLatitude(23.156841);
            routeAndFareDto.setOrigin(origin);
            routeAndFareDto.setOpenCityId(2L);
            RouteVo routeVo = xpMapClient.getDistanceAndDuration(routeAndFareDto).getData();
            routeAndFareDto.setRouteType(1);
            routeAndFareDto.setOrderId(orderId);
            RouteVo routeVo = xpMapClient.getOrderDistanceAndDuration(routeAndFareDto).getData();
            com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
            jsonObject.put("type", "ORDER_ROUTE");
            jsonObject.put("timestamp", System.currentTimeMillis());
@@ -782,12 +784,12 @@
            dto.setMessage("{\"type\":\"ORDER_STATUS\",\"content\":\"{\\\"orderId\\\":\\\"" + orderId + "\\\",\\\"status\\\":5}\",\"timestamp\":\"176569945845456\"}");
            xpPushMessageClient.sendStatus(dto);
            //推送起点到终点的行驶轨迹
            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
            routeAndFareDto = new RouteAndFareDto();
            OrderRouteAndFareDto routeAndFareDto = new OrderRouteAndFareDto();
            routeAndFareDto.setDestination(new LonLatDto(xpOrder.getEndLon(), xpOrder.getEndLat()));
            routeAndFareDto.setOrigin(new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat()));
            routeAndFareDto.setOpenCityId(2L);
            RouteVo routeVo = xpMapClient.getDistanceAndDuration(routeAndFareDto).getData();
            routeAndFareDto.setRouteType(2);
            routeAndFareDto.setOrderId(orderId);
            RouteVo routeVo = xpMapClient.getOrderDistanceAndDuration(routeAndFareDto).getData();
            com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
            jsonObject.put("type", "ORDER_ROUTE");
            jsonObject.put("timestamp", System.currentTimeMillis());
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/utils/XpPricingUtil.java
@@ -264,14 +264,18 @@
        if (holiday) {
            if (realDistance > rule.getDouble("num6")) {
                longDistanceOne = rule.getDouble("num32") * (realDistance - rule.getDouble("num6"));
                longDistanceOne = new BigDecimal(longDistanceOne).setScale(2,RoundingMode.HALF_UP).doubleValue();
            }
            if (realDistance > rule.getDouble("num9")) {
                longDistanceTwo = rule.getDouble("num33") * (realDistance - rule.getDouble("num9"));
                longDistanceTwo = new BigDecimal(longDistanceTwo).setScale(2,RoundingMode.HALF_UP).doubleValue();
            }
            if (realDistance > rule.getDouble("num12")) {
                longDistanceThree = rule.getDouble("num34") * (realDistance - rule.getDouble("num12"));
                longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
            }
            amount = rule.getDouble("num29") + new BigDecimal(exceedDistance * rule.getDouble("num30")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (exceedTime * rule.getDouble("num31")) + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
            amount = rule.getDouble("num29") + new BigDecimal(exceedDistance * rule.getDouble("num30")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num31")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
            // 起步价
@@ -299,14 +303,17 @@
            if (date.getTime() > calendarNight.getTimeInMillis() && date.getTime() < calendar.getTimeInMillis()) {
                if (realDistance > rule.getDouble("num6")) {
                    longDistanceOne = rule.getDouble("num18") * (realDistance - rule.getDouble("num6"));
                    longDistanceOne = new BigDecimal(longDistanceOne).setScale(2,RoundingMode.HALF_UP).doubleValue();
                }
                if (realDistance > rule.getDouble("num9")) {
                    longDistanceTwo = rule.getDouble("num19") * (realDistance - rule.getDouble("num9"));
                    longDistanceTwo = new BigDecimal(longDistanceTwo).setScale(2,RoundingMode.HALF_UP).doubleValue();
                }
                if (realDistance > rule.getDouble("num12")) {
                    longDistanceThree = rule.getDouble("num20") * (realDistance - rule.getDouble("num12"));
                    longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                }
                amount = rule.getDouble("num15") + new BigDecimal(exceedDistance * rule.getDouble("num16")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (exceedTime * rule.getDouble("num17")) + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                amount = rule.getDouble("num15") + new BigDecimal(exceedDistance * rule.getDouble("num16")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num17")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                // 起步价
@@ -355,14 +362,17 @@
                if ((date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) || (date.getTime() > s2.getTimeInMillis() && date.getTime() < e2.getTimeInMillis())) {
                    if (realDistance > rule.getDouble("num6")) {
                        longDistanceOne = rule.getDouble("num26") * (realDistance - rule.getDouble("num6"));
                        longDistanceOne = new BigDecimal(longDistanceOne).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    if (realDistance > rule.getDouble("num9")) {
                        longDistanceTwo = rule.getDouble("num27") * (realDistance - rule.getDouble("num9"));
                        longDistanceTwo = new BigDecimal(longDistanceTwo).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    if (realDistance > rule.getDouble("num12")) {
                        longDistanceThree = rule.getDouble("num28") * (realDistance - rule.getDouble("num12"));
                        longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    amount = rule.getDouble("num23") + new BigDecimal(exceedDistance * rule.getDouble("num24")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (exceedTime * rule.getDouble("num25")) + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    amount = rule.getDouble("num23") + new BigDecimal(exceedDistance * rule.getDouble("num24")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num25")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    // 起步价
@@ -393,14 +403,17 @@
                    //其他时间段的计算
                    if (realDistance > rule.getDouble("num6")) {
                        longDistanceOne = rule.getDouble("num8") * (realDistance - rule.getDouble("num6"));
                        longDistanceOne = new BigDecimal(longDistanceOne).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    if (realDistance > rule.getDouble("num9")) {
                        longDistanceTwo = rule.getDouble("num11") * (realDistance - rule.getDouble("num9"));
                        longDistanceTwo = new BigDecimal(longDistanceTwo).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    if (realDistance > rule.getDouble("num12")) {
                        longDistanceThree = rule.getDouble("num13") * (realDistance - rule.getDouble("num12"));
                        longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    amount = rule.getDouble("num1") + new BigDecimal(exceedDistance * rule.getDouble("num4")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (exceedTime * rule.getDouble("num5")) + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    amount = rule.getDouble("num1") + new BigDecimal(exceedDistance * rule.getDouble("num4")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num5")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    // 起步价
@@ -433,6 +446,7 @@
        // 订单总额
        Double startPrice = xpPricingCardVo.getStartPrice();
        amount=new BigDecimal(amount).setScale(2,RoundingMode.HALF_UP).doubleValue();
        // 先减去起步价重新计算
        amount = amount - startPrice;
        // 动态计算费用
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java
@@ -11,4 +11,5 @@
    String VEHICLE_NOT_EXIST = "vehicle.not.exist";
    String TASK_RULE_NOT_CONFIG = "task.rule.not.config";
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/TaskScheduleConstants.java
@@ -88,16 +88,6 @@
    public static final Integer TASK_STATUS_CANCELLED = 3;
    /**
     * 任务过期通知发送状态 - 未发送
     */
    public static final Integer TASK_EXPIRED_NOTICE_NOT_SENT = 0;
    /**
     * 任务过期通知发送状态 - 已发送
     */
    public static final Integer TASK_EXPIRED_NOTICE_SENT = 1;
    /**
     * 任务规则角色类型 - 车辆日常检测任务接收角色
     */
    public static final Integer RULE_ROLE_TYPE_INSPECTION = 1;
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpSchedulingDetailController.java
@@ -1,13 +1,15 @@
package com.xiaopeng.maintenance.controller;
import com.xiaopeng.api.model.maintenance.XpErrorType;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.model.account.SysUser;import com.xiaopeng.api.model.maintenance.XpErrorType;
import com.xiaopeng.api.vo.account.LoginUser;import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.common.security.utils.SecurityUtils;
import com.xiaopeng.maintenance.dto.SchedulingDetailDto;
import com.xiaopeng.maintenance.dto.ShiftAttendanceDTO;
import com.xiaopeng.maintenance.service.IXpSchedulingDetailService;
import com.xiaopeng.maintenance.vo.SaveSchedulingVo;
import com.xiaopeng.maintenance.vo.SchedulingDetailVo;
import com.xiaopeng.maintenance.vo.ShiftAttendanceVO;
import io.swagger.annotations.Api;
@@ -15,6 +17,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -30,9 +35,10 @@
@RequestMapping("")
public class XpSchedulingDetailController {
    @Autowired
    @Resource
    private IXpSchedulingDetailService xpSchedulingDetailService;
    @Autowired
    @Resource
    private TokenService tokenService;
    @ApiOperation(value = "查询个人排班与考勤信息", response = XpErrorType.class, tags = "运维APP-排班与考勤")
@@ -44,11 +50,27 @@
    }
//    public R<PageInfo<SchedulingDetailDto>> pageList(@RequestBody SchedulingDetailVo query){
//
//    }
    @ApiOperation(value = "排班考勤-排班计划管理-查询列表", response = XpErrorType.class, tags = "管理后台-运维执行")
    @PostMapping("/api/v1/scheduling/pageList")
    public R<PageInfo<SchedulingDetailDto>> pageList(@RequestBody SchedulingDetailVo query){
        PageInfo<SchedulingDetailDto> pageInfo = xpSchedulingDetailService.pageList(query);
        return R.ok(pageInfo);
    }
    @ApiOperation(value = "排班考勤-排班计划管理-保存排班数据", response = XpErrorType.class, tags = "管理后台-运维执行")
    @PostMapping("/api/v1/scheduling/saveSchedulingDetail")
    public R<?> saveSchedulingDetail(@RequestBody SaveSchedulingVo vo){
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        return xpSchedulingDetailService.saveSchedulingDetail(vo, sysUser.getId());
    }
    @ApiOperation(value = "排班考勤-排班计划管理-导出排班数据", response = XpErrorType.class, tags = "管理后台-运维执行")
    @GetMapping("/api/v1/scheduling/exportExcel")
    public void exportExcel(@RequestParam("month") String month, HttpServletResponse response) {
        xpSchedulingDetailService.exportExcel(month, response);
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/SchedulingDetailDto.java
@@ -4,73 +4,87 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
@Data
@ApiModel
public class SchedulingDetailDto {
    @ApiModelProperty("排班ID")
    private Long schedulingId;
    @ApiModelProperty("车队ID")
    private String fleetId;
    @ApiModelProperty("车队")
    private String fleetName;
    @ApiModelProperty("1")
    private String one;
    private Map<String, String> one;
    @ApiModelProperty("2")
    private String two;
    private Map<String, String> two;
    @ApiModelProperty("3")
    private String three;
    private Map<String, String> three;
    @ApiModelProperty("4")
    private String four;
    private Map<String, String> four;
    @ApiModelProperty("5")
    private String five;
    private Map<String, String> five;
    @ApiModelProperty("6")
    private String six;
    private Map<String, String> six;
    @ApiModelProperty("7")
    private String seven;
    private Map<String, String> seven;
    @ApiModelProperty("8")
    private String eight;
    private Map<String, String> eight;
    @ApiModelProperty("9")
    private String nine;
    private Map<String, String> nine;
    @ApiModelProperty("10")
    private String ten;
    private Map<String, String> ten;
    @ApiModelProperty("11")
    private String eleven;
    private Map<String, String> eleven;
    @ApiModelProperty("12")
    private String twelve;
    private Map<String, String> twelve;
    @ApiModelProperty("13")
    private String thirteen;
    private Map<String, String> thirteen;
    @ApiModelProperty("14")
    private String fourteen;
    private Map<String, String> fourteen;
    @ApiModelProperty("15")
    private String fifteen;
    private Map<String, String> fifteen;
    @ApiModelProperty("16")
    private String sixteen;
    private Map<String, String> sixteen;
    @ApiModelProperty("17")
    private String seventeen;
    private Map<String, String> seventeen;
    @ApiModelProperty("18")
    private String eighteen;
    private Map<String, String> eighteen;
    @ApiModelProperty("19")
    private String nineteen;
    private Map<String, String> nineteen;
    @ApiModelProperty("20")
    private String twenty;
    private Map<String, String> twenty;
    @ApiModelProperty("21")
    private String twentyOne;
    private Map<String, String> twentyOne;
    @ApiModelProperty("22")
    private String twentyTwo;
    private Map<String, String> twentyTwo;
    @ApiModelProperty("23")
    private String twentyThree;
    private Map<String, String> twentyThree;
    @ApiModelProperty("24")
    private String twentyFour;
    private Map<String, String> twentyFour;
    @ApiModelProperty("25")
    private String twentyFive;
    private Map<String, String> twentyFive;
    @ApiModelProperty("26")
    private String twentySix;
    private Map<String, String> twentySix;
    @ApiModelProperty("27")
    private String twentySeven;
    private Map<String, String> twentySeven;
    @ApiModelProperty("28")
    private String twentyEight;
    private Map<String, String> twentyEight;
    @ApiModelProperty("29")
    private String twentyNine;
    private Map<String, String> twentyNine;
    @ApiModelProperty("30")
    private String thirty;
    private Map<String, String> thirty;
    @ApiModelProperty("31")
    private String thirtyOne;
    private Map<String, String> thirtyOne;
    @ApiModelProperty("全天")
    private Long allDay;
    @ApiModelProperty("早")
    private Long morning;
    @ApiModelProperty("中")
    private Long midDay;
    @ApiModelProperty("晚")
    private Long evening;
    /**
     * 天数,用逗号分隔
     */
    private String days;
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/TaskRuleDetailDto.java
@@ -1,5 +1,6 @@
package com.xiaopeng.maintenance.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -7,7 +8,8 @@
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.LocalTime;
import java.util.List;
@Data
@@ -21,7 +23,8 @@
    @ApiModelProperty(value = "车辆日常监测 频次")
    private Integer vehicleInspectionFrequency;
    @ApiModelProperty(value = "车辆日常检测 任务下放时间")
    private LocalDateTime vehicleInspectionTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleInspectionTime;
    @ApiModelProperty(value = "车辆日常监测 紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer vehicleInspectionLevel;
@@ -30,7 +33,8 @@
    private Boolean vehicleCollection;
    @ApiModelProperty(value = "车辆收车每日时间")
    private LocalDateTime vehicleCollectionTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleCollectionTime;
    @ApiModelProperty(value = "车辆保养周期是否启用")
    private Boolean maintenanceCycle;
@@ -42,7 +46,8 @@
    private Integer maintenanceCycleTimeType;
    @ApiModelProperty(value = "车辆保养周期 任务下放时间")
    private LocalDateTime maintenanceCycleTaskTime;
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime maintenanceCycleTaskTime;
    @ApiModelProperty(value = "车辆保养周期 紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer maintenanceCycleLevel;
@@ -57,7 +62,11 @@
    private Integer chargingStrategyLevel;
    @ApiModelProperty(value = "车身清洁保养周期X")
    private Integer vehicleCleanTime;
    private Integer vehicleCleanCycle;
    @ApiModelProperty(value = "车身清洁保养任务下放时间")
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime vehicleCleanTime;
    @ApiModelProperty(value = "车身清洁保养周期X 1=天 2=月")
    private Integer vehicleCleanTimeType;
@@ -66,7 +75,11 @@
    private Integer vehicleCleanLevel;
    @ApiModelProperty(value = "日常整备保养周期X")
    private Integer routineMaintenanceTime;
    private Integer routineMaintenanceCycle;
    @ApiModelProperty(value = "日常整备保养任务下放时间")
    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8")
    private LocalTime routineMaintenanceTime;
    @ApiModelProperty(value = "日常整备保养周期X 1=天 2=月")
    private Integer routineMaintenanceTimeType;
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/InsuranceInspectionScheduleTask.java
@@ -344,19 +344,21 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
            // 设置任务时限
            if (taskRule.getProcessingTimeLimit() != null) {
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            // 设置任务状态为待到达
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING);
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE);
            // 设置任务接收人(配置角色下的所有运维人员都可以看到)
            task.setHandleUserId(belongUserIds);
            task.setReportTime(LocalDateTime.now());
            task.setReportUserId(0L);
            task.setBelongUserIds(belongUserIds);
            // 设置创建信息
            task.setReportTime(LocalDateTime.now());
            task.setCreateBy(TaskScheduleConstants.SCHEDULE_CREATOR);
            tasksToSave.add(task);
        }
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/RoutinePreparationScheduleTask.java
@@ -364,16 +364,17 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
            // 设置任务时限
            if (taskRule.getProcessingTimeLimit() != null) {
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            // 设置任务状态为待到达
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING);
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE);
            // 设置任务接收人(配置角色下的所有运维人员都可以看到)
            task.setHandleUserId(belongUserIds);
            task.setReportTime(LocalDateTime.now());
            task.setReportUserId(0L);
            task.setBelongUserIds(belongUserIds);
            // 设置创建信息
            task.setReportTime(LocalDateTime.now());
            task.setCreateBy(TaskScheduleConstants.SCHEDULE_CREATOR);
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCleanScheduleTask.java
@@ -364,16 +364,17 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
            // 设置任务时限
            if (taskRule.getProcessingTimeLimit() != null) {
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            // 设置任务状态为待到达
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING);
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE);
            // 设置任务接收人(配置角色下的所有运维人员都可以看到)
            task.setHandleUserId(belongUserIds);
            task.setReportTime(LocalDateTime.now());
            task.setReportUserId(0L);
            task.setBelongUserIds(belongUserIds);
            // 设置创建信息
            task.setReportTime(LocalDateTime.now());
            task.setCreateBy(TaskScheduleConstants.SCHEDULE_CREATOR);
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCollectionScheduleTask.java
@@ -1,25 +1,14 @@
package com.xiaopeng.maintenance.schedule;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -53,18 +42,6 @@
    @Autowired
    private XpVehicleClient xpVehicleClient;
    @Autowired
    private XpCruiseOrderClient xpCruiseOrderClient;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private OrderMissionClient orderMissionClient;
    @Autowired
    private XpCruisePlanClient xpCruisePlanClient;
    /**
     * 每分钟检查一次是否需要执行收车任务
@@ -185,7 +162,6 @@
                return result.getData().stream()
                        .filter(v -> v.getVehicleType() != null && v.getVehicleType() == 2)
                        .filter(v -> v.getOperatingStatus() != null && v.getOperatingStatus() == 1)
                        .filter(v -> v.getState() != null && v.getState() == 0)
                        .collect(Collectors.toList());
            }
        } catch (Exception e) {
@@ -196,47 +172,17 @@
    /**
     * 向车辆发送收车指令
     * <p>
     * TODO: 具体发送收车指令的实现
     * 可能需要:
     * 1. 调用车辆控制接口发送收车指令
     * 2. 更新车辆状态为"已收车"
     * </p>
     *
     * @param xpVehicle 车辆信息
     * @param vehicle 车辆信息
     */
    private void sendCollectionCommand(XpVehicle xpVehicle) {
        // 收车 关闭当前巡游单子 生成新的返程单子  找到收车站点
        R<String> r = xpCruiseOrderClient.updateCruiseOrder(xpVehicle.getVehicleVin());
        // mongodb 获取当前最新经纬度位置
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
        XpCruiseOrder xpCruiseOrder = new XpCruiseOrder();
        if(vehiclePosition!=null){
            double x = vehiclePosition.getPoint().getX();
            double y = vehiclePosition.getPoint().getY();
            xpCruiseOrder.setStartLon(x);
            xpCruiseOrder.setStartLat(y);
        }
        xpCruiseOrder.setId("XU"+ IdUtil.fastUUID());
        xpCruiseOrder.setVehicleId(xpVehicle.getId());
        xpCruiseOrder.setFleetId(xpVehicle.getFleetId());
        xpCruiseOrder.setOrderType(2);
        xpCruiseOrder.setStatus(1);
        xpCruiseOrder.setOrderReverse(1);
        xpCruiseOrder.setLastOrderId(r.getData());
        // 找到收车站点
        R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
        if(returnCruisePoint!=null){
            xpCruiseOrderClient.addCruiseOrder(returnCruisePoint.getData());
            // 下发命令
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setVin(returnCruisePoint.getData().getVehicleVin());
            pushOrderDto.setOrderId(returnCruisePoint.getData().getId());
            pushOrderDto.setStartLatitude(returnCruisePoint.getData().getStartLat());
            pushOrderDto.setStartLongitude(returnCruisePoint.getData().getStartLon());
            pushOrderDto.setEndLatitude(returnCruisePoint.getData().getEndLat());
            pushOrderDto.setEndLongitude(returnCruisePoint.getData().getEndLon());
            pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
            pushOrderDto.setStage(2);
            orderMissionClient.pushOrder(pushOrderDto);
        }
        log.info("向车辆[{}]发送收车指令", xpVehicle.getPlateNumber());
    private void sendCollectionCommand(XpVehicle vehicle) {
        // TODO: 具体发送收车指令的实现
        log.info("向车辆[{}]发送收车指令", vehicle.getPlateNumber());
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleInspectionScheduleTask.java
@@ -324,14 +324,16 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
            // 设置任务时限
            if (taskRule.getProcessingTimeLimit() != null) {
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            // 设置任务状态为待到达
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING);
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE);
            // 设置任务接收人(配置角色下的所有运维人员都可以看到)
            task.setHandleUserId(belongUserIds);
            task.setBelongUserIds(belongUserIds);
            // 设置创建信息
            task.setReportTime(LocalDateTime.now());
@@ -343,8 +345,6 @@
        // 批量保存任务
        if (!CollectionUtils.isEmpty(tasksToSave)) {
            for (XpTask task : tasksToSave) {
                task.setReportTime(LocalDateTime.now());
                task.setReportUserId(0L);
                taskMapper.insert(task);
            }
            log.info("成功创建 {} 个车辆日常检测任务", tasksToSave.size());
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleMaintenanceScheduleTask.java
@@ -350,20 +350,21 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
            // 设置任务时限
            if (taskRule.getProcessingTimeLimit() != null) {
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            // 设置任务状态为待到达
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING);
            task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE);
            // 设置任务接收人(配置角色下的所有运维人员都可以看到)
            task.setHandleUserId(belongUserIds);
            task.setBelongUserIds(belongUserIds);
            // 设置创建信息
            task.setReportTime(LocalDateTime.now());
            task.setCreateBy(TaskScheduleConstants.SCHEDULE_CREATOR);
            task.setReportTime(LocalDateTime.now());
            task.setReportUserId(0L);
            tasksToSave.add(task);
        }
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpSchedulingDetailService.java
@@ -2,12 +2,17 @@
import com.xiaopeng.api.model.maintenance.XpSchedulingDetail;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.dto.SchedulingDetailDto;
import com.xiaopeng.maintenance.dto.ShiftAttendanceDTO;
import com.xiaopeng.maintenance.vo.SaveSchedulingVo;
import com.xiaopeng.maintenance.vo.SchedulingDetailVo;
import com.xiaopeng.maintenance.vo.ShiftAttendanceVO;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
/**
 * <p>
@@ -33,4 +38,20 @@
     * @return
     */
    PageInfo<SchedulingDetailDto> pageList(SchedulingDetailVo query);
    /**
     * 保存排班明细
     * @param vo
     * @return
     */
    R saveSchedulingDetail(SaveSchedulingVo vo, Long userId);
    /**
     * 导出排班计划
     * @param month
     * @param response
     */
    void exportExcel(String month, HttpServletResponse response);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java
@@ -1,15 +1,19 @@
package com.xiaopeng.maintenance.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.maintenance.XpCheckLocationClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient;
import com.xiaopeng.api.model.maintenance.XpCheckLocation;
import com.xiaopeng.api.model.maintenance.XpClockIn;
import com.xiaopeng.api.model.maintenance.XpSchedulingDetail;
import com.xiaopeng.api.model.maintenance.XpShift;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.model.account.XpOperationsUser;import com.xiaopeng.api.model.maintenance.*;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.poi.ExcelUtil;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.dto.ExportSchedulingDetailDto;
import com.xiaopeng.maintenance.dto.SchedulingDetailDto;
import com.xiaopeng.maintenance.dto.ShiftAttendanceDTO;
import com.xiaopeng.maintenance.mapper.XpCheckLocationMapper;
@@ -17,12 +21,21 @@
import com.xiaopeng.maintenance.mapper.XpSchedulingDetailMapper;
import com.xiaopeng.maintenance.mapper.XpShiftMapper;
import com.xiaopeng.maintenance.service.IXpSchedulingDetailService;
import com.xiaopeng.maintenance.vo.SchedulingDetailVo;
import com.xiaopeng.maintenance.vo.ShiftAttendanceVO;
import com.xiaopeng.maintenance.service.IXpSchedulingService;
import com.xiaopeng.maintenance.service.IXpShiftService;
import com.xiaopeng.maintenance.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
/**
 * <p>
@@ -35,14 +48,22 @@
@Service
public class XpSchedulingDetailServiceImpl extends ServiceImpl<XpSchedulingDetailMapper, XpSchedulingDetail> implements IXpSchedulingDetailService {
    @Autowired
    @Resource
    private XpFleetClient xpFleetClient;
    @Autowired
    @Resource
    private XpCheckLocationMapper xpCheckLocationMapper;
    @Autowired
    @Resource
    private XpShiftMapper xpShiftMapper;
    @Autowired
    @Resource
    private XpClockInMapper xpClockInMapper;
    @Resource
    private IXpSchedulingService xpSchedulingService;
    @Resource
    private IXpShiftService xpShiftService;
    @Resource
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Resource
    private XpOperationUserClient xpOperationUserClient;
    @Override
    public ShiftAttendanceVO shiftAttendance(ShiftAttendanceDTO dto) {
@@ -78,10 +99,10 @@
                .eq(XpClockIn::getAppUserId, dto.getOperationsUserId())
                .likeRight(XpClockIn::getClockInTime, dto.getSchedulingDate())
                .last("LIMIT 1"));
        if(Objects.isNull(xpClockIn)){
        if (Objects.isNull(xpClockIn)) {
            shiftAttendanceVO.setClockIn(false);
            shiftAttendanceVO.setClockOut(false);
        }else {
        } else {
            shiftAttendanceVO.setXpClockIn(xpClockIn);
            shiftAttendanceVO.setClockIn(true);
            shiftAttendanceVO.setClockOut(xpClockIn.getClockOutTime() != null);
@@ -92,15 +113,438 @@
    /**
     * 排班明细分页列表
     *
     * @param query
     * @return
     */
    @Override
    public PageInfo<SchedulingDetailDto> pageList(SchedulingDetailVo query) {
        PageInfo<SchedulingDetailDto> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<SchedulingDetailDto> schedulingDetailDtos = this.baseMapper.pageList(pageInfo, query.getMonth());
        LocalDate parse1 = LocalDate.parse(query.getMonth(), DateTimeFormatter.ofPattern("yyyy-MM"));
        //找出月份的最大天
        int dayOfMonth = parse1.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        for (SchedulingDetailDto schedulingDetailDto : schedulingDetailDtos) {
            String days = schedulingDetailDto.getDays();
            if (StringUtils.isNotBlank(days)) {
                String[] split = days.split(",");
                List<String> list = Arrays.asList(split);
                for (int i = 1; i <= dayOfMonth; i++) {
                    Map<String, String> map1 = new HashMap<>();
                    for (String s : split) {
                        String[] split1 = s.split("_");
                        if (i == Integer.parseInt(split1[0])) {
                            map1.put("shiftId", split1[1]);
                            map1.put("shiftName", split1[2]);
                            map1.put("shiftColor", split1[3]);
                            break;
                        }
                    }
                    setEnglishDay(i, schedulingDetailDto, map1);
                }
                long allDay = list.stream().filter(s -> s.contains("全天")).count();
                long morning = list.stream().filter(s -> s.contains("早")).count();
                long midDay = list.stream().filter(s -> s.contains("中")).count();
                long evening = list.stream().filter(s -> s.contains("晚")).count();
                schedulingDetailDto.setAllDay(allDay);
                schedulingDetailDto.setMorning(morning);
                schedulingDetailDto.setMidDay(midDay);
                schedulingDetailDto.setEvening(evening);
            }
        }
        pageInfo.setRecords(schedulingDetailDtos);
        return pageInfo;
    }
    /**
     * 给每天的字段赋值
     * @param day
     * @param dto
     * @param map
     */
    private void setEnglishDay(int day, SchedulingDetailDto dto, Map<String, String> map) {
        switch (day) {
            case 1:
                dto.setOne(map);
                break;
            case 2:
                dto.setTwo(map);
                break;
            case 3:
                dto.setThree(map);
                break;
            case 4:
                dto.setFour(map);
                break;
            case 5:
                dto.setFive(map);
                break;
            case 6:
                dto.setSix(map);
                break;
            case 7:
                dto.setSeven(map);
                break;
            case 8:
                dto.setEight(map);
                break;
            case 9:
                dto.setNine(map);
                break;
            case 10:
                dto.setTen(map);
                break;
            case 11:
                dto.setEleven(map);
                break;
            case 12:
                dto.setTwelve(map);
                break;
            case 13:
                dto.setThirteen(map);
                break;
            case 14:
                dto.setFourteen(map);
                break;
            case 15:
                dto.setFifteen(map);
                break;
            case 16:
                dto.setSixteen(map);
                break;
            case 17:
                dto.setSeventeen(map);
                break;
            case 18:
                dto.setEighteen(map);
                break;
            case 19:
                dto.setNineteen(map);
                break;
            case 20:
                dto.setTwenty(map);
                break;
            case 21:
                dto.setTwentyOne(map);
                break;
            case 22:
                dto.setTwentyTwo(map);
                break;
            case 23:
                dto.setTwentyThree(map);
                break;
            case 24:
                dto.setTwentyFour(map);
                break;
            case 25:
                dto.setTwentyFive(map);
                break;
            case 26:
                dto.setTwentySix(map);
                break;
            case 27:
                dto.setTwentySeven(map);
                break;
            case 28:
                dto.setTwentyEight(map);
                break;
            case 29:
                dto.setTwentyNine(map);
                break;
            case 30:
                dto.setThirty(map);
                break;
            case 31:
                dto.setThirtyOne(map);
                break;
        }
    }
        return null;
    /**
     * 给每天的字段赋值
     * @param day
     * @param dto
     * @param shiftName
     */
    private void setEnglishDay(int day, ExportSchedulingDetailDto dto, String shiftName) {
        switch (day) {
            case 1:
                dto.setOne(shiftName);
                break;
            case 2:
                dto.setTwo(shiftName);
                break;
            case 3:
                dto.setThree(shiftName);
                break;
            case 4:
                dto.setFour(shiftName);
                break;
            case 5:
                dto.setFive(shiftName);
                break;
            case 6:
                dto.setSix(shiftName);
                break;
            case 7:
                dto.setSeven(shiftName);
                break;
            case 8:
                dto.setEight(shiftName);
                break;
            case 9:
                dto.setNine(shiftName);
                break;
            case 10:
                dto.setTen(shiftName);
                break;
            case 11:
                dto.setEleven(shiftName);
                break;
            case 12:
                dto.setTwelve(shiftName);
                break;
            case 13:
                dto.setThirteen(shiftName);
                break;
            case 14:
                dto.setFourteen(shiftName);
                break;
            case 15:
                dto.setFifteen(shiftName);
                break;
            case 16:
                dto.setSixteen(shiftName);
                break;
            case 17:
                dto.setSeventeen(shiftName);
                break;
            case 18:
                dto.setEighteen(shiftName);
                break;
            case 19:
                dto.setNineteen(shiftName);
                break;
            case 20:
                dto.setTwenty(shiftName);
                break;
            case 21:
                dto.setTwentyOne(shiftName);
                break;
            case 22:
                dto.setTwentyTwo(shiftName);
                break;
            case 23:
                dto.setTwentyThree(shiftName);
                break;
            case 24:
                dto.setTwentyFour(shiftName);
                break;
            case 25:
                dto.setTwentyFive(shiftName);
                break;
            case 26:
                dto.setTwentySix(shiftName);
                break;
            case 27:
                dto.setTwentySeven(shiftName);
                break;
            case 28:
                dto.setTwentyEight(shiftName);
                break;
            case 29:
                dto.setTwentyNine(shiftName);
                break;
            case 30:
                dto.setThirty(shiftName);
                break;
            case 31:
                dto.setThirtyOne(shiftName);
                break;
        }
    }
    /**
     * 保存排班明细
     *
     * @param vo
     * @return
     */
    @Override
    public R saveSchedulingDetail(SaveSchedulingVo vo, Long userId) {
        String month = vo.getMonth();
        List<XpSchedulingDetail> list = this.list(new QueryWrapper<XpSchedulingDetail>().eq("is_deleted", 0).last(" and DATE_FORMAT(planTime,'%Y-%m') = '" + month + "'"));
        //保存排班数据
        XpScheduling xpScheduling = xpSchedulingService.getOne(new QueryWrapper<XpScheduling>().eq("is_deleted", 0).last(" and DATE_FORMAT(schedulingDate,'%Y-%m') = '" + month + "'"));
        if(null == xpScheduling){
            xpScheduling = new XpScheduling();
            xpScheduling.setDeleted(false);
            xpScheduling.setCreateTime(LocalDateTime.now());
            xpScheduling.setUpdateTime(LocalDateTime.now());
            xpScheduling.setCreateBy(userId.toString());
            xpScheduling.setUpdateBy(userId.toString());
        }
        xpScheduling.setSchedulingDate(LocalDate.parse(month, DateTimeFormatter.ofPattern("yyyy-MM")));
        xpScheduling.setCommitUserId(userId);
        xpSchedulingService.saveOrUpdate(xpScheduling);
        List<XpShift> xpShifts = xpShiftService.list(new QueryWrapper<XpShift>().eq("is_deleted", 0));
        //构建排班明细数据
        List<SaveSchedulingDetailVo> datas = vo.getDatas();
        List<XpSchedulingDetail> schedulingDetails = new ArrayList<>();
        for (SaveSchedulingDetailVo data : datas) {
            Long fleetId = data.getFleetId();
            List<SaveSchedulingDetailDay> days = data.getDays();
            for (SaveSchedulingDetailDay day : days) {
                Long shiftId = day.getShiftId();
                LocalDate parse = LocalDate.parse(day.getDayTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                //查询判断数据是否存在
                XpSchedulingDetail schedulingDetail = list.stream().filter(s -> s.getFleetId().equals(fleetId)
                        && s.getShiftId().equals(shiftId)
                        && s.getPlanTime().equals(parse)
                ).findAny().orElse(null);
                //构建存储对象
                if(null == schedulingDetail){
                    schedulingDetail = new XpSchedulingDetail();
                    schedulingDetail.setCreateBy(userId.toString());
                    schedulingDetail.setCreateTime(LocalDateTime.now());
                    schedulingDetail.setUpdateBy(userId.toString());
                    schedulingDetail.setUpdateTime(LocalDateTime.now());
                    schedulingDetail.setDeleted(false);
                }else{
                    //构建通知消息
                    Long old_shiftId = schedulingDetail.getShiftId();
                    if(!old_shiftId.equals(shiftId)){
                        //获取车队的所有人员
                        XpShift xpShift1 = xpShifts.stream().filter(s -> s.getId().equals(old_shiftId)).findAny().orElse(null);
                        XpShift xpShift2 = xpShifts.stream().filter(s -> s.getId().equals(shiftId)).findAny().orElse(null);
                        List<Long> operationsIds = xpFleetOperationsClient.getOperationsIdsByFleetId(fleetId).getData();
                        if(null != operationsIds && !operationsIds.isEmpty()){
                            List<XpOperationsUser> data1 = xpOperationUserClient.listByIds(operationsIds).getData();
                            for (XpOperationsUser xpOperationsUser : data1) {
                                String nickName = xpOperationsUser.getNickName();
                                String message = nickName + "请注意," + month + "你的排班由" + xpShift1.getShiftName() + "变更为了" + xpShift2.getShiftName() + "。详情请联系平台管理员。";
                            }
                        }
                    }
                }
                schedulingDetail.setSchedulingId(xpScheduling.getId());
                schedulingDetail.setFleetId(fleetId);
                schedulingDetail.setShiftId(shiftId);
                XpShift xpShift = xpShifts.stream().filter(s -> s.getId().equals(shiftId)).findAny().orElse(null);
                schedulingDetail.setIsAllDay(xpShift.getShiftName().contains("全天"));
                schedulingDetail.setPlanTime(parse);
                schedulingDetails.add(schedulingDetail);
            }
        }
        //批量保存排班明细数据
        if(schedulingDetails.isEmpty()){
            this.saveOrUpdateBatch(schedulingDetails);
        }
        return R.ok();
    }
    /**
     * 导出排班数据
     * @param month
     * @param response
     */
    @Override
    public void exportExcel(String month, HttpServletResponse response) {
        PageInfo<SchedulingDetailDto> pageInfo = new PageInfo<>(0, 10000);
        List<SchedulingDetailDto> schedulingDetailDtos = this.baseMapper.pageList(pageInfo, month);
        List<ExportSchedulingDetailDto> exportSchedulingDetailDtos = new ArrayList<>();
        //获取月份的最大天数
        LocalDate parse1 = LocalDate.parse(month, DateTimeFormatter.ofPattern("yyyy-MM"));
        int dayOfMonth = parse1.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        //构建表头第二行数据
        ExportSchedulingDetailDto exportSchedulingDetailDto = new ExportSchedulingDetailDto();
        exportSchedulingDetailDto.setFleetName("");
        for (int i = 1; i <= dayOfMonth; i++) {
            LocalDate parse = LocalDate.parse(month + "-" + i, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String week = "";
            switch (parse.getDayOfWeek()){
                case MONDAY:
                    week = "一";
                    break;
                case TUESDAY:
                    week = "二";
                    break;
                case WEDNESDAY:
                    week = "三";
                    break;
                case THURSDAY:
                    week = "四";
                    break;
                case FRIDAY:
                    week = "五";
                    break;
                case SATURDAY:
                    week = "六";
                    break;
                case SUNDAY:
                    week = "日";
                    break;
            }
            setEnglishDay(i, exportSchedulingDetailDto, week);
        }
        exportSchedulingDetailDto.setAllDay("全天");
        exportSchedulingDetailDto.setMorning("早");
        exportSchedulingDetailDto.setMidDay("中");
        exportSchedulingDetailDto.setEvening("晚");
        exportSchedulingDetailDtos.add(exportSchedulingDetailDto);
        //构建数据部分的内容
        for (SchedulingDetailDto schedulingDetailDto : schedulingDetailDtos) {
            exportSchedulingDetailDto = new ExportSchedulingDetailDto();
            exportSchedulingDetailDto.setFleetName(schedulingDetailDto.getFleetName());
            String days = schedulingDetailDto.getDays();
            if (StringUtils.isNotBlank(days)) {
                String[] split = days.split(",");
                List<String> list = Arrays.asList(split);
                for (int i = 1; i <= dayOfMonth; i++) {
                    String shiftName = "休";
                    for (String s : split) {
                        String[] split1 = s.split("_");
                        if (i == Integer.parseInt(split1[0])) {
                            shiftName = split1[2];
                            break;
                        }
                    }
                    setEnglishDay(i, exportSchedulingDetailDto, shiftName);
                }
                long allDay = list.stream().filter(s -> s.contains("全天")).count();
                long morning = list.stream().filter(s -> s.contains("早")).count();
                long midDay = list.stream().filter(s -> s.contains("中")).count();
                long evening = list.stream().filter(s -> s.contains("晚")).count();
                exportSchedulingDetailDto.setAllDay(allDay + "");
                exportSchedulingDetailDto.setMorning(morning + "");
                exportSchedulingDetailDto.setMidDay(midDay + "");
                exportSchedulingDetailDto.setEvening(evening + "");
            }else{
                for (int i = 1; i <= 31; i++) {
                    String shiftName = "休";
                    setEnglishDay(i, exportSchedulingDetailDto, shiftName);
                }
                exportSchedulingDetailDto.setAllDay("0");
                exportSchedulingDetailDto.setMorning("0");
                exportSchedulingDetailDto.setMidDay("0");
                exportSchedulingDetailDto.setEvening("0");
            }
            exportSchedulingDetailDtos.add(exportSchedulingDetailDto);
        }
        String[] split = month.split("-");
        ExcelUtil<ExportSchedulingDetailDto> excelUtil = new ExcelUtil<>(ExportSchedulingDetailDto.class);
        excelUtil.exportExcel(response, exportSchedulingDetailDtos, "排班计划", "日期:" + split[0] + "年" + split[1] + "月");
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -1,17 +1,27 @@
package com.xiaopeng.maintenance.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.pushMessage.AliPushMessageDTO;
import com.xiaopeng.api.feignClient.account.SysUserClient;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.account.XpOperationUserNotificationClient;
import com.xiaopeng.api.feignClient.pushMessage.XpAliPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsRole;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.api.model.maintenance.*;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.common.core.constant.AliPushTypeConstant;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.NotificationTypeEnum;
import com.xiaopeng.common.core.enums.TaskTypeEnum;
import com.xiaopeng.common.core.enums.TaskTypeNotificationEnum;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.constant.I18nKeyConstant;
@@ -25,6 +35,8 @@
import com.xiaopeng.maintenance.model.query.WorkBenchQuery;
import com.xiaopeng.maintenance.model.query.XpTaskRecordPageQuery;
import com.xiaopeng.maintenance.model.vo.*;
import com.xiaopeng.maintenance.service.IXpTaskRuleRoleService;
import com.xiaopeng.maintenance.service.IXpTaskRuleService;
import com.xiaopeng.maintenance.service.XpTaskService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
@@ -57,22 +69,6 @@
    private RedissonClient redissonClient;
    @Autowired
    private XpErrorTypeMapper errorTypeMapper;
    /**
     * 常规任务类型映射
     */
    private static final Map<String, String> TASK_TYPE_MAP = new java.util.HashMap<>();
    static {
        TASK_TYPE_MAP.put("1", "车辆检查");
        TASK_TYPE_MAP.put("2", "车辆充电");
        TASK_TYPE_MAP.put("3", "车辆整备");
        TASK_TYPE_MAP.put("4", "整备洗车");
        TASK_TYPE_MAP.put("5", "车辆维修");
        TASK_TYPE_MAP.put("6", "车辆保养");
        TASK_TYPE_MAP.put("7", "车辆保险到期");
        TASK_TYPE_MAP.put("8", "车辆年检到期");
        TASK_TYPE_MAP.put("9", "车辆运营资质到期");
    }
    @Autowired
    private XpTaskHandleDetailMapper xpTaskHandleDetailMapper;
@@ -98,6 +94,14 @@
    private XpVehicleClient xpVehicleClient;
    @Autowired
    private XpTaskRuleMapper xpTaskRuleMapper;
    @Autowired
    private XpAliPushMessageClient xpAliPushMessageClient;
    @Autowired
    private XpOperationUserNotificationClient xpOperationUserNotificationClient;
    @Autowired
    private IXpTaskRuleRoleService xpTaskRuleRoleService;
    @Autowired
    private IXpTaskRuleService xpTaskRuleService;
    @Override
    public PageInfo<WorkBenchVO> workbench(WorkBenchQuery query) {
@@ -162,14 +166,74 @@
        xpTask.setTaskDescription(dto.getTaskDescription());
        // todo 获取车辆当前位置
//        xpTask.setVehicleLocation();
//        xpTask.setVehicleId();
       xpTask.setVehicleId(dto.getId());
//        xpTask.setVehicleLon();
//        xpTask.setVehicleLat();
        xpTask.setReportUserId(xpOperationsUser.getId());
        xpTask.setReportTime(LocalDateTime.now());
        xpTask.setStatus(0);
        xpTask.setCreateBy(xpOperationsUser.getNickName());
        XpTaskRule taskRule = xpTaskRuleService.lambdaQuery().last("limit 1").one();
        XpTaskRuleRole taskRuleRole = xpTaskRuleRoleService.lambdaQuery().eq(XpTaskRuleRole::getRuleType, 9).last("limit 1").one();
        if (Objects.isNull(taskRuleRole) || Objects.isNull(taskRule)) {
            throw new ServiceException("未配置车辆事故任务分配规则", I18nKeyConstant.TASK_RULE_NOT_CONFIG);
        }
        R<List<XpOperationsRole>> xpOperationsRoleResult = xpOperationUserClient.getXpOperationsRoleByRoleId(taskRuleRole.getRoleId());
        if (CollUtil.isNotEmpty(xpOperationsRoleResult.getData())) {
            List<Long> userIds = xpOperationsRoleResult.getData().stream().map(XpOperationsRole::getOperationsUserId).collect(Collectors.toList());
            xpTask.setHandleUserId(StringUtils.join(userIds, ","));
        }
        this.save(xpTask);
        //发送消息通知
        List<Long> userIds = Arrays.stream(xpTask.getHandleUserId().split(",")).map(Long::valueOf).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userIds)) {
            R<List<XpOperationsUser>> xpOperationUserResult = xpOperationUserClient.listByIds(userIds);
            List<XpOperationsUser> data = xpOperationUserResult.getData();
            if (CollUtil.isNotEmpty(data)) {
                R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(dto.getId());
                XpVehicle vehicle = xpVehicleR.getData();
                String plateNumber = Objects.nonNull(vehicle) ? vehicle.getPlateNumber() : "";
                // 车辆${车牌号}在${车辆位置信息}发生了紧急事故,请在${到达现场限时}内到达现场!${APP链接}
                String content = String.format("车辆%s在%s发生了紧急事故,请在%d分钟内到达现场!", plateNumber, xpTask.getVehicleLocation(), taskRule.getProcessingTimeLimit());
                List<XpOperationsUserNotification> notifications = data.stream().map(item -> {
                    XpOperationsUserNotification notification = new XpOperationsUserNotification();
                    notification.setOperationsUserId(item.getId());
                    notification.setNotificationContent(content);
                    notification.setReadStatus(0);
                    notification.setCreateTime(LocalDateTime.now());
                    return notification;
                }).collect(Collectors.toList());
                xpOperationUserNotificationClient.addNotificationBatch(notifications);
                // 发送阿里云推送
                Map<Integer, List<XpOperationsUser>> operationUserMap = data.stream().collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
                for (Map.Entry<Integer, List<XpOperationsUser>> integerListEntry : operationUserMap.entrySet()) {
                    List<XpOperationsUser> value = integerListEntry.getValue();
                    pushAliMessage(value, content, xpTask);
                }
            }
        }
    }
    /**
     * 推送阿里云通知
     * @param data
     * @param content
     * @param xpTask
     */
    private void pushAliMessage(List<XpOperationsUser> data, String content, XpTask xpTask) {
        String account = data.stream().map(XpOperationsUser::getPhoneNumber).filter(Objects::nonNull).collect(Collectors.joining(","));
        Map<String, Object> param = new HashMap<>();
        param.put("content", content);
        param.put("strategy", NotificationTypeEnum.ACCIDENT_NEW.getCode());
        param.put("type", TaskTypeNotificationEnum.ACCIDENT_TASK.getCode());
        param.put("id", xpTask.getId().toString());
        xpAliPushMessageClient.pushMessage(AliPushMessageDTO.builder()
                .body(JSONObject.toJSONString(param))
                .account(account).title("车辆事故警示")
                .pushType(AliPushTypeConstant.NOTICE)
                        .deviceType(data.get(0).getDeviceType())
                .build());
    }
    @Override
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -1,4 +1,5 @@
# 中文
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
vehicle.not.exist=车辆不存在
task.rule.not.config=未配置车辆事故任务分配规则
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -2,3 +2,4 @@
welcome.message=Welcome to our application!
task.not.exist=The task does not exist.
vehicle.not.exist=The vehicle does not exist.
task.rule.not.config=The vehicle accident task allocation rules have not been configured
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -1,4 +1,5 @@
# 中文
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
vehicle.not.exist=车辆不存在
task.rule.not.config=未配置车辆事故任务分配规则
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpSchedulingDetailMapper.xml
@@ -4,9 +4,20 @@
    <select id="pageList" resultType="com.xiaopeng.maintenance.dto.SchedulingDetailDto">
        select * from xp_scheduling_detail where 1=1
        SELECT
            aa.fleet_id as fleetId
            aa.fleet_name as fleetName,
            bb.days
        FROM
            xp_fleet aa
        LEFT JOIN (
            select
            a.fleet_id, GROUP_CONCAT(concat(DATE_FORMAT(a.plan_time, '%d' ), '_', a.shift_id, '_', b.shift_name, '_', b.shift_color)) as days
            from xp_scheduling_detail a
            left join xp_shift b on (a.shift_id = b.id)
            where a.is_deleted = 0 and DATE_FORMAT(a.plan_time, '%Y-%m') = #{month}
            group by a.fleet_id
        ) AS bb ON ( aa.id = bb.fleet_id)
        WHERE aa.is_deleted = 0
    </select>
</mapper>
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpMapController.java
@@ -4,6 +4,8 @@
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.vo.map.PointByIpVo;
import com.xiaopeng.api.vo.map.XpDistanceAndDurationVo;
import com.xiaopeng.api.vo.operation.RouteVo;
@@ -38,11 +40,13 @@
    private final GDMapGeocodingUtil gdMapGeocodingUtil;
    private final XpGeoFencingPolygonService xpGeoFencingPolygonService;
    private final RedisService redisService;
    private final XpOrderClient xpOrderClient;
    public XpMapController(GDMapGeocodingUtil gdMapGeocodingUtil, XpGeoFencingPolygonService xpGeoFencingPolygonService, RedisService redisService) {
    public XpMapController(GDMapGeocodingUtil gdMapGeocodingUtil, XpGeoFencingPolygonService xpGeoFencingPolygonService, RedisService redisService, XpOrderClient xpOrderClient) {
        this.gdMapGeocodingUtil = gdMapGeocodingUtil;
        this.xpGeoFencingPolygonService = xpGeoFencingPolygonService;
        this.redisService = redisService;
        this.xpOrderClient = xpOrderClient;
    }
@@ -57,24 +61,29 @@
        // 避让区域
        ArrayList<String> pointStrParam = new ArrayList<>();
        for (Document document : pointsInFence) {
            List<GeoPoint> points = document.getList("points", GeoPoint.class);
            // 一个区域的点位
            ArrayList<String> pointStr = new ArrayList<>();
            for (GeoPoint point : points) {
                pointStr.add( point.getLongitude()+","+point.getLatitude());
        try {
            for (Document document : pointsInFence) {
                List<GeoPoint> points = document.getList("points", GeoPoint.class);
                // 一个区域的点位
                ArrayList<String> pointStr = new ArrayList<>();
                for (GeoPoint point : points) {
                    pointStr.add( point.getLongitude()+","+point.getLatitude());
                }
                if(!pointStr.isEmpty()){
                    pointStrParam.add(String.join(";", pointStr));
                }
            }
            if(!pointStr.isEmpty()){
                pointStrParam.add(String.join(";", pointStr));
            RouteVo routeVo = gdMapGeocodingUtil.getDistanceAndTime(dto.getOrigin(), dto.getDestination(), String.join("|", pointStrParam), fenceId,dto.getRoutePlanRule());
            if(routeVo==null){
                return R.fail("没有找到路线");
            }
            return R.ok(routeVo);
        }catch (Exception e){
            e.printStackTrace();
        }
        RouteVo routeVo = gdMapGeocodingUtil.getDistanceAndTime(dto.getOrigin(), dto.getDestination(), String.join("|", pointStrParam), fenceId,dto.getRoutePlanRule());
        if(routeVo==null){
            return R.fail("没有找到路线");
        }
        return R.ok(routeVo);
        return R.fail("没有找到路线");
    }
@@ -112,7 +121,6 @@
        // 存储redis
        redisService.setCacheObject(CacheConstants.ORDER_ROUTE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo);
        // 存储路线偏离缓存,后续进行轨迹截取
        redisService.setCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo);
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java
@@ -57,8 +57,10 @@
    @ApiOperation(value = "获取所有运营中的区域", response = XpElectronicFenceArea.class)
    @PostMapping("/listElectronicFenceArea")
    public R<List<XpElectronicFenceArea>> listElectronicFenceArea() {
        R<List<XpElectronicFenceArea>> listR = xpPointClient.listElectronicFenceArea();
        return xpPointClient.listElectronicFenceArea();
        return listR;
    }
    @ApiOperation(value = "点位管理分页列表", response = XpPoint.class)
    @PostMapping("/pageList")
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpInvitationCodeController.java
@@ -109,7 +109,7 @@
        HttpServletResponse response = WebUtils.response();
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("邀请码导入模板.xls", "utf-8");
            String fileName = URLEncoder.encode("邀请码导入模板.xlsx", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Pragma", "no-cache");
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointController.java
@@ -6,6 +6,7 @@
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.api.vo.order.XpPointsSearchVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.controller.BaseController;
@@ -21,6 +22,7 @@
import javax.validation.Valid;
import java.util.List;
import java.util.Set;
@Slf4j
@RestController
@@ -79,6 +81,12 @@
    }
    @PostMapping("/inner/point/getPointsInfo")
    public R<List<XpPoint>> getPointsInfo(@RequestBody Set<Long> points){
        List<XpPoint> xpPoints = xpPointService.listByIds(points);
        return R.ok(xpPoints);
    }
    /**
     * 获取下单最大距离 最小距离
     */
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointManagementController.java
@@ -1,6 +1,7 @@
package com.xiaopeng.operation.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xiaopeng.api.dto.map.XpPointExportExcelQuery;
import com.xiaopeng.api.dto.operation.PointAddDto;
@@ -16,6 +17,8 @@
import com.xiaopeng.operation.service.IXpElectronicFenceAreaService;
import com.xiaopeng.operation.service.IXpElectronicFenceService;
import com.xiaopeng.operation.service.XpPointService;
import com.xiaopeng.operation.vo.SpecialPointListVo;
import com.xiaopeng.operation.vo.SpecialPointVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@@ -147,8 +150,50 @@
    @ApiOperation(value = "设置特殊点位",tags = "后台管理-特殊点位")
    public R setSpecialPoint(@RequestBody XpPointSpecialDto dto) {
        xpPointService.update(new LambdaUpdateWrapper<XpPoint>().set(XpPoint::getChargePoint, 0).set(XpPoint::getParkingPoint,0));
        xpPointService.update(new LambdaUpdateWrapper<XpPoint>().in(XpPoint::getId,dto.getChargePoints()).set(XpPoint::getChargePoint,1));
        xpPointService.update(new LambdaUpdateWrapper<XpPoint>().in(XpPoint::getId,dto.getParkingPoints()).set(XpPoint::getParkingPoint,2));
        List<XpPoint> list = xpPointService.list(new LambdaQueryWrapper<XpPoint>().in(XpPoint::getId, dto.getChargePoints()));
        list.forEach(e->{
            e.setChargePoint(1);
            e.setElectronicAreaId(null);
        });
        xpPointService.updateBatchById(list);
        List<XpPoint> list1 = xpPointService.list(new LambdaQueryWrapper<XpPoint>().in(XpPoint::getId, dto.getParkingPoints()));
        list1.forEach(e->{
            e.setParkingPoint(1);
            e.setElectronicAreaId(null);
        });
        xpPointService.updateBatchById(list1);
        return R.ok();
    }
    @GetMapping("/listSpecialPoint")
    @ApiOperation(value = "获取特殊点位",tags = "后台管理-特殊点位")
    public R<SpecialPointVo> getSpecialPoint() {
        List<XpPoint> chargePoints = xpPointService.list(new LambdaQueryWrapper<XpPoint>().eq(XpPoint::getChargePoint, 1));
        List<XpPoint> parkingPoints = xpPointService.list(new LambdaQueryWrapper<XpPoint>().eq(XpPoint::getParkingPoint, 1));
        SpecialPointVo specialPointVo = new SpecialPointVo();
        ArrayList<SpecialPointListVo> chargePointsList = new ArrayList<>();
        for (XpPoint chargePoint : chargePoints) {
            SpecialPointListVo specialPointListVo = new SpecialPointListVo();
            specialPointListVo.setPointName(chargePoint.getPointName());
            specialPointListVo.setPointAddress(chargePoint.getPointAddress());
            specialPointListVo.setPointId(chargePoint.getId());
            chargePointsList.add(specialPointListVo);
        }
        specialPointVo.setChargePoints(chargePointsList);
        ArrayList<SpecialPointListVo> parkingPointsList = new ArrayList<>();
        for (XpPoint parkingPoint : parkingPoints) {
            SpecialPointListVo specialPointListVo = new SpecialPointListVo();
            specialPointListVo.setPointName(parkingPoint.getPointName());
            specialPointListVo.setPointAddress(parkingPoint.getPointAddress());
            specialPointListVo.setPointId(parkingPoint.getId());
            parkingPointsList.add(specialPointListVo);
        }
        specialPointVo.setParkingPoints(parkingPointsList);
        return R.ok(specialPointVo);
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java
@@ -78,7 +78,7 @@
                redisService.deleteObject(CacheConstants.XP_REGION);
            }
        }else {
            list = regionService.list(Wrappers.lambdaQuery(XpRegion.class).ne(XpRegion::getParentId, 0).orderByAsc(XpRegion::getInitial));
            list = regionService.list(Wrappers.lambdaQuery(XpRegion.class).ne(XpRegion::getParentId, 0).isNotNull(XpRegion::getInitial).orderByAsc(XpRegion::getInitial));
            redisService.setCacheList(CacheConstants.XP_REGION_CITY, list);
        }
        List<XpOpenCity> openCities = openCityService.list(new LambdaQueryWrapper<XpOpenCity>().eq(XpOpenCity::getStatus,1));
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpCruisePlanServiceImpl.java
@@ -21,10 +21,7 @@
import com.xiaopeng.operation.dto.XpCruisePlanEditDTO;
import com.xiaopeng.operation.mapper.XpCruisePlanMapper;
import com.xiaopeng.operation.query.CruisePlanQuery;
import com.xiaopeng.operation.service.IXpCruisePlanPointService;
import com.xiaopeng.operation.service.IXpCruisePlanService;
import com.xiaopeng.operation.service.IXpCruisePlanVehicleService;
import com.xiaopeng.operation.service.IXpPointService;
import com.xiaopeng.operation.service.*;
import com.xiaopeng.operation.vo.XpCruisePlanDetailVO;
import com.xiaopeng.operation.vo.XpCruisePlanPointVO;
import com.xiaopeng.operation.vo.XpCruisePlanVehicleVO;
@@ -51,7 +48,7 @@
    private final IXpCruisePlanPointService xpCruisePlanPointService;
    private final IXpCruisePlanVehicleService xpCruisePlanVehicleService;
    private final IXpPointService xpPointService;
    private final XpPointService xpPointService;
    private final XpVehicleClient xpVehicleClient;
    private final XpFleetVehicleClient xpFleetVehicleClient;
    private final XpFleetClient xpFleetClient;
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
@@ -176,6 +176,8 @@
            xpHistoryStartPointsVo.setId(xpPoint.getId());
            double distanced = FastDistanceCalculator.distanceFastKm(historyStartPointsDto.getLat(), historyStartPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon());
            xpHistoryStartPointsVo.setDistance(distanced);
            xpHistoryStartPointsVo.setTime(xpPoint.getParkingTimeLimit());
            xpHistoryStartPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId());
            resultList.add(xpHistoryStartPointsVo);
        }
@@ -196,6 +198,8 @@
            xpHistoryEndPointsVo.setId(xpPoint.getId());
            double distanced = FastDistanceCalculator.distanceFastKm(historyEndPointsDto.getLat(), historyEndPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon());
            xpHistoryEndPointsVo.setDistance(distanced);
            xpHistoryEndPointsVo.setTime(xpPoint.getParkingTimeLimit());
            xpHistoryEndPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId());
            resultList.add(xpHistoryEndPointsVo);
        }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -469,14 +469,14 @@
        // 根据id获取手机号
        Boolean isPriorityDispatch = false;
        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
        if (xpAppUserR.getCode() == R.SUCCESS) {
            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
            if (count > 0) {
                isPriorityDispatch = true;
            }
        }
        Boolean isPriorityDispatch = true;
//        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
//        if (xpAppUserR.getCode() == R.SUCCESS) {
//            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
//            if (count > 0) {
//                isPriorityDispatch = true;
//            }
//        }
        // 生成订单数据
        XpOrder xpOrder = new XpOrder();
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java
@@ -68,7 +68,7 @@
                "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<XpRegion> tRegions = this.baseMapper.selectList(Wrappers.lambdaQuery(XpRegion.class).isNotNull(XpRegion::getInitial));
        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());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -4,19 +4,23 @@
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.dto.QueryOrderRouteDTO;
import com.xiaopeng.api.dto.order.GetOrderNumDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.FareBreakdownVo;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.WebUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.order.mangodb.model.OrderTrajectory;
import com.xiaopeng.order.model.dto.XpOrderCommentDto;
import com.xiaopeng.order.model.dto.XpOrderPayDto;
@@ -62,6 +66,7 @@
public class XpOrderController {
    private final IXpOrderService xpOrderService;
    private final RedisService redisService;
    /**
     * 获取订单统计数据(内部接口)
@@ -395,6 +400,17 @@
        String uid = request.getHeader("XP-Uid");
        return xpOrderService.fareBreakdown(orderId,uid);
    }
    /**+
     * 获取行程费用明细
     */
    @PutMapping("/api/v1/mini-program/order/feeDescription/{orderId}")
    @ApiOperation(value = "获取费用说明", tags = {"小程序-获取费用说明"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<String> feeDescription(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return xpOrderService.feeDescription(orderId,uid);
    }
    /**
     * 订单评价
     */
@@ -451,4 +467,18 @@
        return R.ok();
    }
    /**
     * 订单查询实时轨迹路线
     */
    @ApiOperation(value = "订单查询实时轨迹路线")
    @PostMapping("/api/v1/mini-program/order/queryOrderRoute")
    public R<RouteVo> queryOrderRoute(@Validated @RequestBody QueryOrderRouteDTO dto, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
        // 查询订单信息
//        XpOrder xpOrder = xpOrderService.getById(dto.getOrderId());
        // 获取路线规划
        RouteVo routeVo = redisService.getCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType());
        return R.ok(routeVo);
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderHistoryListVO.java
@@ -29,7 +29,40 @@
    @ApiModelProperty("订单金额")
    private Double amount;
    private String timeStr;
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private LocalDateTime time;
    private Long startPointId;
    private String  startPointName;
    private Double  startLon;
    private Double  startLat;
    private Long xpElectronicFenceAreaId;
    private Integer startParkingTimeLimit;
    private Long endPointId;
    private String  endPointName;
    private Double endLat;
    private Double endLon;
    private Integer endParkingTimeLimit;
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -196,4 +196,6 @@
    void popOrder(PopOrderDto dto);
    OrderDetailVo orderDetail(Long orderId, String uid);
    R<String> feeDescription(Long orderId, String uid);
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -696,18 +696,50 @@
    public XpOrderHistoryVO getHistoryOrderList(XpHistoryOrderListQuery query, String uid) {
        Page<XpOrderHistoryListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        List<XpOrderHistoryListVO> list = this.baseMapper.getHistoryOrderList(page, query, Long.parseLong(uid));
        XpOrderHistoryVO xpOrderHistoryVO = new XpOrderHistoryVO();
        if(list.isEmpty()){
            return xpOrderHistoryVO;
        }
        Set<Long> points = list.stream().map(XpOrderHistoryListVO::getStartPointId).collect(Collectors.toSet());
        points.addAll(list.stream().map(XpOrderHistoryListVO::getEndPointId).collect(Collectors.toSet()));
        // 查询 点位信息
        R<List<XpPoint>> pointInfoVos = xpPointClient.getPointsInfo(points);
        List<XpPoint> pointList = pointInfoVos.getData();
        xpOrderHistoryVO.setTotal((int) page.getTotal());
        // 根据time分组
        Map<String, List<XpOrderHistoryListVO>> map = list.stream().collect(Collectors.groupingBy(XpOrderHistoryListVO::getOrderTime));
        Map<String, List<XpOrderHistoryListVO>> map = list.stream().collect(Collectors.groupingBy(XpOrderHistoryListVO::getTimeStr));
        List<XpOrderHistoryDateVO> dateVOS = map.entrySet().stream().map(entry -> {
            XpOrderHistoryDateVO xpOrderHistoryDateVO = new XpOrderHistoryDateVO();
            xpOrderHistoryDateVO.setDateLabel(entry.getKey());
            List<XpOrderHistoryListVO> value = entry.getValue();
            value = value.stream().sorted(Comparator.comparing(XpOrderHistoryListVO::getTime).reversed()).collect(Collectors.toList());
            for (XpOrderHistoryListVO xpOrderHistoryListVO : value) {
                XpPoint xpPoint = pointList.stream().filter(e -> e.getId().equals(xpOrderHistoryListVO.getStartPointId())).findFirst().orElse(null);
                if(xpPoint!=null){
                    xpOrderHistoryListVO.setStartPointName(xpPoint.getPointName());
                    xpOrderHistoryListVO.setStartLat(xpPoint.getPointLat());
                    xpOrderHistoryListVO.setStartLon(xpPoint.getPointLon());
                    xpOrderHistoryListVO.setXpElectronicFenceAreaId(xpPoint.getElectronicAreaId());
                    xpOrderHistoryListVO.setStartParkingTimeLimit(xpPoint.getParkingTimeLimit());
                }
                xpPoint = pointList.stream().filter(e -> e.getId().equals(xpOrderHistoryListVO.getEndPointId())).findFirst().orElse(null);
                if(xpPoint!=null){
                    xpOrderHistoryListVO.setEndPointName(xpPoint.getPointName());
                    xpOrderHistoryListVO.setEndLat(xpPoint.getPointLat());
                    xpOrderHistoryListVO.setEndLon(xpPoint.getPointLon());
                    xpOrderHistoryListVO.setXpElectronicFenceAreaId(xpPoint.getElectronicAreaId());
                    xpOrderHistoryListVO.setEndParkingTimeLimit(xpPoint.getParkingTimeLimit());
                }
            }
            xpOrderHistoryDateVO.setOrders(value);
            return xpOrderHistoryDateVO;
        }).collect(Collectors.toList());
@@ -952,6 +984,7 @@
        order.setStatus(8);
        order.setAppUserId(null);
        order.setTripEnd(LocalDateTime.now());
        order.setMileageKilometers(80.0);
        baseMapper.updateById(order);
        // 解绑用户与车辆关系
        CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
@@ -997,10 +1030,10 @@
        JSONArray startingFareJsonArray = JSONArray.parseArray(pricing.getStartingFareJson());
        if(pricing.getPricingType()==1){
            JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson());
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split("-")[0], basicPricingJson.getString("num21").split("-")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28"))));
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split("-")[0], basicPricingJson.getString("num22").split("-")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28"))));
            config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", basicPricingJson.getString("num14").split("-")[0], basicPricingJson.getString("num14").split("-")[1], Double.parseDouble(basicPricingJson.getString("num16")), Double.parseDouble(basicPricingJson.getString("num17")), Double.parseDouble(basicPricingJson.getString("num18")), Double.parseDouble(basicPricingJson.getString("num19")), Double.parseDouble(basicPricingJson.getString("num20")));
            config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "00:00", "23:59", Double.parseDouble(basicPricingJson.getString("num30")), Double.parseDouble(basicPricingJson.getString("num31")), Double.parseDouble(basicPricingJson.getString("num32")), Double.parseDouble(basicPricingJson.getString("num33")), Double.parseDouble(basicPricingJson.getString("num234")));
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split(" - ")[0], basicPricingJson.getString("num21").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28"))));
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split(" - ")[0], basicPricingJson.getString("num22").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28"))));
            config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", basicPricingJson.getString("num14").split(" - ")[0], basicPricingJson.getString("num14").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num16")), Double.parseDouble(basicPricingJson.getString("num17")), Double.parseDouble(basicPricingJson.getString("num18")), Double.parseDouble(basicPricingJson.getString("num19")), Double.parseDouble(basicPricingJson.getString("num20")));
            config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "00:00", "23:59", Double.parseDouble(basicPricingJson.getString("num30")), Double.parseDouble(basicPricingJson.getString("num31")), Double.parseDouble(basicPricingJson.getString("num32")), Double.parseDouble(basicPricingJson.getString("num33")), Double.parseDouble(basicPricingJson.getString("num34")));
            // --- 远途加价区间配置 (关键修改) ---
            // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2)
            config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num6")), Double.parseDouble(basicPricingJson.getString("num7")), Double.parseDouble(basicPricingJson.getString("num8"))));
@@ -1009,9 +1042,8 @@
            // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值
            config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num12")), 999999, Double.parseDouble(basicPricingJson.getString("num13"))));
        }
        for (Object o : startingFareJsonArray) {
            // 转化为jsonObject
            JSONObject jsonObject = (JSONObject) o;
        for (int i = 0; i < startingFareJsonArray.size(); i++) {
            com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i);
            String num1 = jsonObject.getString("num1");
            String num2 = jsonObject.getString("num2");
            String num3 = jsonObject.getString("num3");
@@ -1021,7 +1053,6 @@
            String num7 = jsonObject.getString("num7");
            config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7)));
        }
        TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService();
        Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getCreateTime()), order.getMileageKilometers(), gpsPoints, config);
@@ -1091,8 +1122,9 @@
                } else if (key.contains("节假")) {
                    startDetail.setType(4);
                }
                startDetail.setDuration(Double.valueOf(key.split("=")[1]));
                startDetail.setMileage(new BigDecimal(key.split("&")[1]));
                String durationAndMileage = key.split("\\|")[2];
                startDetail.setDuration(Double.valueOf(durationAndMileage.split("&")[0]));
                startDetail.setMileage(new BigDecimal(durationAndMileage.split("&")[1]));
                start.add(startDetail);
            }
            // 封装里程费
@@ -1100,8 +1132,8 @@
                FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo();
                if (key.contains("普通时段")) {
                    mileageDetail.setType(1);
                    String key1 = "distance普通时段" + key.split("\\|")[1];
                    String key2 = "普通时段" + key.split("\\|")[1];
                    String key1 = "distance普通时段|" + key.split("\\|")[1];
                    String key2 = "普通时段|" + key.split("\\|")[1];
                    BigDecimal distance = bill.get(key1);
                    BigDecimal money = bill.get(key2);
                    mileageDetail.setMileage(distance);
@@ -1109,8 +1141,8 @@
                    mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate)));
                } else if (key.contains("夜间行驶")) {
                    mileageDetail.setType(2);
                    String key1 = "distance夜间行驶" + key.split("\\|")[1];
                    String key2 = "夜间行驶" + key.split("\\|")[1];
                    String key1 = "distance夜间行驶|" + key.split("\\|")[1];
                    String key2 = "夜间行驶|" + key.split("\\|")[1];
                    BigDecimal distance = bill.get(key1);
                    BigDecimal money = bill.get(key2);
                    mileageDetail.setMileage(distance);
@@ -1119,8 +1151,8 @@
                    mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate)));
                } else if (key.contains("高峰期")) {
                    mileageDetail.setType(3);
                    String key1 = "distance高峰期" + key.split("\\|")[1];
                    String key2 = "高峰期" + key.split("\\|")[1];
                    String key1 = "distance高峰期|" + key.split("\\|")[1];
                    String key2 = "高峰期|" + key.split("\\|")[1];
                    BigDecimal distance = bill.get(key1);
                    BigDecimal money = bill.get(key2);
                    mileageDetail.setMileage(distance);
@@ -1129,8 +1161,8 @@
                    mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate)));
                } else if (key.contains("节假")) {
                    mileageDetail.setType(4);
                    String key1 = "distance节假日" + key.split("\\|")[1];
                    String key2 = "节假日" + key.split("\\|")[1];
                    String key1 = "distance节假日|" + key.split("\\|")[1];
                    String key2 = "节假日|" + key.split("\\|")[1];
                    BigDecimal distance = bill.get(key1);
                    BigDecimal money = bill.get(key2);
                    mileageDetail.setMileage(distance);
@@ -1178,16 +1210,19 @@
        for (XpOrderDetail xpOrderDetail : xpOrderDetails) {
            xpOrderDetailMapper.insert(xpOrderDetail);
        }
        for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) {
            order.setDurationType(fareBreakdownDetailVo.getType());
            order.setDurationMoney(fareBreakdownDetailVo.getMoney());
            order.setDuration(Double.parseDouble(fareBreakdownDetailVo.getDuration() + ""));
        for (XpOrderDetail xpOrderDetail : xpOrderDetails) {
            if (xpOrderDetail.getDetailType() == 1){
                order.setDurationType(xpOrderDetail.getType());
                order.setDurationMoney(xpOrderDetail.getMoney());
                order.setDuration(Double.parseDouble(xpOrderDetail.getDuration() + ""));
            }else{
                order.setLongDistanceType(order.getDurationType());
                order.setLongDistance(xpOrderDetail.getMileage().doubleValue());
                order.setLongDistancemoney(xpOrderDetail.getMoney());
            }
        }
        for (FareBreakdownDetailVo fareBreakdownDetailVo : longDistance) {
            order.setLongDistanceType(fareBreakdownDetailVo.getType());
            order.setLongDistance(fareBreakdownDetailVo.getMileage().doubleValue());
            order.setLongDistancemoney(fareBreakdownDetailVo.getMoney());
        }
        BigDecimal orderMoney = startMoney.add(mileageMoney).add(order.getDurationMoney() != null ? order.getDurationMoney() : BigDecimal.ZERO)
                .add(order.getLongDistancemoney() != null ? order.getLongDistancemoney() : BigDecimal.ZERO)
                .add(order.getWaitMoney()!=null?order.getWaitMoney():BigDecimal.ZERO);
@@ -1478,7 +1513,7 @@
            detail.setTime(xpOrderDetail.getTime());
            detail.setMileage(xpOrderDetail.getMileage());
            detail.setDuration(xpOrderDetail.getDuration());
            if (xpOrderDetail.getType() == 1){
            if (xpOrderDetail.getDetailType() == 1){
                start.add(detail);
            }else{
                mileage.add(detail);
@@ -1490,6 +1525,7 @@
            durationDetail.setType(order.getDurationType());
            durationDetail.setDuration(order.getDuration());
            durationDetail.setMoney(order.getDurationMoney());
            duration.add(durationDetail);
        }
        List<FareBreakdownDetailVo> longDistance = new ArrayList<>();
@@ -1531,6 +1567,7 @@
        // mvp版本不做支付 使用优惠券抵扣为0元订单处理 处理订单状态即可
        XpOrder order = this.getById(dto.getOrderId());
        order.setStatus(9);
        order.setAppUserId(null);
        baseMapper.updateById(order);
        return R.ok();
    }
@@ -1655,6 +1692,18 @@
        return orderDetailVo;
    }
    @Override
    public R<String> feeDescription(Long orderId, String uid) {
        XpOrder order = this.getById(orderId);
        R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCid(order.getCityId());
        XpPricing pricing = pricingByCityId.getData();
        if (pricing == null) {
            throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS);
        }else{
            return R.ok(pricing.getPriceRule());
        }
    }
    /**
     * 成功操作下发命令后调用 用于弹出redis队列的获取成功的数据
@@ -1749,8 +1798,8 @@
            }).collect(Collectors.toList());
            route.put("polyline", collect);
            content.put("route", route);
            jsonObject.put("content", content);
            content.put("route", route.toJSONString());
            jsonObject.put("content", content.toJSONString());
            SendMessageDTO messageDTO = new SendMessageDTO();
            messageDTO.setAppUserId(appUserId);
            messageDTO.setMessage(jsonObject.toJSONString());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java
@@ -41,7 +41,7 @@
            BigDecimal totalMileage = BigDecimal.valueOf(totalMileageKm);
            PricingRule baseRule = config.findMatchedRule(orderTime);
            result.put("起步价(" + baseRule.ruleName + ")"+"|"+baseRule.start+"-"+baseRule.end+"="+baseRule.baseMin+"&"+baseRule.baseKm, baseRule.baseFare);
            result.put("起步价(" + baseRule.ruleName + ")"+"|"+baseRule.start+"-"+baseRule.end+"|"+baseRule.baseMin+"&"+baseRule.baseKm, baseRule.baseFare);
            if (totalMileage.compareTo(baseRule.baseKm) <= 0) {
                return formatMap(result);
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml
@@ -45,8 +45,8 @@
        ORDER BY date ASC
    </select>
    <select id="getHistoryOrderList" resultType="com.xiaopeng.order.model.vo.XpOrderHistoryListVO">
        select start_point_name as originAddress, end_point_name as destinationAddress,
        DATE_FORMAT(create_time, '%H:%i') AS orderTime, pay_money as amount,create_time as time,
        select start_point_name as originAddress, end_point_name as destinationAddress,start_point_id as startPointId,end_point_id as endPointId,
        DATE_FORMAT(create_time, '%H:%i') AS orderTime, pay_money as amount,create_time as time,DATE_FORMAT(create_time,'%Y-%m-%d') AS timeStr,
        id as orderId from xp_order where app_user_id = #{uid} and is_deleted = 0 and status in (9,10)
        <if test="query.status != null">
            and status = #{query.status}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/AliPushController.java
@@ -14,8 +14,6 @@
public class AliPushController {
    @Autowired
    private RedisService redisService;
    @Autowired
    private AliPushUtil aliPushUtil;
    /**
@@ -23,8 +21,17 @@
     * @return
     */
    @GetMapping("/base/v1/aliPush/test")
    public R<String> test() throws Exception {
        String s = aliPushUtil.pushMessage(1, "13540694412", "测试", "{\"content\":\"测试消息\",\"strategy\":1\"type\":1,\"id\":1}");
    public R<String> test(){
        String s = aliPushUtil.pushMessage(1, "13540694412", "事故即将超时提示", "{\"content\":\"车辆川A12345在天府新谷发生的紧急事故即将超时,剩余时间5分钟,请及时到达现场!\",\"strategy\":2\"type\":7,\"id\":1}","NOTICE");
        return R.ok(s);
    }
    /**
     * 运维端消息推送测试
     * @return
     */
    @GetMapping("/base/v1/aliPush/test1")
    public R<String> test1(){
        String s = aliPushUtil.pushMessage(1, "13540694412", "APP版本更新提示", "{\"content\":\"新版本上线啦!请前往更新。\",\"strategy\":8\"type\":0,\"id\":0}","MESSAGE");
        return R.ok(s);
    }
@@ -34,7 +41,7 @@
     */
    @PostMapping("/inner/v1/aliPush/pushMessage")
    public R<String> pushMessage(@RequestBody AliPushMessageDTO dto) {
        String result = aliPushUtil.pushMessage(dto.getDeviceType(), dto.getAccount(), dto.getTitle(), dto.getBody());
        String result = aliPushUtil.pushMessage(dto.getDeviceType(), dto.getAccount(), dto.getTitle(), dto.getBody(),dto.getPushType());
        return R.ok(result);
    }
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/PushOrderRouteController.java
@@ -41,14 +41,19 @@
     */
    @PostMapping("/inner/v1/order/pushOrderRoute")
    public R<String> pushOrderRoute(@Validated @RequestBody PushOrderRouteDTO dto) {
        // 查询订单信息
        XpOrder xpOrder = xpOrderClient.queryOrderById(dto.getOrderId()).getData();
        // 封装消息内容
        Integer routeType = dto.getRouteType();
        if(routeType == 2){
            routeType = 3;
        }else {
            routeType = xpOrder.getStatus() == 3 ? 1 : 2;
        }
        // 获取路线规划
        RouteVo routeVo = redisService.getCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType());
        RouteVo routeVo = redisService.getCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +routeType);
        if(Objects.nonNull(routeVo)){
            // 查询订单信息
            XpOrder xpOrder = xpOrderClient.queryOrderById(dto.getOrderId()).getData();
            // 计算实时点位到线段的最优截取
            List<LonLatDto> lonLatDtos = MapMatchingUtil.clipBySegmentDistance(routeVo.getPolyline(), new LonLatDto(dto.getLongitude(), dto.getLatitude()));
@@ -58,7 +63,7 @@
            routeVo.setPolyline(lonLatDtos);
            // 存储最新路线偏离缓存,后续进行轨迹截取
            redisService.setCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo);
            redisService.setCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +routeType, routeVo);
            // 封装轨迹点位集合
            Map<String, Object> polyline = new HashMap<>();
@@ -72,13 +77,6 @@
            route.put("duration",dto.getDuration());
            route.put("polyline",JSONObject.toJSONString(polyline));
            // 封装消息内容
            Integer routeType = dto.getRouteType();
            if(routeType == 2){
                routeType = 3;
            }else {
                routeType = xpOrder.getStatus() == 4 ? 1 : 2;
            }
            Map<String, Object> content = new HashMap<>();
            content.put("orderId",dto.getOrderId());
            content.put("routeType",routeType);
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/AliPushUtil.java
@@ -34,10 +34,6 @@
    @Value("${ali.push.iosChannelId}")
    private String iosChannelId;
    /**
     * 消息类型  MESSAGE 消息  NOTICE  通知
     */
    private final String PUSH_TYPE = "MESSAGE";
    /**
     * 设备类型 ALL 全部 HARMONY 鸿蒙  IOS ios设备 ANDROID 安卓设备
     */
    private final String DEVICE_TYPE_ALL = "ALL";
@@ -60,9 +56,10 @@
     * @param account 运维手机号
     * @param title 标题
     * @param body 消息内容
     * @param pushType NOTICE:表示通知。 MESSAGE:表示消息。
     * @throws Exception
     */
    public String pushMessage(Integer deviceType,String account, String title, String body){
    public String pushMessage(Integer deviceType,String account, String title, String body,String pushType){
        try {
            StaticCredentialProvider credentialProvider = StaticCredentialProvider.create(
@@ -95,14 +92,28 @@
                PushRequest pushRequest = PushRequest.builder()
                        .appKey(appKeys)
                        .pushType(PUSH_TYPE)
                        .pushType(pushType)
                        .deviceType(DEVICE_TYPE_ALL)
                        .target(TARGET)
                        .targetValue(account)
                        .title(title)
                        .body(body)
                        .androidExtParameters(body)
                        .androidNotificationChannel(channelIds)
                        .build();
                if(deviceType == 2){
                    pushRequest = PushRequest.builder()
                            .appKey(appKeys)
                            .pushType(pushType)
                            .deviceType(DEVICE_TYPE_ALL)
                            .target(TARGET)
                            .targetValue(account)
                            .title(title)
                            .body(body)
                            .iOSExtParameters(body)
                            .androidNotificationChannel(channelIds)
                            .build();
                }
                CompletableFuture<PushResponse> response = client.push(pushRequest);
                PushResponse resp = response.get();
                String json = new Gson().toJson(resp);
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/constant/I18nKeyConstant.java
@@ -28,4 +28,11 @@
    // ========== 车辆开关车门 ==========
    String VEHICLE_NOT_P_GEAR = "vehicle.not.p.gear";
    // ========== 车辆温度控制 ==========
    String VEHICLE_TEMPERATURE_UP = "vehicle.temperature.up";
    String VEHICLE_TEMPERATURE_DOWN = "vehicle.temperature.down";
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetOperationsController.java
@@ -44,7 +44,7 @@
     * @return 车辆isd
     */
    @GetMapping("/inner/fleet-operations/getVehicleByUserId/{id}")
    R<List<Long>> getVehicleByUserId(@PathVariable("id") Long id){
    public R<List<Long>> getVehicleByUserId(@PathVariable("id") Long id){
        List<Long> fleetIds = xpFleetOperationsService.lambdaQuery().eq(XpFleetOperations::getOperationsUserId, id)
                .list().stream().map(XpFleetOperations::getFleetId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(fleetIds)){
@@ -73,4 +73,23 @@
                .collect(Collectors.toList());
        return R.ok(fleetIds);
    }
    /**
     * 根据车队ID查询关联的运维人员ID列表(内部接口)
     *
     * @param fleetId 车队ID
     * @return 运维人员ID列表
     */
    @GetMapping("/inner/fleet-operations/getOperationsIdsByFleetId/{fleetId}")
    public R<List<Long>> getOperationsIdsByFleetId(@PathVariable("fleetId") Long fleetId) {
        List<Long> operationsIds = xpFleetOperationsService.lambdaQuery()
                .eq(XpFleetOperations::getFleetId, fleetId)
                .list()
                .stream()
                .map(XpFleetOperations::getOperationsUserId)
                .distinct()
                .collect(Collectors.toList());
        return R.ok(operationsIds);
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -185,6 +185,12 @@
        if(Objects.isNull(xpVehicle)){
            throw new ServiceException("未查询到有效车辆信息", I18nKeyConstant.VEHICLE_NOT_EXISTS);
        }
        if(dto.getTargetTemperature() > 28){
            throw new ServiceException("温度最高28℃", I18nKeyConstant.VEHICLE_TEMPERATURE_UP);
        }
        if(dto.getTargetTemperature() < 22){
            throw new ServiceException("温度最低22℃", I18nKeyConstant.VEHICLE_TEMPERATURE_DOWN);
        }
        // 设定温度
        VehiclesCommandVo vehiclesCommandVo = new VehiclesCommandVo();
        vehiclesCommandVo.setUid(xpOrder.getAppUserId());
xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages_en_US.properties
@@ -13,4 +13,6 @@
vehicle.operation.info.incomplete=The following information is incomplete and cannot start operation: {0}
vehicle.batch.operation.condition.not.met=The following vehicles do not meet operating conditions: {0}
vehicle.time.expired=The following dates have expired, please enter valid dates: {0}
vehicle.not.p.gear=The trunk cannot be opened when the vehicle is not in P gear
vehicle.not.p.gear=The trunk cannot be opened when the vehicle is not in P gear
vehicle.temperature.up=The highest temperature is 28°C
vehicle.temperature.down=The lowest temperature is 22°C
xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -13,4 +13,6 @@
vehicle.operation.info.incomplete=以下信息未完善,无法开始运营:{0}
vehicle.batch.operation.condition.not.met=以下车辆不满足运营条件:{0}
vehicle.time.expired=以下时间已过期,请填写有效日期:{0}
vehicle.not.p.gear=车辆非P档,无法开启后备箱
vehicle.not.p.gear=车辆非P档,无法开启后备箱
vehicle.temperature.up=温度最高28℃
vehicle.temperature.down=温度最低22℃