From 7a394e5bf750464ef5cdfe4034847fe354fcfe20 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期一, 02 三月 2026 19:09:50 +0800
Subject: [PATCH] feat:常规任务通知定时任务
---
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 176 insertions(+), 0 deletions(-)
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java
index c0d8704..50321c5 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java
@@ -1,9 +1,18 @@
package com.xiaopeng.operation.service.impl;
import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONObject;
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.XpOperationUserClient;
+import com.xiaopeng.api.feignClient.account.XpOperationUserNotificationClient;
+import com.xiaopeng.api.feignClient.pushMessage.XpAliPushMessageClient;
+import com.xiaopeng.api.model.account.XpOperationsUser;
+import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.api.model.operation.XpAppVersion;
+import com.xiaopeng.common.core.domain.R;
+import com.xiaopeng.common.core.enums.NotificationTypeEnum;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.web.page.BasePage;
import com.xiaopeng.common.core.web.page.PageInfo;
@@ -11,10 +20,20 @@
import com.xiaopeng.operation.mapper.XpAppVersionMapper;
import com.xiaopeng.operation.service.IXpAppVersionService;
import com.xiaopeng.operation.vo.XpAppVersionVO;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* App版本管理 服务实现类
@@ -24,7 +43,14 @@
*/
@Slf4j
@Service
+@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class XpAppVersionServiceImpl extends ServiceImpl<XpAppVersionMapper, XpAppVersion> implements IXpAppVersionService {
+
+ private final XpOperationUserClient xpOperationUserClient;
+
+ private final XpOperationUserNotificationClient xpOperationUserNotificationClient;
+
+ private final XpAliPushMessageClient xpAliPushMessageClient;
@Override
public XpAppVersionVO getLatestVersion() {
@@ -68,5 +94,155 @@
appVersion.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
appVersion.setVersionCode(latestVersionCode + 1); // 版本号自增
save(appVersion);
+
+ // 异步发送版本更新通知
+ sendVersionUpdateNotification(appVersion);
+ }
+
+ /**
+ * 发送版本更新通知
+ * @param appVersion 版本信息
+ */
+ private void sendVersionUpdateNotification(XpAppVersion appVersion) {
+ // 异步处理,避免阻塞主流程
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
+ 1, 1, 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>()
+ );
+
+ executor.execute(() -> {
+ try {
+ // 1. 获取所有启用状态的运维用户
+ R<List<XpOperationsUser>> result = xpOperationUserClient.listAllEnabled();
+ if (result == null || result.getCode() != 200 || result.getData() == null || result.getData().isEmpty()) {
+ log.warn("没有需要通知的启用状态用户");
+ return;
+ }
+
+ List<XpOperationsUser> enabledUsers = result.getData();
+ log.info("版本更新通知,共需通知 {} 位用户", enabledUsers.size());
+
+ // 2. 构建通知内容
+ String message = "新版本上线啦!请前往更新。";
+ String bodyJson = buildPushBodyJson(message);
+
+ // 3. 构建并保存通知记录
+ List<XpOperationsUserNotification> notifications = enabledUsers.stream()
+ .map(user -> buildNotification(message, bodyJson, user))
+ .collect(Collectors.toList());
+
+ // 批量保存通知记录
+ xpOperationUserNotificationClient.addNotificationBatch(notifications);
+ log.info("版本更新通知记录保存成功,共 {} 条", notifications.size());
+
+ // 4. 按设备类型分组并批量推送
+ pushMessageByDeviceType(enabledUsers, message);
+
+ } catch (Exception e) {
+ log.error("发送版本更新通知失败", e);
+ }
+ });
+
+ executor.shutdown();
+ }
+
+ /**
+ * 构建推送 body JSON
+ * @param message 消息内容
+ * @return JSON 字符串
+ */
+ private String buildPushBodyJson(String message) {
+ JSONObject body = new JSONObject();
+ body.put("content", message);
+ body.put("strategy", NotificationTypeEnum.VERSION_UPDATE_TIP.getCode()); // 8
+ body.put("type", 0);
+ body.put("id", 0);
+ return body.toJSONString();
+ }
+
+ /**
+ * 构建通知实体
+ * @param message 消息内容
+ * @param bodyJson 推送body内容
+ * @param user 运维用户
+ * @return 通知实体
+ */
+ private XpOperationsUserNotification buildNotification(String message, String bodyJson, XpOperationsUser user) {
+ XpOperationsUserNotification notification = new XpOperationsUserNotification();
+ notification.setNotificationType(NotificationTypeEnum.VERSION_UPDATE_TIP.getCode()); // 8
+ notification.setNotificationContent(message);
+ notification.setOperationsUserId(user.getId());
+ notification.setDataId(0L); // 版本更新通知 dataId 设置为 0
+ notification.setReadStatus(0); // 未读
+ notification.setNotificationExt(bodyJson);
+ return notification;
+ }
+
+ /**
+ * 按设备类型分组推送消息
+ * @param users 用户列表
+ * @param message 消息内容
+ */
+ private void pushMessageByDeviceType(List<XpOperationsUser> users, String message) {
+ // 按设备类型分组 (1=Android, 2=iOS)
+ Map<Integer, List<XpOperationsUser>> usersByDeviceType = users.stream()
+ .filter(u -> u.getDeviceType() != null && u.getPhoneNumber() != null)
+ .collect(Collectors.groupingBy(XpOperationsUser::getDeviceType));
+
+ // 分别推送 Android 和 iOS
+ for (Map.Entry<Integer, List<XpOperationsUser>> entry : usersByDeviceType.entrySet()) {
+ Integer deviceType = entry.getKey();
+ List<XpOperationsUser> deviceUsers = entry.getValue();
+
+ // 按 1000 个手机号一批进行推送
+ List<List<XpOperationsUser>> batches = partition(deviceUsers, 1000);
+
+ for (List<XpOperationsUser> batch : batches) {
+ String accounts = batch.stream()
+ .map(XpOperationsUser::getPhoneNumber)
+ .collect(Collectors.joining(","));
+
+ AliPushMessageDTO pushDTO = buildPushMessageDTO(deviceType, accounts, message);
+
+ try {
+ xpAliPushMessageClient.pushMessage(pushDTO);
+ log.info("版本更新推送成功,设备类型={},用户数={}",
+ deviceType == 1 ? "Android" : "iOS", batch.size());
+ } catch (Exception e) {
+ log.error("版本更新推送失败,设备类型={}", deviceType, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * 构建推送消息 DTO
+ * @param deviceType 设备类型
+ * @param accounts 手机号(逗号分隔)
+ * @param message 消息内容
+ * @return 推送 DTO
+ */
+ private AliPushMessageDTO buildPushMessageDTO(Integer deviceType, String accounts, String message) {
+ AliPushMessageDTO dto = new AliPushMessageDTO();
+ dto.setDeviceType(deviceType);
+ dto.setAccount(accounts);
+ dto.setTitle("APP版本更新提示");
+ dto.setBody(buildPushBodyJson(message));
+ dto.setPushType("NOTICE");
+ return dto;
+ }
+
+ /**
+ * 将列表按指定大小分批
+ * @param list 原始列表
+ * @param batchSize 批次大小
+ * @return 分批后的列表
+ */
+ private <T> List<List<T>> partition(List<T> list, int batchSize) {
+ List<List<T>> batches = new ArrayList<>();
+ for (int i = 0; i < list.size(); i += batchSize) {
+ batches.add(list.subList(i, Math.min(i + batchSize, list.size())));
+ }
+ return batches;
}
}
--
Gitblit v1.7.1