From 446d588f6983d2f9e7bb18546a961fa4c14c99a0 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期二, 19 五月 2026 03:58:31 +0800
Subject: [PATCH] 合并代码

---
 xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java b/xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
index 4638b96..78c759c 100644
--- a/xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
+++ b/xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -45,6 +45,7 @@
 import com.xiaopeng.evi.oss.service.AliOssService;
 import com.xiaopeng.maintenance.constant.I18nKeyConstant;
 import com.xiaopeng.maintenance.dto.HandleVehicleAccidentDto;
+import com.xiaopeng.maintenance.dto.SaveRemoteDrivingAccidentDto;
 import com.xiaopeng.maintenance.dto.SaveErrorTaskDto;
 import com.xiaopeng.maintenance.dto.SaveRoutineDetailDto;
 import com.xiaopeng.maintenance.dto.SaveVehicleAccidentDto;
@@ -365,6 +366,74 @@
         // 异步发送消息通知
         String plateNumber = Objects.nonNull(vehicle) ? vehicle.getPlateNumber() : "";
         sendAccidentNotificationAsync(xpTask, plateNumber, taskRule.getProcessingTimeLimit());
+        return xpTask;
+    }
+
+    @Override
+    @Transactional
+    @ShardingSphereTransactionType(TransactionType.BASE)
+    public XpTask saveRemoteDrivingAccident(SaveRemoteDrivingAccidentDto dto) {
+        validateRemoteDrivingAccidentDto(dto);
+
+        XpVehicle vehicle = xpVehicleClient.findByVehicleVin(dto.getVin().trim()).getData();
+        if (Objects.isNull(vehicle)) {
+            throw new ServiceException("上报失败,未获取到车辆信息", I18nKeyConstant.TASK_VEHICLE_NOT_EXIST);
+        }
+
+        LocalDateTime reportTime = parseRemoteDrivingTaskTime(dto.getTaskTime());
+        Integer taskSource = parseTaskSource(dto.getSource());
+        XpTask xpTask = new XpTask();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);
+        xpTask.setTaskCode(code);
+        xpTask.setTaskCategory(2);
+        xpTask.setTaskTypeId(normalizeAccidentTaskTypeId(dto.getTaskTypeId()));
+        xpTask.setTaskUrgencyLevel(mapRemoteDrivingUrgencyLevel(dto.getTaskUrgencyLevel()));
+        xpTask.setTaskDescription(dto.getTaskDescription().trim());
+        xpTask.setTaskImage(normalizeTaskImage(dto.getTaskImage()));
+        xpTask.setVehicleId(vehicle.getId());
+        xpTask.setVehicleLocation(dto.getVehicleLocation().trim());
+        xpTask.setVehicleLon(dto.getVehicleLon());
+        xpTask.setVehicleLat(dto.getVehicleLat());
+        xpTask.setReportUserId(0L);
+        xpTask.setReportTime(reportTime);
+        xpTask.setStatus(0);
+        xpTask.setTaskSource(taskSource);
+        xpTask.setCreateBy(dto.getSource().trim());
+
+        XpTaskRule taskRule = xpTaskRuleService.lambdaQuery().last("limit 1").one();
+        List<XpTaskRuleRole> list = xpTaskRuleRoleService.lambdaQuery().eq(XpTaskRuleRole::getRuleType, 9).list();
+        if (CollUtil.isEmpty(list) || Objects.isNull(taskRule)) {
+            throw new ServiceException("未配置车辆事故任务分配规则");
+        }
+        List<Long> roleIds = list.stream().map(XpTaskRuleRole::getRoleId).collect(Collectors.toList());
+        R<List<XpOperationsRole>> xpOperationsRoleResult = xpOperationUserClient.getXpOperationsRoleByRoleIds(roleIds);
+        if (CollUtil.isNotEmpty(xpOperationsRoleResult.getData())) {
+            Long fleetId = xpFleetVehicleClient.getFleetIdByVehicleId(vehicle.getId()).getData();
+            List<Long> ids = xpFleetOperationsClient.getOperationsIdsByFleetId(fleetId).getData();
+            // 根据配置的事故处理角色和事故车辆所属车队人员,确定最终的任务分配人列表(取交集)
+            List<Long> userIds = xpOperationsRoleResult.getData().stream()
+                    .map(XpOperationsRole::getOperationsUserId)
+                    .filter(ids::contains)
+                    .distinct()
+                    .collect(Collectors.toList());
+            xpTask.setHandleUserId(StringUtils.join(userIds, ","));
+        }
+        // 根据事故处理限时配置设置任务截止时间
+        xpTask.setEndTime(reportTime.plusMinutes(taskRule.getProcessingTimeLimit()));
+        xpTask.setExpiredNoticeSent(0);
+        xpTask.setWillTimeoutNoticeSent(0);
+        this.save(xpTask);
+        if (xpTask.getId() == null && StringUtils.isNotBlank(xpTask.getTaskCode())) {
+            XpTask savedTask = this.getOne(new LambdaQueryWrapper<XpTask>()
+                    .eq(XpTask::getTaskCode, xpTask.getTaskCode())
+                    .last("limit 1"));
+            if (savedTask != null && savedTask.getId() != null) {
+                xpTask.setId(savedTask.getId());
+            }
+        }
+
+        sendAccidentNotificationAsync(xpTask, vehicle.getPlateNumber(), taskRule.getProcessingTimeLimit());
         return xpTask;
     }
 
@@ -1427,6 +1496,92 @@
         return normalizedTypeIds.stream().map(String::valueOf).collect(Collectors.joining(","));
     }
 
+    private void validateRemoteDrivingAccidentDto(SaveRemoteDrivingAccidentDto dto) {
+        if (dto == null) {
+            throw new ServiceException("请求参数不能为空");
+        }
+        if (StringUtils.isBlank(dto.getVin())) {
+            throw new ServiceException("vin不能为空");
+        }
+        if (StringUtils.isBlank(dto.getTaskTypeId())) {
+            throw new ServiceException("事故类型不能为空");
+        }
+        if (StringUtils.isBlank(dto.getTaskUrgencyLevel())) {
+            throw new ServiceException("事故紧急程度不能为空");
+        }
+        if (StringUtils.isBlank(dto.getTaskDescription())) {
+            throw new ServiceException("事故描述不能为空");
+        }
+        if (dto.getTaskDescription().trim().length() > 600) {
+            throw new ServiceException("事故描述最多600字");
+        }
+        if (StringUtils.isBlank(dto.getTaskTime())) {
+            throw new ServiceException("工单上报时间不能为空");
+        }
+        if (StringUtils.isBlank(dto.getVehicleLocation())) {
+            throw new ServiceException("车辆位置不能为空");
+        }
+        if (dto.getVehicleLon() == null) {
+            throw new ServiceException("车辆经度不能为空");
+        }
+        if (dto.getVehicleLat() == null) {
+            throw new ServiceException("车辆纬度不能为空");
+        }
+        if (StringUtils.isBlank(dto.getSource())) {
+            throw new ServiceException("工单来源不能为空");
+        }
+    }
+
+    private Integer mapRemoteDrivingUrgencyLevel(String taskUrgencyLevel) {
+        String normalized = StringUtils.trimToEmpty(taskUrgencyLevel);
+        if (!StringUtils.isNumeric(normalized)) {
+            throw new ServiceException("事故紧急程度不支持: " + taskUrgencyLevel);
+        }
+        Integer urgencyLevel = Integer.valueOf(normalized);
+        if (urgencyLevel < 0 || urgencyLevel > 3) {
+            throw new ServiceException("事故紧急程度不支持: " + taskUrgencyLevel);
+        }
+        return urgencyLevel;
+    }
+
+    private Integer parseTaskSource(String source) {
+        String normalized = StringUtils.trimToEmpty(source);
+        if (!StringUtils.isNumeric(normalized)) {
+            throw new ServiceException("工单来源不支持: " + source);
+        }
+        Integer taskSource = Integer.valueOf(normalized);
+        if (taskSource < 1 || taskSource > 3) {
+            throw new ServiceException("工单来源不支持: " + source);
+        }
+        return taskSource;
+    }
+
+    private LocalDateTime parseRemoteDrivingTaskTime(String taskTime) {
+        String normalized = StringUtils.trimToEmpty(taskTime);
+        List<DateTimeFormatter> formatters = Arrays.asList(
+                DateTimeFormatter.ISO_LOCAL_DATE_TIME,
+                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+        );
+        for (DateTimeFormatter formatter : formatters) {
+            try {
+                return LocalDateTime.parse(normalized, formatter);
+            } catch (Exception ignored) {
+            }
+        }
+        throw new ServiceException("工单上报时间格式不正确: " + taskTime);
+    }
+
+    private String normalizeTaskImage(String taskImage) {
+        if (StringUtils.isBlank(taskImage)) {
+            return "[]";
+        }
+        String trimmed = taskImage.trim();
+        if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
+            return trimmed;
+        }
+        return "[]";
+    }
+
     private List<Long> parseAccidentTaskTypeIds(String taskTypeId) {
         if (StringUtils.isBlank(taskTypeId)) {
             return Collections.emptyList();

--
Gitblit v1.7.1