xuhy
2026-04-18 c86e794fbd49c90a3abd953be65f100de26e24d6
[feat] 接收任务,socket推送任务
3个文件已添加
5个文件已修改
175 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/pushMessage/WebSocketMessageFallbackFactory.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/pushMessage/WebSocketMessageClient.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/TaskVO.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/controller/WebSocketController.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/pushMessage/WebSocketMessageFallbackFactory.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.api.factory.pushMessage;
import com.xiaopeng.api.dto.pushMessage.AliPushMessageDTO;
import com.xiaopeng.api.feignClient.pushMessage.WebSocketMessageClient;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.common.core.domain.R;
import org.springframework.cloud.openfeign.FallbackFactory;
public class WebSocketMessageFallbackFactory  implements FallbackFactory<WebSocketMessageClient> {
    @Override
    public WebSocketMessageClient create(Throwable cause) {
        return new WebSocketMessageClient() {
            @Override
            public R<String> pushTask(TaskVO dto) {
                return R.fail("发送失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/pushMessage/WebSocketMessageClient.java
New file
@@ -0,0 +1,27 @@
package com.xiaopeng.api.feignClient.pushMessage;
import com.xiaopeng.api.factory.pushMessage.WebSocketMessageFallbackFactory;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
 * 消息Feign客户端
 *
 * @author xiaochen
 */
@FeignClient(contextId = "WebSocketMessageClient",
        value = ServiceNameConstantsEnum.XP_PUSH_MESSAGE_SERVICE,
        fallbackFactory = WebSocketMessageFallbackFactory.class)
public interface WebSocketMessageClient {
    /**
     * 工单推送
     */
    @PostMapping("/inner/websocket/push/task")
    R<String> pushTask(@RequestBody TaskVO dto);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/TaskVO.java
New file
@@ -0,0 +1,64 @@
package com.xiaopeng.api.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
 * 运维APP 任务中心分页列表VO
 * </p>
 *
 * @author mitao
 * @since 2026-02-06
 */
@Data
@ApiModel(value = "任务中心分页列表VO")
public class TaskVO implements Serializable {
    @ApiModelProperty(value = "任务")
    private Long id;
    @ApiModelProperty(value = "任务编号")
    private String taskCode;
    @ApiModelProperty(value = "任务类别1常规 2事故")
    private Integer taskCategory;
    @ApiModelProperty(value = "任务类型id 任务类别为2时对应数据字典,多个逗号分割,为1的时候 枚举1车辆检查 2车辆充电 3车辆整备 4整备洗车 5车辆维修 6车辆保养 7车辆保险到期 8车辆年检到期 9车辆运营资质到期")
    private String taskTypeId;
    @ApiModelProperty(value = "任务类型名称 任务类别为2时返回")
    private String taskTypeName;
    @ApiModelProperty(value = "任务紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer taskUrgencyLevel;
    @ApiModelProperty(value = "任务处理时限")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime endTime;
    @ApiModelProperty(value = "车辆位置")
    private String vehicleLocation;
    @ApiModelProperty(value = "车牌号")
    private String plateNumber;
    @ApiModelProperty(value = "车辆id")
    private Long vehicleId;
    @ApiModelProperty(value = "车辆经度")
    private BigDecimal vehicleLon;
    @ApiModelProperty(value = "车辆纬度")
    private BigDecimal vehicleLat;
    @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消")
    private Integer status;
    @ApiModelProperty(value = "可以操作到达的配置范围,单位米")
    private Double canArriveRange = 200D;
    @ApiModelProperty(value = "处理人id")
    private String handleUserId;
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java
@@ -8,10 +8,9 @@
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.maintenance.XpErrorType;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.api.model.maintenance.XpTaskHandleDetailRoutine;
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.TaskVO;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
@@ -40,7 +39,6 @@
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.transaction.annotation.Transactional;
@@ -101,6 +99,13 @@
        return R.ok(pageList);
    }
    @ApiOperation(value = "接收工单", tags = "运维APP-任务中心")
    @PostMapping("/maintenance-app/api/v1/task/accept")
    public R<?> accept(@RequestBody TaskVO taskVO) {
        xpTaskService.accept(taskVO);
        return R.ok();
    }
    @ApiOperation(value = "工单改派", tags = "运维APP-任务中心")
    @PostMapping("/maintenance-app/api/v1/task/reassign")
    public R<?> reassign(@RequestParam("taskId") Long taskId, @RequestParam("comment") String comment) {
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.dto.HandleVehicleAccidentDto;
@@ -98,4 +99,6 @@
    void reassign(Long taskId, String msg);
    void saveVehicleAccidentError(Long vehicleI);
    void accept(TaskVO taskVO);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -1,5 +1,6 @@
package com.xiaopeng.maintenance.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -13,6 +14,7 @@
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.account.XpOperationUserNotificationClient;
import com.xiaopeng.api.feignClient.operation.SmsClient;
import com.xiaopeng.api.feignClient.pushMessage.WebSocketMessageClient;
import com.xiaopeng.api.feignClient.pushMessage.XpAliPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient;
@@ -23,6 +25,7 @@
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.api.model.maintenance.*;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.api.vo.operation.SmsVo;
@@ -75,6 +78,7 @@
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@@ -420,6 +424,10 @@
            log.info("事故通知记录保存成功,共 {} 条", notifications.size());
        }
        TaskVO taskVO = new TaskVO();
        BeanUtil.copyProperties(xpTask, taskVO);
        xpWebSocketMessageClient.pushTask(taskVO);
        Map<Integer, List<XpOperationsUser>> operationUserMap = data.stream()
                .filter(u -> u.getDeviceType() != null && StringUtils.isNotBlank(u.getPhoneNumber()))
                .collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
@@ -428,6 +436,7 @@
        }
    }
    WebSocketMessageClient xpWebSocketMessageClient;
    /**
     * 推送阿里云通知
     *
@@ -1398,7 +1407,7 @@
        task.setHandleUserId(handlerUser);
        if(handlerUser == null) {
            task.setStatus(4);
            noticeAdministrator(task);
            noticeAdministrator(task);//TODO 需要通知管理员手动处理,考虑再AliPushUtil 中给管理员发送消息
        }
        updateById(task);
        // 存储事故处理日志
@@ -1462,6 +1471,14 @@
        sendAccidentNotificationAsync(task, vehicle.getPlateNumber(), taskRule.getProcessingTimeLimit());
    }
    @Override
    @Transactional
    public void accept(TaskVO taskVO) {
        updateTaskStatus(taskVO.getId(), TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE, Long.valueOf(taskVO.getHandleUserId()));
        sendAccidentNotificationAsync(getById(taskVO.getId()), taskVO.getPlateNumber(), (int) Duration.between(LocalDateTime.now(),taskVO.getEndTime()).toMinutes());
    }
    @Value("${robotaxi.sms.app-id:1476153389173952512}")
    private String smsAppId;
    @Value("${robotaxi.sms.app-push-config-code:ROBOTAXI_VERIFY_CODE_SMS}")
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/controller/WebSocketController.java
@@ -1,6 +1,11 @@
package com.xiaopeng.pushMessage.webSocket.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.controller.BaseController;
import com.xiaopeng.pushMessage.webSocket.service.WebSocketUserService;
@@ -10,6 +15,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -27,6 +33,16 @@
    @Autowired
    private WebSocketUserService webSocketUserService;
    private ObjectMapper om;
    @PostConstruct
    void setupObjectMapper() {
        // 允许对象忽略json中不存在的属性
        om = new ObjectMapper();
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        om.registerModule(new JavaTimeModule());
    }
    // ==================== 基于XpAppUser的WebSocket接口 ====================
@@ -355,4 +371,18 @@
            return R.fail("获取在线用户列表失败: " + e.getMessage());
        }
    }
    /**
     * 运维工单app推送
     */
    @PostMapping("/inner/websocket/push/task")
    public R<?> pushTask(@RequestBody TaskVO vo) throws JsonProcessingException {
        String handleUserId = vo.getHandleUserId();
        String msg = om.writeValueAsString(vo);
        webSocketUserService.sendMessageToUser(handleUserId, msg);
        return R.ok();
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -1099,5 +1099,6 @@
    public R<String> generateBluetoothUnlockToken(){
        return null;
    }
}