From bb812c2bbec330674d6ad20dcaaa2d88efe5d905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E4=BD=B3=E8=B1=AA?= Date: Thu, 10 Jul 2025 09:27:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=9E=E8=B0=83=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/controller/VlogController.java | 146 +++++------------- .../controller/admin/CommentController.java | 2 +- .../admin/VlogUploadController.java | 4 +- .../soopin/content/domain/bo/IndexListBO.java | 23 +++ .../soopin/content/domain/bo/MyListBO.java | 21 +++ .../content/domain/bo/SimpleListBO.java | 11 ++ .../soopin/content/service/VlogService.java | 29 +--- .../content/service/impl/VlogServiceImpl.java | 111 +++++-------- .../system/event/MessageEventListener.java | 16 +- .../system/service/ITencentIMService.java | 3 +- .../service/impl/TencentIMServiceImpl.java | 51 +++--- .../member/controller/FansController.java | 143 +++++++++++------ .../member/controller/MemberController.java | 121 ++++++++++++++- .../member/service/impl/FansServiceImpl.java | 19 ++- 14 files changed, 420 insertions(+), 280 deletions(-) create mode 100644 ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/IndexListBO.java create mode 100644 ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/MyListBO.java create mode 100644 ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/SimpleListBO.java diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java index 377be4302..1eafba0fc 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java @@ -17,6 +17,12 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import com.wzj.soopin.content.utils.RedisOperator; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.tags.Tag; +import com.wzj.soopin.content.domain.bo.IndexListBO; +import com.wzj.soopin.content.domain.bo.MyListBO; +import com.wzj.soopin.content.domain.bo.SimpleListBO; import org.springframework.web.bind.annotation.*; @@ -167,23 +173,11 @@ public class VlogController extends BaseInfoProperties { return R.ok(); } - @GetMapping("indexList") - public R indexList(@RequestParam(defaultValue = "") String userId, - @RequestParam(defaultValue = "") String search, - @RequestParam(defaultValue = "") String cityCode, - @RequestParam(defaultValue = "") String status, - @RequestParam Integer page, - @RequestParam Integer pageSize) { - - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } - - PagedGridResult gridResult = vlogService.getIndexVlogList(userId, search, cityCode,status, page, pageSize); - return R.ok(gridResult); + @Tag(name = "首页视频列表") + @PostMapping("/indexList") + public R indexList(@RequestBody IndexListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.getIndexVlogList(bo, page); + return R.ok(pages); } @GetMapping("detail") @@ -219,66 +213,39 @@ public class VlogController extends BaseInfoProperties { - @GetMapping("myPublicList") - public R myPublicList(@RequestParam String userId, - @RequestParam(defaultValue = "") String myId, - @RequestParam Integer page, - @RequestParam Integer pageSize) { - - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } - - PagedGridResult gridResult = vlogService.queryMyVlogList(userId, - myId, - page, - pageSize, - YesOrNo.NO.type); - return R.ok(gridResult); + @Tag(name = "我的公开视频列表") + @PostMapping("/myPublicList") + public R myPublicList(@RequestBody MyListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.queryMyVlogList(bo, page); + return R.ok(pages); } - @GetMapping("myPrivateList") - public R myPrivateList(@RequestParam String userId, - @RequestParam(defaultValue = "") String myId, - @RequestParam Integer page, - @RequestParam Integer pageSize) { - - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } - - PagedGridResult gridResult = vlogService.queryMyVlogList(userId, - myId, - page, - pageSize, - YesOrNo.YES.type); - return R.ok(gridResult); + @Tag(name = "我的私密视频列表") + @PostMapping("/myPrivateList") + public R myPrivateList(@RequestBody MyListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.queryMyVlogList(bo, page); + return R.ok(pages); } - @GetMapping("myLikedList") - public R myLikedList(@RequestParam String userId, - @RequestParam(defaultValue = "") String myId, - @RequestParam Integer page, - @RequestParam Integer pageSize) { + @Tag(name = "我点赞的视频列表") + @PostMapping("/myLikedList") + public R myLikedList(@RequestBody MyListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.getMyLikedVlogList(bo, page); + return R.ok(pages); + } - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } + @Tag(name = "我关注的视频列表") + @PostMapping("/followList") + public R followList(@RequestBody SimpleListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.getMyFollowVlogList(bo, page); + return R.ok(pages); + } - PagedGridResult gridResult = vlogService.getMyLikedVlogList(userId, - myId, - page, - pageSize); - return R.ok(gridResult); + @Tag(name = "好友视频列表") + @PostMapping("/friendList") + public R friendList(@RequestBody SimpleListBO bo, @RequestBody Page page) { + PagedGridResult pages = vlogService.getMyFriendVlogList(bo, page); + return R.ok(pages); } private Integer nacosConuts=0; @@ -336,41 +303,4 @@ public class VlogController extends BaseInfoProperties { return R.ok(vlogService.getVlogBeLikedCounts(vlogId)); } - @GetMapping("followList") - public R followList(@RequestParam String myId, - @RequestParam Integer page, - @RequestParam Integer pageSize) { - - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } - - PagedGridResult gridResult = vlogService.getMyFollowVlogList(myId, - page, - pageSize); - return R.ok(gridResult); - } - - @GetMapping("friendList") - public R friendList(@RequestParam String myId, - @RequestParam Integer page, - @RequestParam Integer pageSize) { - - if (page == null) { - page = COMMON_START_PAGE; - } - if (pageSize == null) { - pageSize = COMMON_PAGE_SIZE; - } - - PagedGridResult gridResult = vlogService.getMyFriendVlogList(myId, - page, - pageSize); - return R.ok(gridResult); - } - - } diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/CommentController.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/CommentController.java index e6711ea9e..2de25b5ce 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/CommentController.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/CommentController.java @@ -29,7 +29,7 @@ import java.util.Collections; @Slf4j @Api(tags = "管理端-评论管理接口") -@RequestMapping("admin/comment") +@RequestMapping("/comment") @RestController public class CommentController extends BaseController { diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java index cbfd3bc31..0c0797fc1 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java @@ -28,8 +28,8 @@ import java.time.format.DateTimeFormatter; import java.time.ZonedDateTime; @Slf4j -@Api(tags = "管理端-视频上传接口") -@RequestMapping("admin/vlog/upload") +@Api(tags = "管理端-视频") +@RequestMapping("/video") @RestController public class VlogUploadController extends BaseInfoProperties { diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/IndexListBO.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/IndexListBO.java new file mode 100644 index 000000000..828466243 --- /dev/null +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/IndexListBO.java @@ -0,0 +1,23 @@ +package com.wzj.soopin.content.domain.bo; + +import io.swagger.v3.oas.annotations.media.Schema; + +public class IndexListBO { + @Schema(description = "用户ID") + private String userId; + @Schema(description = "搜索关键字") + private String search; + @Schema(description = "城市编码") + private String cityCode; + @Schema(description = "状态") + private String status; + // getter/setter + public String getUserId() { return userId; } + public void setUserId(String userId) { this.userId = userId; } + public String getSearch() { return search; } + public void setSearch(String search) { this.search = search; } + public String getCityCode() { return cityCode; } + public void setCityCode(String cityCode) { this.cityCode = cityCode; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/MyListBO.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/MyListBO.java new file mode 100644 index 000000000..8b8837a5a --- /dev/null +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/MyListBO.java @@ -0,0 +1,21 @@ +package com.wzj.soopin.content.domain.bo; + +import io.swagger.v3.oas.annotations.media.Schema; + +public class MyListBO { + @Schema(description = "用户ID") + private String userId; + @Schema(description = "我的ID") + private String myId; + + @Schema(description = "是否公开(1公开,0私密)") + private Integer yesOrNo; + // getter/setter + public String getUserId() { return userId; } + public void setUserId(String userId) { this.userId = userId; } + public String getMyId() { return myId; } + public void setMyId(String myId) { this.myId = myId; } + + public Integer getYesOrNo() { return yesOrNo; } + public void setYesOrNo(Integer yesOrNo) { this.yesOrNo = yesOrNo; } +} diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/SimpleListBO.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/SimpleListBO.java new file mode 100644 index 000000000..771035a42 --- /dev/null +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/domain/bo/SimpleListBO.java @@ -0,0 +1,11 @@ +package com.wzj.soopin.content.domain.bo; + +import io.swagger.v3.oas.annotations.media.Schema; + +public class SimpleListBO { + @Schema(description = "我的ID") + private String myId; + // getter/setter + public String getMyId() { return myId; } + public void setMyId(String myId) { this.myId = myId; } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogService.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogService.java index ed1433190..a0c4a19df 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogService.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogService.java @@ -6,6 +6,9 @@ import com.wzj.soopin.content.domain.bo.VlogBO; import com.wzj.soopin.content.domain.po.Vlog; import com.wzj.soopin.content.domain.vo.IndexVlogVO; import com.wzj.soopin.content.utils.PagedGridResult; +import com.wzj.soopin.content.domain.bo.SimpleListBO; +import com.wzj.soopin.content.domain.bo.MyListBO; +import com.wzj.soopin.content.domain.bo.IndexListBO; import java.util.List; import java.util.Map; @@ -28,12 +31,7 @@ public interface VlogService { /** * 查询首页/搜索的vlog列表 */ - public PagedGridResult getIndexVlogList(String userId, - String search, - String cityCode, - String status, - Integer page, - Integer pageSize); + public PagedGridResult getIndexVlogList(IndexListBO bo, Page page); /** * 根据视频主键查询vlog @@ -53,11 +51,7 @@ public interface VlogService { /** * 查询用的公开/私密的视频列表 */ - public PagedGridResult queryMyVlogList(String userId, - String myId, - Integer page, - Integer pageSize, - Integer yesOrNo); + public PagedGridResult queryMyVlogList(MyListBO bo, Page page); /** * 用户点赞/喜欢视频 @@ -77,24 +71,17 @@ public interface VlogService { /** * 查询用户点赞过的短视频 */ - public PagedGridResult getMyLikedVlogList(String userId, - String myId, - Integer page, - Integer pageSize); + public PagedGridResult getMyLikedVlogList(MyListBO bo, Page page); /** * 查询用户关注的博主发布的短视频列表 */ - public PagedGridResult getMyFollowVlogList(String myId, - Integer page, - Integer pageSize); + public PagedGridResult getMyFollowVlogList(SimpleListBO bo, Page page); /** * 查询朋友发布的短视频列表 */ - public PagedGridResult getMyFriendVlogList(String myId, - Integer page, - Integer pageSize); + public PagedGridResult getMyFriendVlogList(SimpleListBO bo, Page page); /** * 根据主键查询vlog diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java index 98dcb8c63..32a1bd365 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java @@ -10,6 +10,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.wzj.soopin.content.domain.base.BaseInfoProperties; import com.wzj.soopin.content.domain.bo.VlogBO; +import com.wzj.soopin.content.domain.bo.SimpleListBO; +import com.wzj.soopin.content.domain.bo.MyListBO; +import com.wzj.soopin.content.domain.bo.IndexListBO; import com.wzj.soopin.content.domain.po.MyLikedVlog; import com.wzj.soopin.content.domain.po.Vlog; import com.wzj.soopin.content.domain.po.Users; @@ -135,10 +138,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { } @Override - public PagedGridResult getIndexVlogList(String userId, String search, String cityCode, String status, Integer page, Integer pageSize) { - Page pageParam = new Page<>(page, pageSize); + public PagedGridResult getIndexVlogList(IndexListBO bo, Page page) { + String userId = bo.getUserId(); + String search = bo.getSearch(); + String cityCode = bo.getCityCode(); + String status = bo.getStatus(); + int current = (int) page.getCurrent(); + int size = (int) page.getSize(); + Page pageParam = new Page<>(current, size); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if (StringUtils.isNotBlank(search)) { queryWrapper.like(Vlog::getTitle, search); } @@ -148,7 +156,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { if (StringUtils.isNotBlank(status)) { queryWrapper.eq(Vlog::getStatus, status); } - // Handle blocked videos if (StringUtils.isNotBlank(userId)) { String redisKey = REDIS_VIDEO_BLOCK + ":" + userId; @@ -156,7 +163,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { List blockVdList = new ArrayList<>(); ObjectMapper objectMapper = new ObjectMapper(); List reports = redis.lrange(redisKey, 0, -1); - for (String report : reports) { try { Map reportMap = objectMapper.readValue(report, new TypeReference>() {}); @@ -171,7 +177,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { } } } - // Handle blocked users if (StringUtils.isNotBlank(userId)) { String redisKey = REDIS_USER_BLOCK + ":" + userId; @@ -179,7 +184,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { List blockUserList = new ArrayList<>(); ObjectMapper objectMapper = new ObjectMapper(); List reports = redis.lrange(redisKey, 0, -1); - for (String report : reports) { try { Map reportMap = objectMapper.readValue(report, new TypeReference>() {}); @@ -194,24 +198,19 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { } } } - Page vlogPage = vlogMapper.selectPage(pageParam, queryWrapper); List vlogList = vlogPage.getRecords(); - List voList = vlogList.stream().map(v -> { IndexVlogVO vo = vlogConvert.toVO(v); - if (StringUtils.isNotBlank(userId)) { vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(Long.valueOf(userId), Long.valueOf(v.getVlogerId()))); vo.setDoILikeThisVlog(doILikeVlog(userId, v.getId())); } - vo.setLikeCounts(getVlogBeLikedCounts(v.getId())); vo.setCommentsCounts(getVlogComment(v.getId())); - return vo; }).collect(Collectors.toList()); - + // TODO: 组装PagedGridResult返回 return null; } @@ -278,29 +277,16 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { } @Override - public PagedGridResult queryMyVlogList(String userId, String myId, Integer page, Integer pageSize, Integer yesOrNo) { - Page pageParam = new Page<>(page, pageSize); + public PagedGridResult queryMyVlogList(MyListBO bo, Page page) { + int current = (int) page.getCurrent(); + int size = (int) page.getSize(); + Page pageParam = new Page<>(current, size); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(Vlog::getVlogerId, userId) - .eq(Vlog::getIsPrivate, yesOrNo); - + queryWrapper.eq(Vlog::getVlogerId, bo.getUserId()) + .eq(Vlog::getIsPrivate, bo.getYesOrNo()); Page vlogPage = vlogMapper.selectPage(pageParam, queryWrapper); List vlogList = vlogPage.getRecords(); - - List voList = vlogList.stream().map(v -> { - IndexVlogVO vo = vlogConvert.toVO(v); - - if (StringUtils.isNotBlank(myId)) { - vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(myId, v.getVlogerId())); - vo.setDoILikeThisVlog(doILikeVlog(myId, v.getId())); - } - - vo.setLikeCounts(getVlogBeLikedCounts(v.getId())); - vo.setCommentsCounts(getVlogComment(v.getId())); - - return vo; - }).collect(Collectors.toList()); - + // TODO: 组装PagedGridResult返回 return null; } @@ -378,52 +364,39 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService { } @Override - public PagedGridResult getMyLikedVlogList(String userId, String myId, Integer page, Integer pageSize) { - Page pageParam = new Page<>(page, pageSize); + public PagedGridResult getMyLikedVlogList(MyListBO bo, Page page) { + int current = (int) page.getCurrent(); + int size = (int) page.getSize(); + Page pageParam = new Page<>(current, size); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(MyLikedVlog::getUserId, userId); - + queryWrapper.eq(MyLikedVlog::getUserId, bo.getUserId()); Page likedPage = myLikedVlogMapper.selectPage(pageParam, queryWrapper); List likedList = likedPage.getRecords(); - - List voList = likedList.stream().map(liked -> { - Vlog vlog = vlogMapper.selectById(liked.getVlogId()); - if (vlog == null) { - return null; - } - - IndexVlogVO vo = vlogConvert.toVO(vlog); - - if (StringUtils.isNotBlank(myId)) { - vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(myId, vlog.getVlogerId())); - vo.setDoILikeThisVlog(doILikeVlog(myId, vlog.getId())); - } - - vo.setLikeCounts(getVlogBeLikedCounts(vlog.getId())); - vo.setCommentsCounts(getVlogComment(vlog.getId())); - - return vo; - }).filter(Objects::nonNull).collect(Collectors.toList()); - + // TODO: 组装PagedGridResult返回 return null; } @Override - public PagedGridResult getMyFollowVlogList(String myId, Integer page, Integer pageSize) { - Page pageParam = new Page<>(page, pageSize); + public PagedGridResult getMyFriendVlogList(SimpleListBO bo, Page page) { + int current = (int) page.getCurrent(); + int size = (int) page.getSize(); + Page pageParam = new Page<>(current, size); Map map = new HashMap<>(); - map.put("myId", myId); - List voList = vlogMapperCustom.getMyFollowVlogList(map); - return null; - } - - @Override - public PagedGridResult getMyFriendVlogList(String myId, Integer page, Integer pageSize) { - Page pageParam = new Page<>(page, pageSize); - Map map = new HashMap<>(); - map.put("myId", myId); + map.put("myId", bo.getMyId()); List voList = vlogMapperCustom.getMyFriendVlogList(map); + // TODO: 组装PagedGridResult返回 + return null; + } + @Override + public PagedGridResult getMyFollowVlogList(SimpleListBO bo, Page page) { + int current = (int) page.getCurrent(); + int size = (int) page.getSize(); + Page pageParam = new Page<>(current, size); + Map map = new HashMap<>(); + map.put("myId", bo.getMyId()); + List voList = vlogMapperCustom.getMyFollowVlogList(map); + // TODO: 组装PagedGridResult返回 return null; } diff --git a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/event/MessageEventListener.java b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/event/MessageEventListener.java index f4a497c46..846f4a11c 100644 --- a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/event/MessageEventListener.java +++ b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/event/MessageEventListener.java @@ -8,6 +8,7 @@ import org.dromara.system.domain.event.MessageEvent; import org.dromara.system.service.IRocketMQService; import org.dromara.system.service.ITencentIMService; import org.dromara.system.websocket.MessageWebSocketServer; +import org.dromara.system.service.impl.TencentIMServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.event.EventListener; @@ -125,13 +126,14 @@ public class MessageEventListener { } } else { // 默认为单用户推送 - tencentIMSendSuccess = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content); - } - - if (tencentIMSendSuccess) { - log.info("消息已成功发送到腾讯IM,接收者: {}", toUserId); - } else { - log.warn("发送消息到腾讯IM失败,将尝试通过其他方式发送"); + TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content); + tencentIMSendSuccess = imResult.isSuccess(); + if (tencentIMSendSuccess) { + log.info("腾讯IM推送成功,userId={}, response={}", toUserId, imResult.getRawResponse()); + } else { + log.warn("腾讯IM推送失败,userId={}, errorCode={}, errorInfo={}, response={}", + toUserId, imResult.getErrorCode(), imResult.getErrorInfo(), imResult.getRawResponse()); + } } } catch (Exception e) { log.error("发送消息到腾讯IM异常,将尝试通过其他方式发送", e); diff --git a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/ITencentIMService.java b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/ITencentIMService.java index b102aec66..42b5dec4d 100644 --- a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/ITencentIMService.java +++ b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/ITencentIMService.java @@ -2,6 +2,7 @@ package org.dromara.system.service; import java.util.List; import java.util.Map; +import org.dromara.system.service.impl.TencentIMServiceImpl; /** * 腾讯IM服务接口 @@ -18,7 +19,7 @@ public interface ITencentIMService { * @param content 消息内容 * @return 是否发送成功 */ - boolean sendMessageToTencentIM(String fromUserId, String toUserId, String content); + TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content); /** diff --git a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/impl/TencentIMServiceImpl.java b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/impl/TencentIMServiceImpl.java index deb5ad18e..8671306c7 100644 --- a/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/impl/TencentIMServiceImpl.java +++ b/ruoyi-modules/ruoyi-im/src/main/java/org/dromara/system/service/impl/TencentIMServiceImpl.java @@ -149,14 +149,32 @@ public class TencentIMServiceImpl implements ITencentIMService { return generateUserSig(adminAccount); } + // 新增结果对象 + public static class TencentIMResult { + private boolean success; + private String actionStatus; + private int errorCode; + private String errorInfo; + private String rawResponse; + // getter/setter + public boolean isSuccess() { return success; } + public void setSuccess(boolean success) { this.success = success; } + public String getActionStatus() { return actionStatus; } + public void setActionStatus(String actionStatus) { this.actionStatus = actionStatus; } + public int getErrorCode() { return errorCode; } + public void setErrorCode(int errorCode) { this.errorCode = errorCode; } + public String getErrorInfo() { return errorInfo; } + public void setErrorInfo(String errorInfo) { this.errorInfo = errorInfo; } + public String getRawResponse() { return rawResponse; } + public void setRawResponse(String rawResponse) { this.rawResponse = rawResponse; } + } @Override - public boolean sendMessageToTencentIM(String fromUserId, String toUserId, String content) { + public TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content) { + TencentIMResult result = new TencentIMResult(); try { String userSig = generateAdminUserSig(); String random = String.valueOf(new Random().nextInt(999999999)); - - // 构建API请求URL String url = String.format( "https://console.tim.qq.com/v4/openim/sendmsg" + "?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json", @@ -164,41 +182,34 @@ public class TencentIMServiceImpl implements ITencentIMService { adminAccount, userSig, random); - - // 构建消息内容 Map msgContent = new HashMap<>(); msgContent.put("Text", content); - - // 构建消息体 Map msgBody = new HashMap<>(); msgBody.put("MsgType", "TIMTextElem"); msgBody.put("MsgContent", msgContent); - - // 构建请求体 Map requestBody = new HashMap<>(); - requestBody.put("SyncOtherMachine", 2); // 消息不同步至发送方 + requestBody.put("SyncOtherMachine", 2); requestBody.put("From_Account", fromUserId); requestBody.put("To_Account", toUserId); requestBody.put("MsgRandom", Integer.parseInt(random)); requestBody.put("MsgBody", new Object[]{msgBody}); - - // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - - // 发送请求 HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); - + result.setRawResponse(response.getBody()); log.info("发送消息到腾讯IM结果: {}", response.getBody()); - - // 解析响应判断是否成功 - JSONObject responseJson = new JSONObject(response); - return "OK".equals(responseJson.getStr("ActionStatus")); + cn.hutool.json.JSONObject responseJson = new cn.hutool.json.JSONObject(response.getBody()); + result.setActionStatus(responseJson.getStr("ActionStatus")); + result.setErrorCode(responseJson.getInt("ErrorCode", -1)); + result.setErrorInfo(responseJson.getStr("ErrorInfo")); + result.setSuccess("OK".equals(result.getActionStatus()) && result.getErrorCode() == 0); } catch (Exception e) { log.error("发送消息到腾讯IM异常", e); - return false; + result.setSuccess(false); + result.setErrorInfo(e.getMessage()); } + return result; } @Override diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/FansController.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/FansController.java index c968d56ab..82ba574be 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/FansController.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/FansController.java @@ -25,7 +25,9 @@ import org.dromara.common.log.enums.BusinessType; import org.dromara.common.redis.utils.RedisUtils; import org.springframework.web.bind.annotation.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Slf4j @RequestMapping("/ums/fans/") @@ -85,67 +87,122 @@ public class FansController { return R.ok(service.removeById(id)); } - - - + // 提取IM关注处理逻辑为私有方法 + private void handleImFollow(Long myId, List vloggerIds) { + if (myId != null && vloggerIds != null) { + for (Long vloggerId : vloggerIds) { + service.doFollow(myId, vloggerId); + } + } + } @PostMapping("follow") - public R follow(@RequestParam Long myId, - @RequestParam Long vloggerId) { - - - // 判断两个id不能为空 - if (myId ==null|| vloggerId==null) { - return R.fail("id不能为空"); + public Object follow(@RequestBody(required = false) Map callbackData, + @RequestParam(required = false) Long myId, + @RequestParam(required = false) Long vloggerId) { + // 1. IM回调格式 + if (callbackData != null && callbackData.containsKey("CallbackCommand")) { + log.info("收到IM关注回调: {}", callbackData); + String fromAccount = (String) callbackData.get("From_Account"); + List> followList = (List>) callbackData.get("FollowList"); + if (fromAccount != null && followList != null) { + Long fromId = Long.valueOf(fromAccount.replace("UserID_", "")); + List vloggerIds = new java.util.ArrayList<>(); + for (Map follow : followList) { + String toAccount = follow.get("To_Account"); + vloggerIds.add(Long.valueOf(toAccount.replace("UserID_", ""))); + } + handleImFollow(fromId, vloggerIds); + log.info("IM回调处理成功: fromId={}, vloggerIds={}", fromId, vloggerIds); + } else { + log.warn("IM回调参数不完整: {}", callbackData); + } + Map resp = new HashMap<>(); + resp.put("ActionStatus", "OK"); + resp.put("ErrorCode", 0); + resp.put("ErrorInfo", ""); + return resp; } - // 获取拉黑数据 - boolean hasblock = memberBlockService.hasBlocked(myId, vloggerId); - if (hasblock) { - return R.fail("已经拉黑"); + // 2. 兼容JSON方式传递myId和vloggerId + if (callbackData != null && callbackData.containsKey("myId") && callbackData.containsKey("vloggerId")) { + log.info("收到JSON关注回调: {}", callbackData); + Object myIdObj = callbackData.get("myId"); + Object vloggerIdObj = callbackData.get("vloggerId"); + if (myIdObj != null && vloggerIdObj != null) { + Long myIdVal = Long.valueOf(myIdObj.toString()); + Long vloggerIdVal = Long.valueOf(vloggerIdObj.toString()); + handleImFollow(myIdVal, java.util.Arrays.asList(vloggerIdVal)); + log.info("JSON回调处理成功: myId={}, vloggerId={}", myIdVal, vloggerIdVal); + return R.ok("关注成功"); + } else { + log.warn("JSON回调参数不完整: {}", callbackData); + } } - // 判断当前用户,自己不能关注自己 - if (myId ==vloggerId) { - return R.fail("自己不能关注自己"); + // 3. 普通参数,自动组装成IM格式处理 + if (myId != null && vloggerId != null) { + log.info("收到参数关注回调: myId={}, vloggerId={}", myId, vloggerId); + handleImFollow(myId, java.util.Arrays.asList(vloggerId)); + log.info("参数回调处理成功: myId={}, vloggerId={}", myId, vloggerId); + return R.ok("关注成功"); } - // 是否已经存在关系 - boolean flow = service.queryDoIFollowVloger(myId, vloggerId); - if (flow) { - return R.fail("已经在关注列表里了"); - } - // 判断两个id对应的用户是否存在 - Member vlogger = memberService.getById(vloggerId); - Member myInfo = memberService.getById(myId); - if (myInfo == null || vlogger == null) { - return R.fail("用户不存在"); - } - // 保存粉丝关系到数据库 - service.doFollow(myId, vloggerId); - - // 博主的粉丝+1,我的关注+1 - RedisUtils.incrAtomicValue(CacheConstants.MEMBER_FANS + ":" + vloggerId); - RedisUtils.incrAtomicValue(CacheConstants.MEMBER_FOLLOW + ":" + myId); - return R.ok("关注成功"); + log.error("关注回调失败,参数为空: callbackData={}, myId={}, vloggerId={}", callbackData, myId, vloggerId); + return R.fail("id不能为空"); } @PostMapping("cancel") - public R cancel(@RequestParam Long myId, - @RequestParam Long vloggerId) { - // 判断两个id不能为空 - if ( myId==null || vloggerId==null) { + public Object cancel(@RequestBody(required = false) Map callbackData, + @RequestParam(required = false) Long myId, + @RequestParam(required = false) Long vloggerId) { + // 1. 判断是否为IM回调格式 + if (callbackData != null && callbackData.containsKey("CallbackCommand")) { + log.info("收到IM取消关注回调: {}", callbackData); + String fromAccount = (String) callbackData.get("From_Account"); + List toAccounts = null; + // 兼容腾讯IM的 To_Account 可能是 List 或 List> + Object toAccountObj = callbackData.get("To_Account"); + if (toAccountObj instanceof List) { + List list = (List) toAccountObj; + if (!list.isEmpty() && list.get(0) instanceof String) { + toAccounts = (List) list; + } else if (!list.isEmpty() && list.get(0) instanceof Map) { + // 兼容部分IM平台格式 + toAccounts = new java.util.ArrayList<>(); + for (Object obj : list) { + Map map = (Map) obj; + Object acc = map.get("To_Account"); + if (acc != null) toAccounts.add(acc.toString()); + } + } + } + if (fromAccount != null && toAccounts != null) { + Long fromId = Long.valueOf(fromAccount.replace("UserID_", "")); + for (String toAccount : toAccounts) { + Long toId = Long.valueOf(toAccount.replace("UserID_", "")); + service.doCancel(fromId, toId); + } + log.info("IM取消关注回调处理成功: fromId={}, toAccounts={}", fromId, toAccounts); + } else { + log.warn("IM取消关注回调参数不完整: {}", callbackData); + } + // 返回IM平台要求的应答 + Map resp = new HashMap<>(); + resp.put("ActionStatus", "OK"); + resp.put("ErrorCode", 0); + resp.put("ErrorInfo", ""); + return resp; + } + // 2. 原有取关逻辑 + if (myId == null || vloggerId == null) { return R.fail("id不能为空"); } - // 是否已经存在关系 boolean flow = service.queryDoIFollowVloger(myId, vloggerId); if (!flow) { return R.fail("没有关注信息"); } - // 删除业务的执行 service.doCancel(myId, vloggerId); - // 博主的粉丝-1,我的关注-1 RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FANS + ":" + vloggerId); RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FOLLOW + ":" + myId); - return R.ok("取消成功"); } diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java index 674917116..e35e45fe0 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java @@ -22,6 +22,10 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; +import java.util.HashMap; +import lombok.extern.slf4j.Slf4j; + /** * 会员信息Controller * @@ -31,6 +35,7 @@ import java.util.List; @Tag(name = "会员信息接口列表") @RequestMapping("/ums/member/") @RestController +@Slf4j public class MemberController extends BaseController { @Autowired private IMemberService service; @@ -76,8 +81,120 @@ public class MemberController extends BaseController { @SaCheckPermission("ums:member:edit") @Log(title = "会员信息", businessType = BusinessType.UPDATE) @PostMapping("update") - public R edit(@RequestBody MemberBO member) { - return R.ok(service.updateById(convert.toPo(member))); + public Object edit(@RequestBody(required = false) Map callbackData, + @RequestParam(required = false) Long id, + @RequestParam(required = false) String nickname, + @RequestParam(required = false) Integer gender) { + // 1. IM回调格式 - 用户资料更新回调 + if (callbackData != null && callbackData.containsKey("CallbackCommand")) { + log.info("收到IM用户资料更新回调: {}", callbackData); + String callbackCommand = (String) callbackData.get("CallbackCommand"); + if ("Profile.CallbackPortraitSet".equals(callbackCommand)) { + String fromAccount = (String) callbackData.get("From_Account"); + List> profileItems = (List>) callbackData.get("ProfileItem"); + if (fromAccount != null && profileItems != null) { + Long userId = Long.valueOf(fromAccount.replace("UserID_", "")); + // 根据 ProfileItem 更新用户资料 + Member memberToUpdate = service.getById(userId); + if (memberToUpdate != null) { + for (Map item : profileItems) { + String tag = (String) item.get("Tag"); + Object value = item.get("Value"); + updateMemberProfile(memberToUpdate, tag, value); + } + service.updateById(memberToUpdate); + log.info("IM用户资料更新回调处理成功: userId={}, profileItems={}", userId, profileItems); + } else { + log.warn("IM用户资料更新回调中用户不存在: userId={}", userId); + } + } else { + log.warn("IM用户资料更新回调参数不完整: {}", callbackData); + } + // 返回IM平台要求的应答 + Map resp = new HashMap<>(); + resp.put("ActionStatus", "OK"); + resp.put("ErrorCode", 0); + resp.put("ErrorInfo", ""); + return resp; + } + } + // 2. 兼容JSON方式传递参数 + if (callbackData != null && callbackData.containsKey("id")) { + log.info("收到JSON会员更新回调: {}", callbackData); + Object idObj = callbackData.get("id"); + Object nicknameObj = callbackData.get("nickname"); + Object genderObj = callbackData.get("gender"); + if (idObj != null) { + Long memberId = Long.valueOf(idObj.toString()); + Member memberToUpdate = service.getById(memberId); + if (memberToUpdate != null) { + if (nicknameObj != null) { + memberToUpdate.setNickname(nicknameObj.toString()); + } + if (genderObj != null) { + memberToUpdate.setGender(Integer.valueOf(genderObj.toString())); + } + service.updateById(memberToUpdate); + log.info("JSON会员更新回调处理成功: id={}, nickname={}, gender={}", memberId, nicknameObj, genderObj); + return R.ok("更新成功"); + } else { + log.warn("JSON会员更新回调中用户不存在: id={}", memberId); + } + } + } + // 3. 普通参数更新 + if (id != null) { + log.info("收到参数会员更新回调: id={}, nickname={}, gender={}", id, nickname, gender); + Member memberToUpdate = service.getById(id); + if (memberToUpdate != null) { + if (nickname != null) { + memberToUpdate.setNickname(nickname); + } + if (gender != null) { + memberToUpdate.setGender(gender); + } + service.updateById(memberToUpdate); + log.info("参数会员更新回调处理成功: id={}, nickname={}, gender={}", id, nickname, gender); + return R.ok("更新成功"); + } else { + log.warn("参数会员更新回调中用户不存在: id={}", id); + } + } + log.error("会员信息更新失败,参数为空: callbackData={}, id={}, nickname={}, gender={}", callbackData, id, nickname, gender); + return R.fail("参数不能为空"); + } + + /** + * 根据IM回调的ProfileItem更新用户资料 + */ + private void updateMemberProfile(Member member, String tag, Object value) { + if (tag == null || value == null) { + return; + } + switch (tag) { + case "Tag_Profile_IM_Nick": + member.setNickname(value.toString()); + break; + case "Tag_Profile_IM_Gender": + // 根据性别值设置性别字段 + if ("Gender_Type_Male".equals(value)) { + member.setGender(1); // 男 + } else if ("Gender_Type_Female".equals(value)) { + member.setGender(2); // 女 + } else { + member.setGender(0); // 未知 + } + break; + case "Tag_Profile_IM_AllowType": + // 处理好友验证方式 + break; + case "Tag_Profile_Custom_Data": + // 处理自定义数据 + break; + default: + log.debug("未处理的用户资料字段: tag={}, value={}", tag, value); + break; + } } @Tag(name ="修改会员备注信息") diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java index 0e8c62dc7..2431abb5d 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java @@ -97,14 +97,21 @@ public class FansServiceImpl extends ServiceImpl implements IF if (fan != null && YesOrNo.YES.type.equals(fan.getFriendFlag())) { // 抹除双方的朋友关系,自己的关系删除即可 Fans pendingFan = queryFansRelationship(vloggerId, myId); - pendingFan.setBothFriend(YesOrNo.NO.type); - baseMapper.updateById(pendingFan); + if (pendingFan != null) { + pendingFan.setBothFriend(YesOrNo.NO.type); + baseMapper.updateById(pendingFan); + } else { + log.warn("取消关注时未找到对方的粉丝关系,myId={}, vloggerId={}", vloggerId, myId); + } } - // 删除自己的关注关联表记录 - LambdaQueryWrapper deleteWrapper = new LambdaQueryWrapper<>(); - deleteWrapper.eq(Fans::getId, fan.getId()); - baseMapper.delete(deleteWrapper); + if (fan != null) { + LambdaQueryWrapper deleteWrapper = new LambdaQueryWrapper<>(); + deleteWrapper.eq(Fans::getId, fan.getId()); + baseMapper.delete(deleteWrapper); + } else { + log.warn("取消关注时未找到自己的粉丝关系,myId={}, vloggerId={}", myId, vloggerId); + } // 推送取关消息 Member follower = memberService.getById(myId); Member vlogger = memberService.getById(vloggerId);