liujie
2026-03-18 15c0a773a587243e6fae4293d990c3c73f308792
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
package com.xiaopeng.maintenance.schedule;
 
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.pushMessage.AliPushMessageDTO;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.pushMessage.XpAliPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
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.TaskTypeNotificationEnum;
import com.xiaopeng.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
 
/**
 * 事故任务通知支撑类
 *
 * <p>用于事故任务相关定时通知的通用方法抽取。</p>
 *
 * @author mitao
 * @since 2026-03-14
 */
@Component
public class AccidentTaskNotificationSupport {
 
    private static final Logger log = LoggerFactory.getLogger(AccidentTaskNotificationSupport.class);
 
    @Autowired
    private XpOperationUserClient xpOperationUserClient;
 
    @Autowired
    private XpVehicleClient xpVehicleClient;
 
    @Autowired
    private XpAliPushMessageClient xpAliPushMessageClient;
 
    /**
     * 解析 handleUserId(逗号分隔)
     */
    public Set<Long> parseUserIds(String handleUserId) {
        if (StringUtils.isBlank(handleUserId)) {
            return Collections.emptySet();
        }
        String[] parts = handleUserId.split(",");
        Set<Long> userIds = new HashSet<>();
        for (String part : parts) {
            if (StringUtils.isBlank(part)) {
                continue;
            }
            try {
                userIds.add(Long.valueOf(part.trim()));
            } catch (NumberFormatException e) {
                log.warn("任务接收人ID非法,handleUserId={}", handleUserId);
            }
        }
        return userIds;
    }
 
    /**
     * 获取运维人员信息
     */
    public Map<Long, XpOperationsUser> fetchOperationUsers(Set<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyMap();
        }
        try {
            R<List<XpOperationsUser>> result = xpOperationUserClient.listByIds(new ArrayList<>(userIds));
            if (result == null || CollectionUtils.isEmpty(result.getData())) {
                return Collections.emptyMap();
            }
            return result.getData().stream()
                    .filter(Objects::nonNull)
                    .filter(u -> u.getId() != null)
                    .collect(Collectors.toMap(XpOperationsUser::getId, u -> u, (a, b) -> a));
        } catch (Exception e) {
            log.error("获取运维人员信息失败", e);
            return Collections.emptyMap();
        }
    }
 
    /**
     * 批量获取车辆信息
     */
    public Map<Long, XpVehicle> fetchVehicles(Set<Long> vehicleIds) {
        if (CollectionUtils.isEmpty(vehicleIds)) {
            return Collections.emptyMap();
        }
        try {
            R<List<XpVehicle>> result = xpVehicleClient.listByIds(new ArrayList<>(vehicleIds));
            if (result == null || CollectionUtils.isEmpty(result.getData())) {
                return Collections.emptyMap();
            }
            return result.getData().stream()
                    .filter(Objects::nonNull)
                    .filter(v -> v.getId() != null)
                    .collect(Collectors.toMap(XpVehicle::getId, v -> v, (a, b) -> a));
        } catch (Exception e) {
            log.error("获取车辆信息失败", e);
            return Collections.emptyMap();
        }
    }
 
    /**
     * 构建推送 body JSON
     */
    public String buildPushBodyJson(String content, Integer strategyCode, Long taskId) {
        Map<String, Object> param = new HashMap<>();
        param.put("content", content);
        param.put("strategy", strategyCode);
        param.put("type", TaskTypeNotificationEnum.ACCIDENT_TASK.getCode());
        param.put("id", taskId == null ? "0" : taskId.toString());
        return JSONObject.toJSONString(param);
    }
 
    /**
     * 批量构建通知记录(包含 notificationExt)
     */
    public List<XpOperationsUserNotification> buildNotifications(List<XpOperationsUser> users,
                                                                 Integer notificationType,
                                                                 String content,
                                                                 Long taskId,
                                                                 String bodyJson) {
        if (CollectionUtils.isEmpty(users)) {
            return Collections.emptyList();
        }
        List<XpOperationsUserNotification> notifications = new ArrayList<>();
        for (XpOperationsUser user : users) {
            if (user == null || user.getId() == null) {
                continue;
            }
            XpOperationsUserNotification notification = new XpOperationsUserNotification();
            notification.setNotificationType(notificationType);
            notification.setNotificationContent(content);
            notification.setOperationsUserId(user.getId());
            notification.setDataId(taskId == null ? 0L : taskId);
            notification.setReadStatus(0);
            notification.setNotificationExt(bodyJson);
            notifications.add(notification);
        }
        return notifications;
    }
 
    /**
     * 推送通知(按 deviceType 分组)
     */
    public int pushToUsersByDeviceType(List<XpOperationsUser> users, String title, String bodyJson) {
        if (CollectionUtils.isEmpty(users)) {
            return 0;
        }
        Map<Integer, List<XpOperationsUser>> operationUserMap = users.stream()
                .filter(u -> u != null && u.getDeviceType() != null && StringUtils.isNotBlank(u.getPhoneNumber()))
                .collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
 
        int pushCount = 0;
        for (Map.Entry<Integer, List<XpOperationsUser>> entry : operationUserMap.entrySet()) {
            List<XpOperationsUser> groupUsers = entry.getValue();
            if (CollectionUtils.isEmpty(groupUsers)) {
                continue;
            }
            String account = groupUsers.stream()
                    .map(XpOperationsUser::getPhoneNumber)
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining(","));
            if (StringUtils.isBlank(account)) {
                continue;
            }
            try {
                xpAliPushMessageClient.pushMessage(AliPushMessageDTO.builder()
                        .body(bodyJson)
                        .account(account)
                        .title(title)
                        .pushType(AliPushTypeConstant.NOTICE)
                        .deviceType(entry.getKey())
                        .build());
                pushCount++;
            } catch (Exception e) {
                log.error("事故任务推送失败,deviceType={}", entry.getKey(), e);
            }
        }
        return pushCount;
    }
}