“mitao”
2026-03-25 915599e28042d8b47774f7fe695a7019d81efbda
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -323,38 +323,58 @@
                }
                // 构建通知内容
                String content = String.format("车辆%s在%s发生了紧急事故,请在%d分钟内到达现场!", plateNumber, xpTask.getVehicleLocation(), processingTimeLimit);
                String bodyJson = buildAccidentPushBodyJson(content, xpTask);
                // 构建通知记录(包含 notificationExt)
                List<XpOperationsUserNotification> notifications = data.stream().map(item -> {
                    XpOperationsUserNotification notification = new XpOperationsUserNotification();
                    notification.setOperationsUserId(item.getId());
                    notification.setNotificationType(NotificationTypeEnum.ACCIDENT_NEW.getCode());
                    notification.setNotificationContent(content);
                    notification.setDataId(xpTask.getId());
                    notification.setReadStatus(0);
                    notification.setNotificationExt(bodyJson);
                    return notification;
                }).collect(Collectors.toList());
                // 批量保存通知记录
                xpOperationUserNotificationClient.addNotificationBatch(notifications);
                log.info("事故通知记录保存成功,共 {} 条", notifications.size());
                // 按设备类型分组发送阿里云推送
                Map<Integer, List<XpOperationsUser>> operationUserMap = data.stream()
                        .filter(u -> u.getDeviceType() != null && u.getPhoneNumber() != null)
                        .collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
                for (Map.Entry<Integer, List<XpOperationsUser>> entry : operationUserMap.entrySet()) {
                    pushAliMessage(entry.getValue(), content, xpTask);
                }
                String content = buildAccidentNotificationContent(xpTask, plateNumber, processingTimeLimit);
                saveAndPushAccidentNotification(data, content, xpTask);
            } catch (Exception e) {
                log.error("发送事故通知失败,任务ID={}", xpTask.getId(), e);
            }
        });
        executor.shutdown();
    }
    /**
     * 异步发送事故任务分配通知
     *
     * @param xpTask 任务信息
     * @param handlerUserId 当前分配的处理人
     * @param plateNumber 车牌号
     * @param processingTimeLimit 处理时限(分钟)
     */
    private void sendAssignedAccidentNotificationAsync(XpTask xpTask, Long handlerUserId, String plateNumber, Integer processingTimeLimit) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>()
        );
        executor.execute(() -> {
            try {
                R<List<XpOperationsUser>> xpOperationUserResult = xpOperationUserClient.listByIds(Collections.singletonList(handlerUserId));
                List<XpOperationsUser> data = xpOperationUserResult == null ? Collections.emptyList() : xpOperationUserResult.getData();
                if (CollUtil.isEmpty(data)) {
                    return;
                }
                String content = buildAccidentNotificationContent(xpTask, plateNumber, processingTimeLimit);
                saveAndPushAccidentNotification(data, content, xpTask);
            } catch (Exception e) {
                log.error("发送事故任务分配通知失败,任务ID={}, handlerUserId={}", xpTask.getId(), handlerUserId, e);
            }
        });
        executor.shutdown();
    }
    /**
     * 构建事故通知文案
     *
     * @param xpTask 任务信息
     * @param plateNumber 车牌号
     * @param processingTimeLimit 处理时限(分钟)
     * @return 通知内容
     */
    private String buildAccidentNotificationContent(XpTask xpTask, String plateNumber, Integer processingTimeLimit) {
        return String.format("车辆%s在%s发生了紧急事故,请在%d分钟内到达现场!", plateNumber, xpTask.getVehicleLocation(), processingTimeLimit);
    }
    /**
@@ -370,6 +390,40 @@
        param.put("type", TaskTypeNotificationEnum.ACCIDENT_TASK.getCode());
        param.put("id", xpTask.getId().toString());
        return JSONObject.toJSONString(param);
    }
    /**
     * 保存事故通知记录并发送阿里云推送
     *
     * @param data 接收通知的运维人员
     * @param content 通知内容
     * @param xpTask 任务信息
     */
    private void saveAndPushAccidentNotification(List<XpOperationsUser> data, String content, XpTask xpTask) {
        String bodyJson = buildAccidentPushBodyJson(content, xpTask);
        List<XpOperationsUserNotification> notifications = data.stream().map(item -> {
            XpOperationsUserNotification notification = new XpOperationsUserNotification();
            notification.setOperationsUserId(item.getId());
            notification.setNotificationType(NotificationTypeEnum.ACCIDENT_NEW.getCode());
            notification.setNotificationContent(content);
            notification.setDataId(xpTask.getId());
            notification.setReadStatus(0);
            notification.setNotificationExt(bodyJson);
            return notification;
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(notifications)) {
            xpOperationUserNotificationClient.addNotificationBatch(notifications);
            log.info("事故通知记录保存成功,共 {} 条", notifications.size());
        }
        Map<Integer, List<XpOperationsUser>> operationUserMap = data.stream()
                .filter(u -> u.getDeviceType() != null && StringUtils.isNotBlank(u.getPhoneNumber()))
                .collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
        for (Map.Entry<Integer, List<XpOperationsUser>> entry : operationUserMap.entrySet()) {
            pushAliMessage(entry.getValue(), content, xpTask);
        }
    }
    /**
@@ -1523,16 +1577,41 @@
    @Override
    public R assigneeTask(Long id, Long handlerUserId, Long assigneeUserId) {
        XpTask task = this.getById(id);
        // 查询规则 任务结束时间从任务分配时开始计算
        XpTaskRule taskRule = xpTaskRuleMapper.selectOne(null);
        if (taskRule != null) {
            task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
        if (task == null) {
            throw new ServiceException(
                    "任务不存在",
                    I18nKeyConstant.TASK_NOT_EXIST
            );
        }
        boolean isAccidentTask = Integer.valueOf(2).equals(task.getTaskCategory());
        Long vehicleId = task.getVehicleId();
        Integer processingTimeLimit = null;
        String plateNumber = "";
        if (isAccidentTask) {
            // 查询规则 任务结束时间从任务分配时开始计算
            XpTaskRule taskRule = xpTaskRuleMapper.selectOne(null);
            if (taskRule != null) {
                processingTimeLimit = taskRule.getProcessingTimeLimit();
                task.setEndTime(LocalDateTime.now().plusMinutes(taskRule.getProcessingTimeLimit()));
            }
            if (vehicleId != null) {
                XpVehicle vehicle = xpVehicleClient.queryById(vehicleId).getData();
                if (vehicle != null && StringUtils.isNotBlank(vehicle.getPlateNumber())) {
                    plateNumber = vehicle.getPlateNumber();
                }
            }
        } else {
            task.setEndTime(LocalDateTime.now().plusDays(3));
        }
        task.setAssigneeTime(LocalDateTime.now());
        task.setHandleUserId(handlerUserId.toString());
        task.setVehicleId(null);
        task.setAssigneeUserId(assigneeUserId);
        this.updateById(task);
        if (isAccidentTask && processingTimeLimit != null) {
            sendAssignedAccidentNotificationAsync(task, handlerUserId, plateNumber, processingTimeLimit);
        }
        return R.ok();
    }
@@ -1585,19 +1664,7 @@
                    I18nKeyConstant.VEHICLE_NOT_EXIST
            );
        }
        String vehiclePicture = vehicle.getVehiclePictures();
        if (vehicle.getVehiclePictures() != null) {
            JSONObject jsonObject = JSONObject.parseObject(vehicle.getVehiclePictures());
            // 1
            String downloadUrl = jsonObject.getString("url");
            try {
                downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
            } catch (UnsupportedEncodingException e) {
                log.error("获取图片下载地址失败", e);
            }
            jsonObject.put("url", downloadUrl);
            vehiclePicture = jsonObject.toJSONString();
        }
        String vehiclePicture = aliOssDownloadUtil.getPictureJSONObject(vehicle.getVehiclePictures());
        if (task.getTaskCategory() == 1) {
            // 常规任务
@@ -1613,19 +1680,7 @@
                    taskManagementDetectionDetailVO.setVehicleCode(vehicle.getVehicleCode());
                    taskManagementDetectionDetailVO.setVehicleVin(vehicle.getVehicleVin());
                    taskManagementDetectionDetailVO.setVehicleLocation(task.getVehicleLocation());
                    if (vehicle.getVehiclePictures() != null) {
                        JSONObject jsonObject = JSONObject.parseObject(vehicle.getVehiclePictures());
                        // 1
                        String downloadUrl = jsonObject.getString("url");
                        try {
                            downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
                        } catch (UnsupportedEncodingException e) {
                            log.error("获取图片下载地址失败", e);
                        }
                        jsonObject.put("url", downloadUrl);
                        taskManagementDetectionDetailVO.setVehiclePictures(jsonObject.toJSONString());
                    }
                    taskManagementDetectionDetailVO.setVehiclePictures(vehiclePicture);
                    taskManagementDetectionDetailVO.setTaskCode(task.getTaskCode());
                    XpVehicleDetection vehicleDetection = vehicleDetectionMapper.selectOne(new LambdaQueryWrapper<XpVehicleDetection>()