From 7901224f014a52dbd693c723eee7b20fac1e1def Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 7 Jul 2024 19:28:47 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5unipush?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-platform/pom.xml | 5 + .../bx/implatform/config/UniPushConfig.java | 44 +++++++ .../com/bx/implatform/contant/RedisKey.java | 6 + .../controller/LoginController.java | 13 +- .../java/com/bx/implatform/dto/LoginDTO.java | 3 + .../java/com/bx/implatform/dto/LogoutDTO.java | 19 +++ .../java/com/bx/implatform/entity/User.java | 5 + .../listener/PrivateMessageListener.java | 39 +++++- .../service/INotifyPrivateService.java | 98 ++++++++++++++ .../bx/implatform/service/IUserService.java | 9 ++ .../service/impl/GroupServiceImpl.java | 6 +- .../impl/PrivateMessageServiceImpl.java | 6 +- .../service/impl/UserServiceImpl.java | 24 ++++ .../service/thirdparty/UniPushService.java | 122 ++++++++++++++++++ .../bx/implatform/session/NotifySession.java | 43 ++++++ .../src/main/resources/application.yml | 10 ++ im-platform/src/main/resources/db/db.sql | 1 + im-uniapp/App.vue | 17 +++ im-uniapp/manifest.json | 14 +- im-uniapp/pages/login/login.vue | 8 +- 20 files changed, 477 insertions(+), 15 deletions(-) create mode 100644 im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java create mode 100644 im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java create mode 100644 im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java create mode 100644 im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java create mode 100644 im-platform/src/main/java/com/bx/implatform/session/NotifySession.java diff --git a/im-platform/pom.xml b/im-platform/pom.xml index 16e987c..9e7502a 100644 --- a/im-platform/pom.xml +++ b/im-platform/pom.xml @@ -115,6 +115,11 @@ redisson 3.17.3 + + com.getui.push + restful-sdk + 1.0.3.0 + diff --git a/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java b/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java new file mode 100644 index 0000000..641c3f6 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java @@ -0,0 +1,44 @@ +package com.bx.implatform.config; + +import com.getui.push.v2.sdk.ApiHelper; +import com.getui.push.v2.sdk.GtApiConfiguration; +import com.getui.push.v2.sdk.api.PushApi; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +/** + * @author: 谢绍许 + * @date: 2024-07-06 + * @version: 1.0 + */ +@Data +@Component +public class UniPushConfig { + + @Value("${notify.uniPush.appId}") + private String appId; + @Value("${notify.uniPush.appKey}") + private String appKey; + @Value("${notify.uniPush.masterSecret}") + private String masterSecret; + + @Bean + public GtApiConfiguration uniPushConfiguration(){ + GtApiConfiguration apiConfiguration = new GtApiConfiguration(); + apiConfiguration.setAppId(appId); + apiConfiguration.setAppKey(appKey); + apiConfiguration.setMasterSecret(masterSecret); + return apiConfiguration; + } + + @Bean + public PushApi uniPushApi(GtApiConfiguration configuration){ + // 实例化ApiHelper对象,用于创建接口对象 + ApiHelper apiHelper = ApiHelper.build(configuration); + // 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi + PushApi pushApi = apiHelper.creatApi(PushApi.class); + return pushApi; + } +} diff --git a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java index 026e3c9..b2dd88b 100644 --- a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java +++ b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java @@ -10,6 +10,11 @@ public final class RedisKey { * 已读群聊消息位置(已读最大id) */ public static final String IM_GROUP_READED_POSITION = "im:readed:group:position"; + + /** + * 私聊离线通知 + */ + public static final String IM_OFFLINE_NOTIFY_PRIVATE = "im:notify:private"; /** * webrtc 单人通话 */ @@ -45,4 +50,5 @@ public final class RedisKey { */ public static final String IM_LOCK_RTC_GROUP = IM_LOCK + "rtc:group"; + } diff --git a/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java b/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java index 4a5e2d4..dbf07c2 100644 --- a/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java +++ b/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java @@ -1,6 +1,7 @@ package com.bx.implatform.controller; import com.bx.implatform.dto.LoginDTO; +import com.bx.implatform.dto.LogoutDTO; import com.bx.implatform.dto.ModifyPwdDTO; import com.bx.implatform.dto.RegisterDTO; import com.bx.implatform.result.Result; @@ -21,13 +22,21 @@ public class LoginController { private final IUserService userService; + @PostMapping("/login") - @ApiOperation(value = "用户注册", notes = "用户注册") - public Result register(@Valid @RequestBody LoginDTO dto) { + @ApiOperation(value = "用户登陆", notes = "用户注册") + public Result login(@Valid @RequestBody LoginDTO dto) { LoginVO vo = userService.login(dto); return ResultUtils.success(vo); } + @PostMapping("/logout") + @ApiOperation(value = "用户退出登陆", notes = "用户退出登陆") + public Result logout(@Valid @RequestBody LogoutDTO dto) { + userService.logout(dto); + return ResultUtils.success(); + } + @PutMapping("/refreshToken") @ApiOperation(value = "刷新token", notes = "用refreshtoken换取新的token") diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java index 0cdede2..cea3110 100644 --- a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java +++ b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java @@ -27,4 +27,7 @@ public class LoginDTO { @ApiModelProperty(value = "用户密码") private String password; + @ApiModelProperty(value = "用户客户端id") + private String cid; + } diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java new file mode 100644 index 0000000..4b252af --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java @@ -0,0 +1,19 @@ +package com.bx.implatform.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Data +@ApiModel("用户登录DTO") +public class LogoutDTO { + + @ApiModelProperty(value = "用户客户端id") + private String cid; + +} diff --git a/im-platform/src/main/java/com/bx/implatform/entity/User.java b/im-platform/src/main/java/com/bx/implatform/entity/User.java index 639b43b..67937fc 100644 --- a/im-platform/src/main/java/com/bx/implatform/entity/User.java +++ b/im-platform/src/main/java/com/bx/implatform/entity/User.java @@ -79,6 +79,11 @@ public class User extends Model { @TableField("password") private String password; + /** + * 客户端id,用于uni-push推送 + */ + @TableField("cid") + private String cid; /** * 最后登录时间 */ diff --git a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java index 194f469..5843302 100644 --- a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java +++ b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java @@ -6,10 +6,12 @@ import com.bx.imclient.annotation.IMListener; import com.bx.imclient.listener.MessageListener; import com.bx.imcommon.enums.IMListenerType; import com.bx.imcommon.enums.IMSendCode; +import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.model.IMSendResult; import com.bx.implatform.entity.PrivateMessage; import com.bx.implatform.enums.MessageStatus; import com.bx.implatform.service.IPrivateMessageService; +import com.bx.implatform.service.INotifyPrivateService; import com.bx.implatform.vo.PrivateMessageVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -25,24 +27,49 @@ public class PrivateMessageListener implements MessageListener @Lazy @Autowired private IPrivateMessageService privateMessageService; + + @Lazy + @Autowired + private INotifyPrivateService uniPushService; + @Override public void process(List> results) { + // 更新消息状态 + updateMessageStatus(results); + // 推送离线通知 + sendOfflineNotify(results); + } + + private void updateMessageStatus(List> results) { Set messageIds = new HashSet<>(); - for(IMSendResult result : results){ + for (IMSendResult result : results) { PrivateMessageVO messageInfo = result.getData(); // 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态 if (result.getCode().equals(IMSendCode.SUCCESS.code())) { messageIds.add(messageInfo.getId()); - log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal()); + log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), + result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal()); } } - // 批量修改状态 - if(CollUtil.isNotEmpty(messageIds)){ + // 对发送成功的消息修改状态 + if (CollUtil.isNotEmpty(messageIds)) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.lambda().in(PrivateMessage::getId, messageIds) - .eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code()) - .set(PrivateMessage::getStatus, MessageStatus.SENDED.code()); + .eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code()) + .set(PrivateMessage::getStatus, MessageStatus.SENDED.code()); privateMessageService.update(updateWrapper); } } + + private void sendOfflineNotify(List> results) { + for (IMSendResult result : results) { + PrivateMessageVO messageInfo = result.getData(); + if (result.getCode().equals(IMSendCode.SUCCESS.code()) && result.getReceiver().getTerminal() + .equals(IMTerminalType.APP.code())) { + uniPushService.sendMessage(messageInfo.getSendId(), messageInfo.getRecvId(), messageInfo.getContent()); + log.info("推送离线通知,消息id:{},发送者:{},接收者:{}", messageInfo.getId(), result.getSender().getId(), + result.getReceiver().getId()); + } + } + } } diff --git a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java new file mode 100644 index 0000000..6fa2f5a --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java @@ -0,0 +1,98 @@ +package com.bx.implatform.service; + +import cn.hutool.core.util.StrUtil; +import com.bx.implatform.contant.RedisKey; +import com.bx.implatform.entity.User; +import com.bx.implatform.session.NotifySession; +import com.bx.implatform.service.thirdparty.UniPushService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * 私聊离线通知服务 + * + * @author: blue + * @date: 2024-07-06 + * @version: 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class INotifyPrivateService { + private final UniPushService uniPushService; + private final IUserService userService; + private final RedisTemplate redisTemplate; + @Value("${notify.enable}") + private Boolean enable = false; + @Value("${notify.max.private}") + private Integer max = -1; + public void sendMessage(Long sendId, Long recvId, String content) { + if(!enable){ + return; + } + NotifySession session = findNotifySession(sendId, recvId); + if (Objects.isNull(session)) { + session = createNotifySession(sendId, recvId); + } + // 未上报cid,无法推送 + if (StrUtil.isEmpty(session.getCid())) { + log.info("用户'{}'未上报cid,无法推送离线通知", recvId); + return; + } + // 已达到最大数量 + if (max > 0 && session.getCount() >= max) { + log.info("用户'{}'已到达推送数量上线,不再推送离线通知", recvId); + return; + } + // 消息数量加1 + session.setCount(session.getCount()+1); + String body = String.format("%s:%s", session.getSendNickName(),content); + // 大于1条时需要展示数量 + if (session.getCount() > 1) { + body = String.format("[%d条] ", session.getCount()) + body; + } + uniPushService.pushByCid(session,body); + // 保存会话 + saveNotifySession(session,sendId,recvId); + } + + public void removeNotifySession(Long sendId, Long recvId){ + String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, "*", recvId); + Set keys = redisTemplate.keys(key); + redisTemplate.delete(keys); + } + + private NotifySession createNotifySession(Long sendId, Long recvId) { + String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); + User sendUser = userService.getById(sendId); + User recvUser = userService.getById(recvId); + NotifySession session = new NotifySession(); + session.setCount(0); + session.setCid(recvUser.getCid()); + session.setTitle(sendUser.getNickName()); + session.setSendNickName(sendUser.getNickName()); + session.setNotifyId(Math.abs(key.hashCode())); + session.setLogo(sendUser.getHeadImageThumb()); + redisTemplate.opsForValue().set(key, session, 30, TimeUnit.DAYS); + return session; + } + + private NotifySession findNotifySession(Long sendId, Long recvId) { + String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); + return (NotifySession)redisTemplate.opsForValue().get(key); + } + + private void saveNotifySession(NotifySession session, Long sendId, Long recvId) { + String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); + redisTemplate.opsForValue().set(key, session); + } + +} diff --git a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java index a24e0c3..1d1c823 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java +++ b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java @@ -2,6 +2,7 @@ package com.bx.implatform.service; import com.baomidou.mybatisplus.extension.service.IService; import com.bx.implatform.dto.LoginDTO; +import com.bx.implatform.dto.LogoutDTO; import com.bx.implatform.dto.ModifyPwdDTO; import com.bx.implatform.dto.RegisterDTO; import com.bx.implatform.entity.User; @@ -21,6 +22,14 @@ public interface IUserService extends IService { */ LoginVO login(LoginDTO dto); + /** + * 用户退出登陆 + * + * @param dto 退出登陆dto + * @return + */ + void logout(LogoutDTO dto); + /** * 修改用户密码 * diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java index feb13c8..c32de84 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java @@ -75,7 +75,7 @@ public class GroupServiceImpl extends ServiceImpl implements return vo; } - @CacheEvict(value = "#vo.getId()") + @CacheEvict(key = "#vo.getId()") @Transactional(rollbackFor = Exception.class) @Override public GroupVO modifyGroup(GroupVO vo) { @@ -100,7 +100,7 @@ public class GroupServiceImpl extends ServiceImpl implements } @Transactional(rollbackFor = Exception.class) - @CacheEvict(value = "#groupId") + @CacheEvict(key = "#groupId") @Override public void deleteGroup(Long groupId) { UserSession session = SessionContext.getSession(); @@ -178,7 +178,7 @@ public class GroupServiceImpl extends ServiceImpl implements return vo; } - @Cacheable(value = "#groupId") + @Cacheable(key = "#groupId") @Override public Group getById(Long groupId) { Group group = super.getById(groupId); diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java index 0e10922..3c0dc4d 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java @@ -21,6 +21,7 @@ import com.bx.implatform.exception.GlobalException; import com.bx.implatform.mapper.PrivateMessageMapper; import com.bx.implatform.service.IFriendService; import com.bx.implatform.service.IPrivateMessageService; +import com.bx.implatform.service.INotifyPrivateService; import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; @@ -43,7 +44,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl implements IU private final JwtProperties jwtProperties; private final IMClient imClient; + @Override public LoginVO login(LoginDTO dto) { User user = this.findUserByUserName(dto.getUserName()); @@ -56,6 +61,12 @@ public class UserServiceImpl extends ServiceImpl implements IU if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) { throw new GlobalException(ResultCode.PASSWOR_ERROR); } + // 更新用户登陆时间和cid + user.setLastLoginTime(new Date()); + if(StrUtil.isNotEmpty(dto.getCid())){ + user.setCid(dto.getCid()); + } + this.updateById(user); // 生成token UserSession session = BeanUtils.copyProperties(user, UserSession.class); session.setUserId(user.getId()); @@ -71,6 +82,19 @@ public class UserServiceImpl extends ServiceImpl implements IU return vo; } + @Override + public void logout(LogoutDTO dto) { + UserSession session = SessionContext.getSession(); + if(StrUtil.isNotEmpty(dto.getCid())){ + // 清除cid,不再推送离线通知 + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(); + wrapper.eq(User::getId,session.getUserId()); + wrapper.eq(User::getCid,dto.getCid()); + wrapper.set(User::getCid, Strings.EMPTY); + this.update(wrapper); + } + } + @Override public LoginVO refreshToken(String refreshToken) { //验证 token diff --git a/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java b/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java new file mode 100644 index 0000000..f0c367b --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java @@ -0,0 +1,122 @@ +package com.bx.implatform.service.thirdparty; + +import com.bx.implatform.session.NotifySession; +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.Settings; +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.GTNotification; +import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification; +import com.getui.push.v2.sdk.dto.req.message.android.Ups; +import com.getui.push.v2.sdk.dto.req.message.ios.Alert; +import com.getui.push.v2.sdk.dto.req.message.ios.Aps; +import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author: 谢绍许 + * @date: 2024-07-06 + * @version: 1.0 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class UniPushService { + + private final PushApi pushApi; + + public void pushByCid(NotifySession session, String body){ + //根据cid进行单推 + PushDTO pushDTO = new PushDTO(); + // 设置推送参数,requestid需要每次变化唯一 + pushDTO.setRequestId(System.currentTimeMillis()+""); + Settings settings = new Settings(); + pushDTO.setSettings(settings); + //消息有效期,走厂商消息必须设置该值 + settings.setTtl(3600000); + //在线走个推通道时推送的消息体 + PushMessage pushMessage = new PushMessage(); + pushDTO.setPushMessage(pushMessage); + //此格式的透传消息由 unipush 做了特殊处理,会自动展示通知栏。开发者也可自定义其它格式,在客户端自己处理。 + GTNotification gtNotification = new GTNotification(); + gtNotification.setTitle(session.getTitle()); + gtNotification.setBody(body); + gtNotification.setClickType("startapp"); + gtNotification.setNotifyId(session.getNotifyId().toString()); + gtNotification.setLogoUrl(session.getLogo()); + gtNotification.setBadgeAddNum("1"); + pushMessage.setNotification(gtNotification); + // 设置接收人信息 + Audience audience = new Audience(); + pushDTO.setAudience(audience); + audience.addCid(session.getCid()); + //设置离线推送时的消息体 + PushChannel pushChannel = new PushChannel(); + //安卓离线厂商通道推送的消息体 + AndroidDTO androidDTO = new AndroidDTO(); + Ups ups = new Ups(); + ThirdNotification thirdNotification = new ThirdNotification(); + ups.setNotification(thirdNotification); + ups.setOptions(buildOptions(session.getLogo())); + thirdNotification.setTitle(session.getTitle()); + thirdNotification.setBody(body); + thirdNotification.setNotifyId(session.getNotifyId().toString()); + // 打开首页 + thirdNotification.setClickType("startapp"); + androidDTO.setUps(ups); + pushChannel.setAndroid(androidDTO); + // ios离线apn通道推送的消息体 + Alert alert = new Alert(); + alert.setTitle(session.getTitle()); + alert.setBody(body); + Aps aps = new Aps(); + // 0:普通通知消息 1:静默推送(无通知栏消息),静默推送时不需要填写其他参数。苹果建议1小时最多推送3条静默消息 + aps.setContentAvailable(0); + // default: 系统铃声 不填:无声 + aps.setSound("default"); + aps.setAlert(alert); + + IosDTO iosDTO = new IosDTO(); + iosDTO.setAps(aps); + iosDTO.setType("notify"); + pushChannel.setIos(iosDTO); + pushDTO.setPushChannel(pushChannel); + // 进行cid单推 + ApiResult>> apiResult = pushApi.pushToSingleByCid(pushDTO); + if (apiResult.isSuccess()) { + log.info("推送成功,{}",apiResult.getData()); + } else { + log.info("推送失败,code:{},msg:{}",apiResult.getCode(),apiResult.getMsg()); + } + } + + + private Map> buildOptions(String logo){ + Map> options = new HashMap<>(); + // 小米 + Map xm = new HashMap<>(); + xm.put("/extra.notification_style_type",1); + xm.put("/extra.notification_large_icon_uri",logo); + options.put("XM",xm); + // 华为 + Map hw = new HashMap<>(); + hw.put("/message/android/notification/image",logo); + hw.put("/message/android/notification/style",1); + options.put("HW",hw); + // 荣耀 + Map ho = new HashMap<>(); + hw.put("/android/notification/badge/addNum",1); + hw.put("/android/notification/icon",logo); + options.put("HW",hw); + return options; + } +} diff --git a/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java b/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java new file mode 100644 index 0000000..1ab253c --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java @@ -0,0 +1,43 @@ +package com.bx.implatform.session; + +import lombok.Data; + +/** + * 离线通知session + * @author: blue + * @date: 2024-07-06 + * @version: 1.0 + */ +@Data +public class NotifySession { + /** + * 接收方客户端id + */ + private String cid; + + /** + * 通知id + */ + private Integer notifyId; + + /** + * 发送方用户名 + */ + private String sendNickName; + + /** + * 标题 + */ + private String title; + + /** + * 显示图标 + */ + private String logo; + + /** + * 消息数量 + */ + private Integer count; + +} diff --git a/im-platform/src/main/resources/application.yml b/im-platform/src/main/resources/application.yml index 8e0cbe8..2c26381 100644 --- a/im-platform/src/main/resources/application.yml +++ b/im-platform/src/main/resources/application.yml @@ -43,6 +43,16 @@ webrtc: iceServers: - urls: stun:stun.l.google.com:19302 +notify: + enable: true + max: + private: -1 # 私聊单个会话最大通知数量,-1表示不显示 + group: 10 # 群聊单个会话最大通知数量,-1表示不显示 + uniPush: + appId: nyK71XQYUy9s7Vlzoutlp1 + appKey: XtG6NkUSL98evtpLSE0jYA + masterSecret: MxApXxsx057jcPCeC0cXk6 + jwt: accessToken: expireIn: 1800 #半个小时 diff --git a/im-platform/src/main/resources/db/db.sql b/im-platform/src/main/resources/db/db.sql index 1ea4b86..03a5486 100644 --- a/im-platform/src/main/resources/db/db.sql +++ b/im-platform/src/main/resources/db/db.sql @@ -9,6 +9,7 @@ create table `im_user`( `sex` tinyint(1) default 0 comment '性别 0:男 1:女', `type` smallint default 1 comment '用户类型 1:普通用户 2:审核账户', `signature` varchar(1024) default '' comment '个性签名', + `cid` varchar(255) default '' comment '客户端id,用于uni-push推送', `last_login_time` datetime DEFAULT null comment '最后登录时间', `created_time` datetime DEFAULT CURRENT_TIMESTAMP comment '创建时间', unique key `idx_user_name`(user_name), diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 549bf4e..77fe6c6 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -19,6 +19,7 @@ store.dispatch("load").then(() => { // 初始化websocket this.initWebSocket(); + this.initUniPush(); }).catch((e) => { console.log(e); this.exit(); @@ -312,6 +313,21 @@ url: '/user/self', method: 'GET' }) + }, + initUniPush(){ + // #ifdef APP-PLUS + plus.push.setAutoNotification(true); + const clientInfo = plus.push.getClientInfo(); + console.log("clientInfo",clientInfo); + plus.push.addEventListener('click', (message)=>{ + const messages = plus.push.getAllMessage(); + console.log("messages",messages) + console.log("click",message) + }); + plus.push.addEventListener('receive', (message)=>{ + console.log("receive",message) + }); + // #endif } }, onLaunch() { @@ -333,6 +349,7 @@ }) // #endif } + } } diff --git a/im-uniapp/manifest.json b/im-uniapp/manifest.json index d69c7ad..2c30905 100644 --- a/im-uniapp/manifest.json +++ b/im-uniapp/manifest.json @@ -20,7 +20,8 @@ "modules" : { "Camera" : {}, "Record" : {}, - "Bluetooth" : {} + "Bluetooth" : {}, + "Push" : {} }, /* 应用发布信息 */ "distribute" : { @@ -59,7 +60,16 @@ /* SDK配置 */ "sdkConfigs" : { "ad" : {}, - "speech" : {} + "speech" : {}, + "push" : { + "unipush" : { + "icons" : { + "small" : { + "ldpi" : "C:/Users/82565/Desktop/盒子/logo.png" + } + } + } + } }, "icons" : { "android" : { diff --git a/im-uniapp/pages/login/login.vue b/im-uniapp/pages/login/login.vue index e3146b0..07ae6cb 100644 --- a/im-uniapp/pages/login/login.vue +++ b/im-uniapp/pages/login/login.vue @@ -21,7 +21,8 @@ loginForm: { terminal: 1, // APP终端 userName: '', - password: '' + password: '', + cid: '' }, rules: { userName: { @@ -41,6 +42,11 @@ }, methods: { submit() { + // APP需要上报cid,用于离线推送 + // #ifdef APP-PLUS + const clientInfo = plus.push.getClientInfo(); + this.loginForm.cid = clientInfo.clientid; + // #endif this.$http({ url: '/login', data: this.loginForm, From edd01b70ce9fcfea18e1b8990371a40e19e78ada Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 8 Jul 2024 17:06:30 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5unipush?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../implatform/service/INotifyPrivateService.java | 13 +++++++++++-- .../service/impl/PrivateMessageServiceImpl.java | 2 +- .../bx/implatform/service/impl/UserServiceImpl.java | 8 ++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java index 6fa2f5a..323d889 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java +++ b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java @@ -7,7 +7,9 @@ import com.bx.implatform.session.NotifySession; import com.bx.implatform.service.thirdparty.UniPushService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -27,8 +29,10 @@ import java.util.concurrent.TimeUnit; @Service @RequiredArgsConstructor public class INotifyPrivateService { + @Lazy + @Autowired + private IUserService userService; private final UniPushService uniPushService; - private final IUserService userService; private final RedisTemplate redisTemplate; @Value("${notify.enable}") private Boolean enable = false; @@ -64,12 +68,17 @@ public class INotifyPrivateService { saveNotifySession(session,sendId,recvId); } - public void removeNotifySession(Long sendId, Long recvId){ + public void removeNotifySession( Long recvId){ String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, "*", recvId); Set keys = redisTemplate.keys(key); redisTemplate.delete(keys); } + public void removeNotifySession(Long sendId, Long recvId){ + String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); + redisTemplate.delete(key); + } + private NotifySession createNotifySession(Long sendId, Long recvId) { String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); User sendUser = userService.getById(sendId); diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java index 3c0dc4d..0904735 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java @@ -220,7 +220,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl implements IU private final IFriendService friendService; private final JwtProperties jwtProperties; private final IMClient imClient; - + private final INotifyPrivateService notifyPrivateService; @Override public LoginVO login(LoginDTO dto) { @@ -63,8 +64,10 @@ public class UserServiceImpl extends ServiceImpl implements IU } // 更新用户登陆时间和cid user.setLastLoginTime(new Date()); - if(StrUtil.isNotEmpty(dto.getCid())){ + // 用户更换了设备,记录新的cid + if(StrUtil.isNotEmpty(dto.getCid()) && dto.getCid().equals(user.getCid())){ user.setCid(dto.getCid()); + notifyPrivateService.removeNotifySession(user.getId()); } this.updateById(user); // 生成token @@ -87,6 +90,7 @@ public class UserServiceImpl extends ServiceImpl implements IU UserSession session = SessionContext.getSession(); if(StrUtil.isNotEmpty(dto.getCid())){ // 清除cid,不再推送离线通知 + notifyPrivateService.removeNotifySession(session.getUserId()); LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(); wrapper.eq(User::getId,session.getUserId()); wrapper.eq(User::getCid,dto.getCid()); From 3ffd84498b058d26f18b876a8251d44671ed367e Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 5 Aug 2024 22:23:57 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=E5=9C=A8=E7=BA=BF=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../bx/implatform/config/RedissonConfig.java | 39 ------------------- .../com/bx/imserver/config/RedisConfig.java | 35 +++++++++++++++++ .../bx/imserver/netty/IMChannelHandler.java | 2 +- 4 files changed, 37 insertions(+), 41 deletions(-) delete mode 100644 im-platform/src/main/java/com/bx/implatform/config/RedissonConfig.java create mode 100644 im-server/src/main/java/com/bx/imserver/config/RedisConfig.java diff --git a/README.md b/README.md index 4ac5a63..2b3e9d6 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ - redis记录了每个用户的websocket连接的是哪个im-server,当用户发送消息时,im-platform将根据所连接的im-server的id,决定将消息推向哪个queue -#### 本地快速部署 +#### 本地启动 1.安装运行环境 - 安装node:v18.19.0 - 安装jdk:17 diff --git a/im-platform/src/main/java/com/bx/implatform/config/RedissonConfig.java b/im-platform/src/main/java/com/bx/implatform/config/RedissonConfig.java deleted file mode 100644 index f3203a0..0000000 --- a/im-platform/src/main/java/com/bx/implatform/config/RedissonConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.bx.implatform.config; - -import cn.hutool.core.util.StrUtil; -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.client.codec.StringCodec; -import org.redisson.config.Config; -import org.redisson.config.SingleServerConfig; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; -import org.springframework.context.annotation.Bean; - -/** - * @author: Blue - * @date: 2024-06-09 - * @version: 1.0 - */ - -//@Configuration -//@ConditionalOnClass(Config.class) -//@EnableConfigurationProperties(RedisProperties.class) -public class RedissonConfig { - - @Bean - RedissonClient redissonClient(RedisProperties redisProperties) { - Config config = new Config(); - config.setCodec(new StringCodec()); - String address = "redis://" + redisProperties.getHost()+":"+redisProperties.getPort(); - SingleServerConfig serverConfig = config.useSingleServer() - .setAddress(address) - .setDatabase(redisProperties.getDatabase()); - if(StrUtil.isNotEmpty(redisProperties.getPassword())) { - serverConfig.setPassword(redisProperties.getPassword()); - } - - return Redisson.create(config); - } - - -} diff --git a/im-server/src/main/java/com/bx/imserver/config/RedisConfig.java b/im-server/src/main/java/com/bx/imserver/config/RedisConfig.java new file mode 100644 index 0000000..fd9d26c --- /dev/null +++ b/im-server/src/main/java/com/bx/imserver/config/RedisConfig.java @@ -0,0 +1,35 @@ +package com.bx.imserver.config; + +import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Primary + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + // 设置值(value)的序列化采用FastJsonRedisSerializer + redisTemplate.setValueSerializer(fastJsonRedisSerializer()); + redisTemplate.setHashValueSerializer(fastJsonRedisSerializer()); + // 设置键(key)的序列化采用StringRedisSerializer。 + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + + public FastJsonRedisSerializer fastJsonRedisSerializer() { + return new FastJsonRedisSerializer<>(Object.class); + } + + +} diff --git a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java index dd9e30e..a932093 100644 --- a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java +++ b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java @@ -71,7 +71,7 @@ public class IMChannelHandler extends SimpleChannelInboundHandler { // 移除channel UserChannelCtxMap.removeChannelCtx(userId, terminal); // 用户下线 - RedisTemplate redisTemplate = SpringContextHolder.getBean("redisTemplate"); + RedisTemplate redisTemplate = SpringContextHolder.getBean(RedisTemplate.class); String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), terminal.toString()); redisTemplate.delete(key); log.info("断开连接,userId:{},终端类型:{},{}", userId, terminal, ctx.channel().id().asLongText()); From 7323342430f9eae7163cca33e2bf32b8d7783d12 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 5 Aug 2024 22:48:38 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=BF=98=E5=8E=9F=E6=97=A0=E6=95=88?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bx/implatform/contant/RedisKey.java | 6 - .../java/com/bx/implatform/dto/LoginDTO.java | 3 - .../java/com/bx/implatform/dto/LogoutDTO.java | 19 --- .../java/com/bx/implatform/entity/User.java | 5 - .../listener/PrivateMessageListener.java | 36 +----- .../service/INotifyPrivateService.java | 107 --------------- .../bx/implatform/service/UserService.java | 9 -- .../impl/PrivateMessageServiceImpl.java | 32 ++--- .../service/impl/UserServiceImpl.java | 28 ---- .../service/thirdparty/UniPushService.java | 122 ------------------ im-uniapp/App.vue | 17 --- im-uniapp/pages/login/login.vue | 8 +- 12 files changed, 19 insertions(+), 373 deletions(-) delete mode 100644 im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java delete mode 100644 im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java delete mode 100644 im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java diff --git a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java index 221ddbf..17ddd9f 100644 --- a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java +++ b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java @@ -10,11 +10,6 @@ public final class RedisKey { * 已读群聊消息位置(已读最大id) */ public static final String IM_GROUP_READED_POSITION = "im:readed:group:position"; - - /** - * 私聊离线通知 - */ - public static final String IM_OFFLINE_NOTIFY_PRIVATE = "im:notify:private"; /** * webrtc 单人通话 */ @@ -57,5 +52,4 @@ public final class RedisKey { */ public static final String IM_LOCK_RTC_GROUP = "im:lock:rtc:group"; - } diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java index 5470fac..30b240e 100644 --- a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java +++ b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java @@ -25,7 +25,4 @@ public class LoginDTO { @Schema(description = "用户密码") private String password; - @ApiModelProperty(value = "用户客户端id") - private String cid; - } diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java deleted file mode 100644 index 4b252af..0000000 --- a/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.bx.implatform.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@Data -@ApiModel("用户登录DTO") -public class LogoutDTO { - - @ApiModelProperty(value = "用户客户端id") - private String cid; - -} diff --git a/im-platform/src/main/java/com/bx/implatform/entity/User.java b/im-platform/src/main/java/com/bx/implatform/entity/User.java index 3960601..ca292e6 100644 --- a/im-platform/src/main/java/com/bx/implatform/entity/User.java +++ b/im-platform/src/main/java/com/bx/implatform/entity/User.java @@ -69,11 +69,6 @@ public class User { */ private String reason; - /** - * 客户端id,用于uni-push推送 - */ - @TableField("cid") - private String cid; /** * 最后登录时间 */ diff --git a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java index d60fa46..6417274 100644 --- a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java +++ b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java @@ -6,12 +6,10 @@ import com.bx.imclient.annotation.IMListener; import com.bx.imclient.listener.MessageListener; import com.bx.imcommon.enums.IMListenerType; import com.bx.imcommon.enums.IMSendCode; -import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.model.IMSendResult; import com.bx.implatform.entity.PrivateMessage; import com.bx.implatform.enums.MessageStatus; import com.bx.implatform.service.PrivateMessageService; -import com.bx.implatform.service.INotifyPrivateService; import com.bx.implatform.vo.PrivateMessageVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -24,36 +22,22 @@ import java.util.Set; @Slf4j @IMListener(type = IMListenerType.PRIVATE_MESSAGE) public class PrivateMessageListener implements MessageListener { - @Lazy @Autowired private PrivateMessageService privateMessageService; - - @Lazy - @Autowired - private NotifyPrivateService uniPushService; - @Override public void process(List> results) { - // 更新消息状态 - updateMessageStatus(results); - // 推送离线通知 - sendOfflineNotify(results); - } - - private void updateMessageStatus(List> results) { Set messageIds = new HashSet<>(); - for (IMSendResult result : results) { + for(IMSendResult result : results){ PrivateMessageVO messageInfo = result.getData(); // 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态 if (result.getCode().equals(IMSendCode.SUCCESS.code())) { messageIds.add(messageInfo.getId()); - log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), - result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal()); + log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal()); } } - // 对发送成功的消息修改状态 - if (CollUtil.isNotEmpty(messageIds)) { + // 批量修改状态 + if(CollUtil.isNotEmpty(messageIds)){ UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.lambda().in(PrivateMessage::getId, messageIds) .eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code()) @@ -61,16 +45,4 @@ public class PrivateMessageListener implements MessageListener privateMessageService.update(updateWrapper); } } - - private void sendOfflineNotify(List> results) { - for (IMSendResult result : results) { - PrivateMessageVO messageInfo = result.getData(); - if (result.getCode().equals(IMSendCode.SUCCESS.code()) && result.getReceiver().getTerminal() - .equals(IMTerminalType.APP.code())) { - uniPushService.sendMessage(messageInfo.getSendId(), messageInfo.getRecvId(), messageInfo.getContent()); - log.info("推送离线通知,消息id:{},发送者:{},接收者:{}", messageInfo.getId(), result.getSender().getId(), - result.getReceiver().getId()); - } - } - } } diff --git a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java deleted file mode 100644 index 323d889..0000000 --- a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.bx.implatform.service; - -import cn.hutool.core.util.StrUtil; -import com.bx.implatform.contant.RedisKey; -import com.bx.implatform.entity.User; -import com.bx.implatform.session.NotifySession; -import com.bx.implatform.service.thirdparty.UniPushService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * 私聊离线通知服务 - * - * @author: blue - * @date: 2024-07-06 - * @version: 1.0 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class INotifyPrivateService { - @Lazy - @Autowired - private IUserService userService; - private final UniPushService uniPushService; - private final RedisTemplate redisTemplate; - @Value("${notify.enable}") - private Boolean enable = false; - @Value("${notify.max.private}") - private Integer max = -1; - public void sendMessage(Long sendId, Long recvId, String content) { - if(!enable){ - return; - } - NotifySession session = findNotifySession(sendId, recvId); - if (Objects.isNull(session)) { - session = createNotifySession(sendId, recvId); - } - // 未上报cid,无法推送 - if (StrUtil.isEmpty(session.getCid())) { - log.info("用户'{}'未上报cid,无法推送离线通知", recvId); - return; - } - // 已达到最大数量 - if (max > 0 && session.getCount() >= max) { - log.info("用户'{}'已到达推送数量上线,不再推送离线通知", recvId); - return; - } - // 消息数量加1 - session.setCount(session.getCount()+1); - String body = String.format("%s:%s", session.getSendNickName(),content); - // 大于1条时需要展示数量 - if (session.getCount() > 1) { - body = String.format("[%d条] ", session.getCount()) + body; - } - uniPushService.pushByCid(session,body); - // 保存会话 - saveNotifySession(session,sendId,recvId); - } - - public void removeNotifySession( Long recvId){ - String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, "*", recvId); - Set keys = redisTemplate.keys(key); - redisTemplate.delete(keys); - } - - public void removeNotifySession(Long sendId, Long recvId){ - String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); - redisTemplate.delete(key); - } - - private NotifySession createNotifySession(Long sendId, Long recvId) { - String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); - User sendUser = userService.getById(sendId); - User recvUser = userService.getById(recvId); - NotifySession session = new NotifySession(); - session.setCount(0); - session.setCid(recvUser.getCid()); - session.setTitle(sendUser.getNickName()); - session.setSendNickName(sendUser.getNickName()); - session.setNotifyId(Math.abs(key.hashCode())); - session.setLogo(sendUser.getHeadImageThumb()); - redisTemplate.opsForValue().set(key, session, 30, TimeUnit.DAYS); - return session; - } - - private NotifySession findNotifySession(Long sendId, Long recvId) { - String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); - return (NotifySession)redisTemplate.opsForValue().get(key); - } - - private void saveNotifySession(NotifySession session, Long sendId, Long recvId) { - String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId); - redisTemplate.opsForValue().set(key, session); - } - -} diff --git a/im-platform/src/main/java/com/bx/implatform/service/UserService.java b/im-platform/src/main/java/com/bx/implatform/service/UserService.java index b5f28e5..37bcc8b 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/UserService.java +++ b/im-platform/src/main/java/com/bx/implatform/service/UserService.java @@ -2,7 +2,6 @@ package com.bx.implatform.service; import com.baomidou.mybatisplus.extension.service.IService; import com.bx.implatform.dto.LoginDTO; -import com.bx.implatform.dto.LogoutDTO; import com.bx.implatform.dto.ModifyPwdDTO; import com.bx.implatform.dto.RegisterDTO; import com.bx.implatform.entity.User; @@ -22,14 +21,6 @@ public interface UserService extends IService { */ LoginVO login(LoginDTO dto); - /** - * 用户退出登陆 - * - * @param dto 退出登陆dto - * @return - */ - void logout(LogoutDTO dto); - /** * 修改用户密码 * diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java index 132d4db..213c809 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java @@ -20,7 +20,6 @@ import com.bx.implatform.exception.GlobalException; import com.bx.implatform.mapper.PrivateMessageMapper; import com.bx.implatform.service.FriendService; import com.bx.implatform.service.PrivateMessageService; -import com.bx.implatform.service.NotifyPrivateService; import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; @@ -44,7 +43,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl wrapper = new QueryWrapper<>(); wrapper.lambda().and(wrap -> wrap.and( - wp -> wp.eq(PrivateMessage::getSendId, userId) + wp -> wp.eq(PrivateMessage::getSendId, userId) .eq(PrivateMessage::getRecvId, friendId)) .or(wp -> wp.eq(PrivateMessage::getRecvId, userId) - .eq(PrivateMessage::getSendId, friendId))) - .ne(PrivateMessage::getStatus, MessageStatus.RECALL.code()) - .orderByDesc(PrivateMessage::getId) - .last("limit " + stIdx + "," + size); + .eq(PrivateMessage::getSendId, friendId))) + .ne(PrivateMessage::getStatus, MessageStatus.RECALL.code()) + .orderByDesc(PrivateMessage::getId) + .last("limit " + stIdx + "," + size); List messages = this.list(wrapper); List messageInfos = messages.stream().map(m -> BeanUtils.copyProperties(m, PrivateMessageVO.class)).collect(Collectors.toList()); @@ -216,13 +215,10 @@ public class PrivateMessageServiceImpl extends ServiceImpl updateWrapper = Wrappers.lambdaUpdate(); updateWrapper.eq(PrivateMessage::getSendId, friendId) - .eq(PrivateMessage::getRecvId, session.getUserId()) - .eq(PrivateMessage::getStatus, MessageStatus.SENDED.code()) - .set(PrivateMessage::getStatus, MessageStatus.READED.code()); + .eq(PrivateMessage::getRecvId, session.getUserId()) + .eq(PrivateMessage::getStatus, MessageStatus.SENDED.code()) + .set(PrivateMessage::getStatus, MessageStatus.READED.code()); this.update(updateWrapper); - // 清除通知会话信息 - notifyPrivateService.removeNotifySession(friendId,session.getUserId()); - log.info("消息已读,接收方id:{},发送方id:{}", session.getUserId(), friendId); } @@ -232,11 +228,11 @@ public class PrivateMessageServiceImpl extends ServiceImpl wrapper = Wrappers.lambdaQuery(); wrapper.eq(PrivateMessage::getSendId, session.getUserId()) - .eq(PrivateMessage::getRecvId, friendId) - .eq(PrivateMessage::getStatus, MessageStatus.READED.code()) - .orderByDesc(PrivateMessage::getId) - .select(PrivateMessage::getId) - .last("limit 1"); + .eq(PrivateMessage::getRecvId, friendId) + .eq(PrivateMessage::getStatus, MessageStatus.READED.code()) + .orderByDesc(PrivateMessage::getId) + .select(PrivateMessage::getId) + .last("limit 1"); PrivateMessage message = this.getOne(wrapper); if(Objects.isNull(message)){ return -1L; diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java index 380b944..7ea154b 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java @@ -1,9 +1,7 @@ package com.bx.implatform.service.impl; -import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -12,7 +10,6 @@ import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.util.JwtUtil; import com.bx.implatform.config.JwtProperties; import com.bx.implatform.dto.LoginDTO; -import com.bx.implatform.dto.LogoutDTO; import com.bx.implatform.dto.ModifyPwdDTO; import com.bx.implatform.dto.RegisterDTO; import com.bx.implatform.entity.Friend; @@ -23,7 +20,6 @@ import com.bx.implatform.exception.GlobalException; import com.bx.implatform.mapper.UserMapper; import com.bx.implatform.service.FriendService; import com.bx.implatform.service.GroupMemberService; -import com.bx.implatform.service.NotifyPrivateService; import com.bx.implatform.service.UserService; import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; @@ -33,7 +29,6 @@ import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.UserVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.logging.log4j.util.Strings; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -51,7 +46,6 @@ public class UserServiceImpl extends ServiceImpl implements Us private final FriendService friendService; private final JwtProperties jwtProperties; private final IMClient imClient; - private final INotifyPrivateService notifyPrivateService; @Override public LoginVO login(LoginDTO dto) { @@ -66,14 +60,6 @@ public class UserServiceImpl extends ServiceImpl implements Us if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) { throw new GlobalException(ResultCode.PASSWOR_ERROR); } - // 更新用户登陆时间和cid - user.setLastLoginTime(new Date()); - // 用户更换了设备,记录新的cid - if(StrUtil.isNotEmpty(dto.getCid()) && dto.getCid().equals(user.getCid())){ - user.setCid(dto.getCid()); - notifyPrivateService.removeNotifySession(user.getId()); - } - this.updateById(user); // 生成token UserSession session = BeanUtils.copyProperties(user, UserSession.class); session.setUserId(user.getId()); @@ -91,20 +77,6 @@ public class UserServiceImpl extends ServiceImpl implements Us return vo; } - @Override - public void logout(LogoutDTO dto) { - UserSession session = SessionContext.getSession(); - if(StrUtil.isNotEmpty(dto.getCid())){ - // 清除cid,不再推送离线通知 - notifyPrivateService.removeNotifySession(session.getUserId()); - LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(); - wrapper.eq(User::getId,session.getUserId()); - wrapper.eq(User::getCid,dto.getCid()); - wrapper.set(User::getCid, Strings.EMPTY); - this.update(wrapper); - } - } - @Override public LoginVO refreshToken(String refreshToken) { //验证 token diff --git a/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java b/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java deleted file mode 100644 index f0c367b..0000000 --- a/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.bx.implatform.service.thirdparty; - -import com.bx.implatform.session.NotifySession; -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.Settings; -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.GTNotification; -import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification; -import com.getui.push.v2.sdk.dto.req.message.android.Ups; -import com.getui.push.v2.sdk.dto.req.message.ios.Alert; -import com.getui.push.v2.sdk.dto.req.message.ios.Aps; -import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author: 谢绍许 - * @date: 2024-07-06 - * @version: 1.0 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class UniPushService { - - private final PushApi pushApi; - - public void pushByCid(NotifySession session, String body){ - //根据cid进行单推 - PushDTO pushDTO = new PushDTO(); - // 设置推送参数,requestid需要每次变化唯一 - pushDTO.setRequestId(System.currentTimeMillis()+""); - Settings settings = new Settings(); - pushDTO.setSettings(settings); - //消息有效期,走厂商消息必须设置该值 - settings.setTtl(3600000); - //在线走个推通道时推送的消息体 - PushMessage pushMessage = new PushMessage(); - pushDTO.setPushMessage(pushMessage); - //此格式的透传消息由 unipush 做了特殊处理,会自动展示通知栏。开发者也可自定义其它格式,在客户端自己处理。 - GTNotification gtNotification = new GTNotification(); - gtNotification.setTitle(session.getTitle()); - gtNotification.setBody(body); - gtNotification.setClickType("startapp"); - gtNotification.setNotifyId(session.getNotifyId().toString()); - gtNotification.setLogoUrl(session.getLogo()); - gtNotification.setBadgeAddNum("1"); - pushMessage.setNotification(gtNotification); - // 设置接收人信息 - Audience audience = new Audience(); - pushDTO.setAudience(audience); - audience.addCid(session.getCid()); - //设置离线推送时的消息体 - PushChannel pushChannel = new PushChannel(); - //安卓离线厂商通道推送的消息体 - AndroidDTO androidDTO = new AndroidDTO(); - Ups ups = new Ups(); - ThirdNotification thirdNotification = new ThirdNotification(); - ups.setNotification(thirdNotification); - ups.setOptions(buildOptions(session.getLogo())); - thirdNotification.setTitle(session.getTitle()); - thirdNotification.setBody(body); - thirdNotification.setNotifyId(session.getNotifyId().toString()); - // 打开首页 - thirdNotification.setClickType("startapp"); - androidDTO.setUps(ups); - pushChannel.setAndroid(androidDTO); - // ios离线apn通道推送的消息体 - Alert alert = new Alert(); - alert.setTitle(session.getTitle()); - alert.setBody(body); - Aps aps = new Aps(); - // 0:普通通知消息 1:静默推送(无通知栏消息),静默推送时不需要填写其他参数。苹果建议1小时最多推送3条静默消息 - aps.setContentAvailable(0); - // default: 系统铃声 不填:无声 - aps.setSound("default"); - aps.setAlert(alert); - - IosDTO iosDTO = new IosDTO(); - iosDTO.setAps(aps); - iosDTO.setType("notify"); - pushChannel.setIos(iosDTO); - pushDTO.setPushChannel(pushChannel); - // 进行cid单推 - ApiResult>> apiResult = pushApi.pushToSingleByCid(pushDTO); - if (apiResult.isSuccess()) { - log.info("推送成功,{}",apiResult.getData()); - } else { - log.info("推送失败,code:{},msg:{}",apiResult.getCode(),apiResult.getMsg()); - } - } - - - private Map> buildOptions(String logo){ - Map> options = new HashMap<>(); - // 小米 - Map xm = new HashMap<>(); - xm.put("/extra.notification_style_type",1); - xm.put("/extra.notification_large_icon_uri",logo); - options.put("XM",xm); - // 华为 - Map hw = new HashMap<>(); - hw.put("/message/android/notification/image",logo); - hw.put("/message/android/notification/style",1); - options.put("HW",hw); - // 荣耀 - Map ho = new HashMap<>(); - hw.put("/android/notification/badge/addNum",1); - hw.put("/android/notification/icon",logo); - options.put("HW",hw); - return options; - } -} diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 7984fb7..98a8802 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -21,7 +21,6 @@ store.dispatch("load").then(() => { // 初始化websocket this.initWebSocket(); - this.initUniPush(); }).catch((e) => { console.log(e); this.exit(); @@ -331,21 +330,6 @@ url: '/user/self', method: 'GET' }) - }, - initUniPush(){ - // #ifdef APP-PLUS - plus.push.setAutoNotification(true); - const clientInfo = plus.push.getClientInfo(); - console.log("clientInfo",clientInfo); - plus.push.addEventListener('click', (message)=>{ - const messages = plus.push.getAllMessage(); - console.log("messages",messages) - console.log("click",message) - }); - plus.push.addEventListener('receive', (message)=>{ - console.log("receive",message) - }); - // #endif } }, onLaunch() { @@ -367,7 +351,6 @@ }) // #endif } - } } diff --git a/im-uniapp/pages/login/login.vue b/im-uniapp/pages/login/login.vue index 1e91a81..f8cb97a 100644 --- a/im-uniapp/pages/login/login.vue +++ b/im-uniapp/pages/login/login.vue @@ -23,8 +23,7 @@ loginForm: { terminal: 1, // APP终端 userName: '', - password: '', - cid: '' + password: '' }, rules: { userName: { @@ -44,11 +43,6 @@ }, methods: { submit() { - // APP需要上报cid,用于离线推送 - // #ifdef APP-PLUS - const clientInfo = plus.push.getClientInfo(); - this.loginForm.cid = clientInfo.clientid; - // #endif this.$http({ url: '/login', data: this.loginForm, From e24fbf1db40dc5b5711971c7c7766d54cffa1ce7 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 5 Aug 2024 22:58:21 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E8=BF=98=E5=8E=9F=E6=97=A0=E6=95=88?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/im-platform.sql | 1 - im-platform/pom.xml | 5 --- .../bx/implatform/config/UniPushConfig.java | 44 ------------------- .../bx/implatform/session/NotifySession.java | 43 ------------------ .../src/main/resources/application.yml | 10 ----- im-uniapp/manifest.json | 14 +----- 6 files changed, 2 insertions(+), 115 deletions(-) delete mode 100644 im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java delete mode 100644 im-platform/src/main/java/com/bx/implatform/session/NotifySession.java diff --git a/db/im-platform.sql b/db/im-platform.sql index 003b6f8..d90976f 100644 --- a/db/im-platform.sql +++ b/db/im-platform.sql @@ -10,7 +10,6 @@ create table `im_user`( `reason` varchar(255) default '' comment '被封禁原因', `type` smallint default 1 comment '用户类型 1:普通用户 2:审核账户', `signature` varchar(1024) default '' comment '个性签名', - `cid` varchar(255) default '' comment '客户端id,用于uni-push推送', `last_login_time` datetime DEFAULT null comment '最后登录时间', `created_time` datetime DEFAULT CURRENT_TIMESTAMP comment '创建时间', unique key `idx_user_name`(user_name), diff --git a/im-platform/pom.xml b/im-platform/pom.xml index 8aaab0a..65ef8ab 100644 --- a/im-platform/pom.xml +++ b/im-platform/pom.xml @@ -91,11 +91,6 @@ knife4j-openapi3-jakarta-spring-boot-starter ${knife4j.version} - - com.getui.push - restful-sdk - 1.0.3.0 - ${project.artifactId} diff --git a/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java b/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java deleted file mode 100644 index 641c3f6..0000000 --- a/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.bx.implatform.config; - -import com.getui.push.v2.sdk.ApiHelper; -import com.getui.push.v2.sdk.GtApiConfiguration; -import com.getui.push.v2.sdk.api.PushApi; -import lombok.Data; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -/** - * @author: 谢绍许 - * @date: 2024-07-06 - * @version: 1.0 - */ -@Data -@Component -public class UniPushConfig { - - @Value("${notify.uniPush.appId}") - private String appId; - @Value("${notify.uniPush.appKey}") - private String appKey; - @Value("${notify.uniPush.masterSecret}") - private String masterSecret; - - @Bean - public GtApiConfiguration uniPushConfiguration(){ - GtApiConfiguration apiConfiguration = new GtApiConfiguration(); - apiConfiguration.setAppId(appId); - apiConfiguration.setAppKey(appKey); - apiConfiguration.setMasterSecret(masterSecret); - return apiConfiguration; - } - - @Bean - public PushApi uniPushApi(GtApiConfiguration configuration){ - // 实例化ApiHelper对象,用于创建接口对象 - ApiHelper apiHelper = ApiHelper.build(configuration); - // 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi - PushApi pushApi = apiHelper.creatApi(PushApi.class); - return pushApi; - } -} diff --git a/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java b/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java deleted file mode 100644 index 1ab253c..0000000 --- a/im-platform/src/main/java/com/bx/implatform/session/NotifySession.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.bx.implatform.session; - -import lombok.Data; - -/** - * 离线通知session - * @author: blue - * @date: 2024-07-06 - * @version: 1.0 - */ -@Data -public class NotifySession { - /** - * 接收方客户端id - */ - private String cid; - - /** - * 通知id - */ - private Integer notifyId; - - /** - * 发送方用户名 - */ - private String sendNickName; - - /** - * 标题 - */ - private String title; - - /** - * 显示图标 - */ - private String logo; - - /** - * 消息数量 - */ - private Integer count; - -} diff --git a/im-platform/src/main/resources/application.yml b/im-platform/src/main/resources/application.yml index 62ce8d6..ae5abb0 100644 --- a/im-platform/src/main/resources/application.yml +++ b/im-platform/src/main/resources/application.yml @@ -21,16 +21,6 @@ mybatis-plus: map-underscore-to-camel-case: true #开启自动驼峰命名规则 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -notify: - enable: true - max: - private: -1 # 私聊单个会话最大通知数量,-1表示不显示 - group: 10 # 群聊单个会话最大通知数量,-1表示不显示 - uniPush: - appId: nyK71XQYUy9s7Vlzoutlp1 - appKey: XtG6NkUSL98evtpLSE0jYA - masterSecret: MxApXxsx057jcPCeC0cXk6 - jwt: accessToken: expireIn: 1800 #半个小时 diff --git a/im-uniapp/manifest.json b/im-uniapp/manifest.json index 2c30905..d69c7ad 100644 --- a/im-uniapp/manifest.json +++ b/im-uniapp/manifest.json @@ -20,8 +20,7 @@ "modules" : { "Camera" : {}, "Record" : {}, - "Bluetooth" : {}, - "Push" : {} + "Bluetooth" : {} }, /* 应用发布信息 */ "distribute" : { @@ -60,16 +59,7 @@ /* SDK配置 */ "sdkConfigs" : { "ad" : {}, - "speech" : {}, - "push" : { - "unipush" : { - "icons" : { - "small" : { - "ldpi" : "C:/Users/82565/Desktop/盒子/logo.png" - } - } - } - } + "speech" : {} }, "icons" : { "android" : {