package com.ruoyi.project.system.service.impl;
|
|
import com.getui.push.v2.sdk.ApiHelper;
|
import com.getui.push.v2.sdk.GtApiConfiguration;
|
import com.getui.push.v2.sdk.api.PushApi;
|
import com.getui.push.v2.sdk.common.ApiResult;
|
import com.getui.push.v2.sdk.dto.req.Audience;
|
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
|
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
|
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
|
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
|
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
|
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.project.system.domain.GetuiConfig;
|
import com.ruoyi.project.system.domain.SysMenu;
|
import com.ruoyi.project.system.domain.SysNotice;
|
import com.ruoyi.project.system.domain.SysUserClient;
|
import com.ruoyi.project.system.mapper.SysMenuMapper;
|
import com.ruoyi.project.system.service.SysUserClientService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.jetbrains.annotations.NotNull;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.PostConstruct;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* APP消息推送服务
|
*
|
* @author deslrey
|
* @version 1.4
|
* @since 2026/2/9
|
*/
|
@Slf4j
|
@Component
|
public class UnipushService {
|
|
@Autowired
|
private SysMenuMapper sysMenuMapper;
|
|
@Autowired
|
private GetuiConfig getuiConfig;
|
|
@Autowired
|
private SysUserClientService userClientService;
|
|
private PushApi pushApi;
|
|
private static final String DEFAULT_APP_PAGE = "pages/index";
|
|
@PostConstruct
|
public void init() {
|
GtApiConfiguration config = new GtApiConfiguration();
|
config.setAppId(getuiConfig.getAppId());
|
config.setAppKey(getuiConfig.getAppKey());
|
config.setMasterSecret(getuiConfig.getMasterSecret());
|
config.setDomain(getuiConfig.getDomain());
|
ApiHelper apiHelper = ApiHelper.build(config);
|
this.pushApi = apiHelper.creatApi(PushApi.class);
|
}
|
|
/**
|
* 批量发送通知公告到移动端
|
*/
|
@Async
|
public void sendClientMessage(List<SysNotice> sysNoticeList) {
|
if (sysNoticeList == null || sysNoticeList.isEmpty()) {
|
return;
|
}
|
|
for (SysNotice sysNotice : sysNoticeList) {
|
SysUserClient client = userClientService.getById(sysNotice.getConsigneeId());
|
if (client == null || StringUtils.isEmpty(client.getCid())) {
|
log.warn("用户 {} 未绑定移动端 CID,跳过推送", sysNotice.getConsigneeId());
|
continue;
|
}
|
|
// 转换路径
|
String appPath = convertWebPathToAppPath(sysNotice.getJumpPath());
|
|
// 推送
|
sendRoutingPush(
|
client.getCid(),
|
sysNotice.getNoticeTitle(),
|
sysNotice.getRemark() != null ? sysNotice.getRemark() : sysNotice.getNoticeContent(),
|
appPath
|
);
|
}
|
}
|
|
/**
|
* 将 Web 端分层全路径转换为 App 端组件路由
|
*/
|
private String convertWebPathToAppPath(String webPath) {
|
if (StringUtils.isEmpty(webPath)) {
|
return DEFAULT_APP_PAGE;
|
}
|
|
String pathOnly = webPath;
|
String queryString = "";
|
if (webPath.contains("?")) {
|
int index = webPath.indexOf("?");
|
pathOnly = webPath.substring(0, index);
|
queryString = webPath.substring(index);
|
}
|
|
String[] pathSegments = pathOnly.split("/");
|
String lastSegment = "";
|
for (int i = pathSegments.length - 1; i >= 0; i--) {
|
if (StringUtils.isNotEmpty(pathSegments[i])) {
|
lastSegment = pathSegments[i];
|
break;
|
}
|
}
|
|
if (StringUtils.isEmpty(lastSegment)) {
|
return DEFAULT_APP_PAGE;
|
}
|
|
SysMenu menu = sysMenuMapper.selectMenuByPath(lastSegment);
|
|
if (menu != null && StringUtils.isNotEmpty(menu.getAppComponent())) {
|
String appComponent = menu.getAppComponent();
|
if (appComponent.startsWith("/")) {
|
appComponent = appComponent.substring(1);
|
}
|
return appComponent + queryString;
|
}
|
|
return DEFAULT_APP_PAGE;
|
}
|
|
/**
|
* 发送单人路由推送
|
*/
|
private void sendRoutingPush(String cid, String title, String content, String targetPath) {
|
log.info("准备推送消息: CID={}, Title={}, TargetPath={}", cid, title, targetPath);
|
|
PushDTO<Audience> pushDTO = new PushDTO<>();
|
pushDTO.setRequestId("REQ_" + System.currentTimeMillis());
|
|
// 在线透传内容
|
PushMessage pushMessage = new PushMessage();
|
String transmissionContent = String.format(
|
"{\"title\":\"%s\",\"content\":\"%s\",\"payload\":\"%s\"}",
|
title, content, targetPath
|
);
|
pushMessage.setTransmission(transmissionContent);
|
pushDTO.setPushMessage(pushMessage);
|
|
// 接收人
|
Audience audience = new Audience();
|
audience.addCid(cid);
|
pushDTO.setAudience(audience);
|
|
// 离线推送通道
|
pushDTO.setPushChannel(getPushChannel(title, content, targetPath));
|
|
try {
|
ApiResult<Map<String, Map<String, String>>> result = pushApi.pushToSingleByCid(pushDTO);
|
if (result.isSuccess()) {
|
log.info("Unipush 推送成功: CID={}", cid);
|
} else {
|
log.error("Unipush 推送失败: CID={}, Code={}, Msg={}", cid, result.getCode(), result.getMsg());
|
}
|
} catch (Exception e) {
|
log.error("Unipush 推送异常: ", e);
|
}
|
}
|
|
@NotNull
|
private PushChannel getPushChannel(String title, String content, String targetPath) {
|
PushChannel pushChannel = new PushChannel();
|
AndroidDTO androidDTO = new AndroidDTO();
|
Ups ups = new Ups();
|
ThirdNotification thirdNotification = new ThirdNotification();
|
thirdNotification.setTitle(title);
|
thirdNotification.setBody(content);
|
thirdNotification.setClickType("intent");
|
|
String intent = "intent:#Intent;launchFlags=0x04000000;"
|
+ "component=" + getuiConfig.getIntentComponent() + ";"
|
+ "S.UP-OL-P9=true;"
|
+ "S.path=" + targetPath + ";"
|
+ "S.payload=" + targetPath + ";"
|
+ "end";
|
thirdNotification.setIntent(intent);
|
|
ups.setNotification(thirdNotification);
|
androidDTO.setUps(ups);
|
pushChannel.setAndroid(androidDTO);
|
return pushChannel;
|
}
|
}
|