修改回调代码

This commit is contained in:
曹佳豪 2025-07-10 09:27:53 +08:00
parent b09b6f7ece
commit bb812c2bbe
14 changed files with 420 additions and 280 deletions

View File

@ -17,6 +17,12 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import com.wzj.soopin.content.utils.RedisOperator; 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.*; import org.springframework.web.bind.annotation.*;
@ -167,23 +173,11 @@ public class VlogController extends BaseInfoProperties {
return R.ok(); return R.ok();
} }
@GetMapping("indexList") @Tag(name = "首页视频列表")
public R<PagedGridResult> indexList(@RequestParam(defaultValue = "") String userId, @PostMapping("/indexList")
@RequestParam(defaultValue = "") String search, public R<PagedGridResult> indexList(@RequestBody IndexListBO bo, @RequestBody Page page) {
@RequestParam(defaultValue = "") String cityCode, PagedGridResult pages = vlogService.getIndexVlogList(bo, page);
@RequestParam(defaultValue = "") String status, return R.ok(pages);
@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);
} }
@GetMapping("detail") @GetMapping("detail")
@ -219,66 +213,39 @@ public class VlogController extends BaseInfoProperties {
@GetMapping("myPublicList") @Tag(name = "我的公开视频列表")
public R<PagedGridResult> myPublicList(@RequestParam String userId, @PostMapping("/myPublicList")
@RequestParam(defaultValue = "") String myId, public R<PagedGridResult> myPublicList(@RequestBody MyListBO bo, @RequestBody Page page) {
@RequestParam Integer page, PagedGridResult pages = vlogService.queryMyVlogList(bo, page);
@RequestParam Integer pageSize) { return R.ok(pages);
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);
} }
@GetMapping("myPrivateList") @Tag(name = "我的私密视频列表")
public R<PagedGridResult> myPrivateList(@RequestParam String userId, @PostMapping("/myPrivateList")
@RequestParam(defaultValue = "") String myId, public R<PagedGridResult> myPrivateList(@RequestBody MyListBO bo, @RequestBody Page page) {
@RequestParam Integer page, PagedGridResult pages = vlogService.queryMyVlogList(bo, page);
@RequestParam Integer pageSize) { return R.ok(pages);
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);
} }
@GetMapping("myLikedList") @Tag(name = "我点赞的视频列表")
public R<PagedGridResult> myLikedList(@RequestParam String userId, @PostMapping("/myLikedList")
@RequestParam(defaultValue = "") String myId, public R<PagedGridResult> myLikedList(@RequestBody MyListBO bo, @RequestBody Page page) {
@RequestParam Integer page, PagedGridResult pages = vlogService.getMyLikedVlogList(bo, page);
@RequestParam Integer pageSize) { return R.ok(pages);
}
if (page == null) { @Tag(name = "我关注的视频列表")
page = COMMON_START_PAGE; @PostMapping("/followList")
} public R<PagedGridResult> followList(@RequestBody SimpleListBO bo, @RequestBody Page page) {
if (pageSize == null) { PagedGridResult pages = vlogService.getMyFollowVlogList(bo, page);
pageSize = COMMON_PAGE_SIZE; return R.ok(pages);
} }
PagedGridResult gridResult = vlogService.getMyLikedVlogList(userId, @Tag(name = "好友视频列表")
myId, @PostMapping("/friendList")
page, public R<PagedGridResult> friendList(@RequestBody SimpleListBO bo, @RequestBody Page page) {
pageSize); PagedGridResult pages = vlogService.getMyFriendVlogList(bo, page);
return R.ok(gridResult); return R.ok(pages);
} }
private Integer nacosConuts=0; private Integer nacosConuts=0;
@ -336,41 +303,4 @@ public class VlogController extends BaseInfoProperties {
return R.ok(vlogService.getVlogBeLikedCounts(vlogId)); return R.ok(vlogService.getVlogBeLikedCounts(vlogId));
} }
@GetMapping("followList")
public R<PagedGridResult> 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<PagedGridResult> 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);
}
} }

View File

@ -29,7 +29,7 @@ import java.util.Collections;
@Slf4j @Slf4j
@Api(tags = "管理端-评论管理接口") @Api(tags = "管理端-评论管理接口")
@RequestMapping("admin/comment") @RequestMapping("/comment")
@RestController @RestController
public class CommentController extends BaseController { public class CommentController extends BaseController {

View File

@ -28,8 +28,8 @@ import java.time.format.DateTimeFormatter;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@Slf4j @Slf4j
@Api(tags = "管理端-视频上传接口") @Api(tags = "管理端-视频")
@RequestMapping("admin/vlog/upload") @RequestMapping("/video")
@RestController @RestController
public class VlogUploadController extends BaseInfoProperties { public class VlogUploadController extends BaseInfoProperties {

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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.po.Vlog;
import com.wzj.soopin.content.domain.vo.IndexVlogVO; import com.wzj.soopin.content.domain.vo.IndexVlogVO;
import com.wzj.soopin.content.utils.PagedGridResult; 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.List;
import java.util.Map; import java.util.Map;
@ -28,12 +31,7 @@ public interface VlogService {
/** /**
* 查询首页/搜索的vlog列表 * 查询首页/搜索的vlog列表
*/ */
public PagedGridResult getIndexVlogList(String userId, public PagedGridResult getIndexVlogList(IndexListBO bo, Page page);
String search,
String cityCode,
String status,
Integer page,
Integer pageSize);
/** /**
* 根据视频主键查询vlog * 根据视频主键查询vlog
@ -53,11 +51,7 @@ public interface VlogService {
/** /**
* 查询用的公开/私密的视频列表 * 查询用的公开/私密的视频列表
*/ */
public PagedGridResult queryMyVlogList(String userId, public PagedGridResult queryMyVlogList(MyListBO bo, Page page);
String myId,
Integer page,
Integer pageSize,
Integer yesOrNo);
/** /**
* 用户点赞/喜欢视频 * 用户点赞/喜欢视频
@ -77,24 +71,17 @@ public interface VlogService {
/** /**
* 查询用户点赞过的短视频 * 查询用户点赞过的短视频
*/ */
public PagedGridResult getMyLikedVlogList(String userId, public PagedGridResult getMyLikedVlogList(MyListBO bo, Page page);
String myId,
Integer page,
Integer pageSize);
/** /**
* 查询用户关注的博主发布的短视频列表 * 查询用户关注的博主发布的短视频列表
*/ */
public PagedGridResult getMyFollowVlogList(String myId, public PagedGridResult getMyFollowVlogList(SimpleListBO bo, Page page);
Integer page,
Integer pageSize);
/** /**
* 查询朋友发布的短视频列表 * 查询朋友发布的短视频列表
*/ */
public PagedGridResult getMyFriendVlogList(String myId, public PagedGridResult getMyFriendVlogList(SimpleListBO bo, Page page);
Integer page,
Integer pageSize);
/** /**
* 根据主键查询vlog * 根据主键查询vlog

View File

@ -10,6 +10,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzj.soopin.content.domain.base.BaseInfoProperties; import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.domain.bo.VlogBO; 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.MyLikedVlog;
import com.wzj.soopin.content.domain.po.Vlog; import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.po.Users; import com.wzj.soopin.content.domain.po.Users;
@ -135,10 +138,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
@Override @Override
public PagedGridResult getIndexVlogList(String userId, String search, String cityCode, String status, Integer page, Integer pageSize) { public PagedGridResult getIndexVlogList(IndexListBO bo, Page page) {
Page<Vlog> pageParam = new Page<>(page, pageSize); 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<Vlog> pageParam = new Page<>(current, size);
LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(search)) { if (StringUtils.isNotBlank(search)) {
queryWrapper.like(Vlog::getTitle, search); queryWrapper.like(Vlog::getTitle, search);
} }
@ -148,7 +156,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
if (StringUtils.isNotBlank(status)) { if (StringUtils.isNotBlank(status)) {
queryWrapper.eq(Vlog::getStatus, status); queryWrapper.eq(Vlog::getStatus, status);
} }
// Handle blocked videos // Handle blocked videos
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
String redisKey = REDIS_VIDEO_BLOCK + ":" + userId; String redisKey = REDIS_VIDEO_BLOCK + ":" + userId;
@ -156,7 +163,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
List<String> blockVdList = new ArrayList<>(); List<String> blockVdList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
List<String> reports = redis.lrange(redisKey, 0, -1); List<String> reports = redis.lrange(redisKey, 0, -1);
for (String report : reports) { for (String report : reports) {
try { try {
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {}); Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
@ -171,7 +177,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
} }
} }
// Handle blocked users // Handle blocked users
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
String redisKey = REDIS_USER_BLOCK + ":" + userId; String redisKey = REDIS_USER_BLOCK + ":" + userId;
@ -179,7 +184,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
List<String> blockUserList = new ArrayList<>(); List<String> blockUserList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
List<String> reports = redis.lrange(redisKey, 0, -1); List<String> reports = redis.lrange(redisKey, 0, -1);
for (String report : reports) { for (String report : reports) {
try { try {
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {}); Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
@ -194,24 +198,19 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
} }
} }
Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper); Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
List<Vlog> vlogList = vlogPage.getRecords(); List<Vlog> vlogList = vlogPage.getRecords();
List<IndexVlogVO> voList = vlogList.stream().map(v -> { List<IndexVlogVO> voList = vlogList.stream().map(v -> {
IndexVlogVO vo = vlogConvert.toVO(v); IndexVlogVO vo = vlogConvert.toVO(v);
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(Long.valueOf(userId), Long.valueOf(v.getVlogerId()))); vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(Long.valueOf(userId), Long.valueOf(v.getVlogerId())));
vo.setDoILikeThisVlog(doILikeVlog(userId, v.getId())); vo.setDoILikeThisVlog(doILikeVlog(userId, v.getId()));
} }
vo.setLikeCounts(getVlogBeLikedCounts(v.getId())); vo.setLikeCounts(getVlogBeLikedCounts(v.getId()));
vo.setCommentsCounts(getVlogComment(v.getId())); vo.setCommentsCounts(getVlogComment(v.getId()));
return vo; return vo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
// TODO: 组装PagedGridResult返回
return null; return null;
} }
@ -278,29 +277,16 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
@Override @Override
public PagedGridResult queryMyVlogList(String userId, String myId, Integer page, Integer pageSize, Integer yesOrNo) { public PagedGridResult queryMyVlogList(MyListBO bo, Page page) {
Page<Vlog> pageParam = new Page<>(page, pageSize); int current = (int) page.getCurrent();
int size = (int) page.getSize();
Page<Vlog> pageParam = new Page<>(current, size);
LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Vlog::getVlogerId, userId) queryWrapper.eq(Vlog::getVlogerId, bo.getUserId())
.eq(Vlog::getIsPrivate, yesOrNo); .eq(Vlog::getIsPrivate, bo.getYesOrNo());
Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper); Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
List<Vlog> vlogList = vlogPage.getRecords(); List<Vlog> vlogList = vlogPage.getRecords();
// TODO: 组装PagedGridResult返回
List<IndexVlogVO> 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());
return null; return null;
} }
@ -378,52 +364,39 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
@Override @Override
public PagedGridResult getMyLikedVlogList(String userId, String myId, Integer page, Integer pageSize) { public PagedGridResult getMyLikedVlogList(MyListBO bo, Page page) {
Page<MyLikedVlog> pageParam = new Page<>(page, pageSize); int current = (int) page.getCurrent();
int size = (int) page.getSize();
Page<MyLikedVlog> pageParam = new Page<>(current, size);
LambdaQueryWrapper<MyLikedVlog> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<MyLikedVlog> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MyLikedVlog::getUserId, userId); queryWrapper.eq(MyLikedVlog::getUserId, bo.getUserId());
Page<MyLikedVlog> likedPage = myLikedVlogMapper.selectPage(pageParam, queryWrapper); Page<MyLikedVlog> likedPage = myLikedVlogMapper.selectPage(pageParam, queryWrapper);
List<MyLikedVlog> likedList = likedPage.getRecords(); List<MyLikedVlog> likedList = likedPage.getRecords();
// TODO: 组装PagedGridResult返回
List<IndexVlogVO> 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());
return null; return null;
} }
@Override @Override
public PagedGridResult getMyFollowVlogList(String myId, Integer page, Integer pageSize) { public PagedGridResult getMyFriendVlogList(SimpleListBO bo, Page page) {
Page<Vlog> pageParam = new Page<>(page, pageSize); int current = (int) page.getCurrent();
int size = (int) page.getSize();
Page<Vlog> pageParam = new Page<>(current, size);
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("myId", myId); map.put("myId", bo.getMyId());
List<IndexVlogVO> voList = vlogMapperCustom.getMyFollowVlogList(map);
return null;
}
@Override
public PagedGridResult getMyFriendVlogList(String myId, Integer page, Integer pageSize) {
Page<Vlog> pageParam = new Page<>(page, pageSize);
Map<String, Object> map = new HashMap<>();
map.put("myId", myId);
List<IndexVlogVO> voList = vlogMapperCustom.getMyFriendVlogList(map); List<IndexVlogVO> 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<Vlog> pageParam = new Page<>(current, size);
Map<String, Object> map = new HashMap<>();
map.put("myId", bo.getMyId());
List<IndexVlogVO> voList = vlogMapperCustom.getMyFollowVlogList(map);
// TODO: 组装PagedGridResult返回
return null; return null;
} }

View File

@ -8,6 +8,7 @@ import org.dromara.system.domain.event.MessageEvent;
import org.dromara.system.service.IRocketMQService; import org.dromara.system.service.IRocketMQService;
import org.dromara.system.service.ITencentIMService; import org.dromara.system.service.ITencentIMService;
import org.dromara.system.websocket.MessageWebSocketServer; 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.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
@ -125,13 +126,14 @@ public class MessageEventListener {
} }
} else { } else {
// 默认为单用户推送 // 默认为单用户推送
tencentIMSendSuccess = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content); TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content);
} tencentIMSendSuccess = imResult.isSuccess();
if (tencentIMSendSuccess) {
if (tencentIMSendSuccess) { log.info("腾讯IM推送成功userId={}, response={}", toUserId, imResult.getRawResponse());
log.info("消息已成功发送到腾讯IM接收者: {}", toUserId); } else {
} else { log.warn("腾讯IM推送失败userId={}, errorCode={}, errorInfo={}, response={}",
log.warn("发送消息到腾讯IM失败将尝试通过其他方式发送"); toUserId, imResult.getErrorCode(), imResult.getErrorInfo(), imResult.getRawResponse());
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error("发送消息到腾讯IM异常将尝试通过其他方式发送", e); log.error("发送消息到腾讯IM异常将尝试通过其他方式发送", e);

View File

@ -2,6 +2,7 @@ package org.dromara.system.service;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.dromara.system.service.impl.TencentIMServiceImpl;
/** /**
* 腾讯IM服务接口 * 腾讯IM服务接口
@ -18,7 +19,7 @@ public interface ITencentIMService {
* @param content 消息内容 * @param content 消息内容
* @return 是否发送成功 * @return 是否发送成功
*/ */
boolean sendMessageToTencentIM(String fromUserId, String toUserId, String content); TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content);
/** /**

View File

@ -149,14 +149,32 @@ public class TencentIMServiceImpl implements ITencentIMService {
return generateUserSig(adminAccount); 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 @Override
public boolean sendMessageToTencentIM(String fromUserId, String toUserId, String content) { public TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content) {
TencentIMResult result = new TencentIMResult();
try { try {
String userSig = generateAdminUserSig(); String userSig = generateAdminUserSig();
String random = String.valueOf(new Random().nextInt(999999999)); String random = String.valueOf(new Random().nextInt(999999999));
// 构建API请求URL
String url = String.format( String url = String.format(
"https://console.tim.qq.com/v4/openim/sendmsg" + "https://console.tim.qq.com/v4/openim/sendmsg" +
"?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json", "?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json",
@ -164,41 +182,34 @@ public class TencentIMServiceImpl implements ITencentIMService {
adminAccount, adminAccount,
userSig, userSig,
random); random);
// 构建消息内容
Map<String, Object> msgContent = new HashMap<>(); Map<String, Object> msgContent = new HashMap<>();
msgContent.put("Text", content); msgContent.put("Text", content);
// 构建消息体
Map<String, Object> msgBody = new HashMap<>(); Map<String, Object> msgBody = new HashMap<>();
msgBody.put("MsgType", "TIMTextElem"); msgBody.put("MsgType", "TIMTextElem");
msgBody.put("MsgContent", msgContent); msgBody.put("MsgContent", msgContent);
// 构建请求体
Map<String, Object> requestBody = new HashMap<>(); Map<String, Object> requestBody = new HashMap<>();
requestBody.put("SyncOtherMachine", 2); // 消息不同步至发送方 requestBody.put("SyncOtherMachine", 2);
requestBody.put("From_Account", fromUserId); requestBody.put("From_Account", fromUserId);
requestBody.put("To_Account", toUserId); requestBody.put("To_Account", toUserId);
requestBody.put("MsgRandom", Integer.parseInt(random)); requestBody.put("MsgRandom", Integer.parseInt(random));
requestBody.put("MsgBody", new Object[]{msgBody}); requestBody.put("MsgBody", new Object[]{msgBody});
// 设置请求头
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
// 发送请求
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers); HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
result.setRawResponse(response.getBody());
log.info("发送消息到腾讯IM结果: {}", response.getBody()); log.info("发送消息到腾讯IM结果: {}", response.getBody());
cn.hutool.json.JSONObject responseJson = new cn.hutool.json.JSONObject(response.getBody());
// 解析响应判断是否成功 result.setActionStatus(responseJson.getStr("ActionStatus"));
JSONObject responseJson = new JSONObject(response); result.setErrorCode(responseJson.getInt("ErrorCode", -1));
return "OK".equals(responseJson.getStr("ActionStatus")); result.setErrorInfo(responseJson.getStr("ErrorInfo"));
result.setSuccess("OK".equals(result.getActionStatus()) && result.getErrorCode() == 0);
} catch (Exception e) { } catch (Exception e) {
log.error("发送消息到腾讯IM异常", e); log.error("发送消息到腾讯IM异常", e);
return false; result.setSuccess(false);
result.setErrorInfo(e.getMessage());
} }
return result;
} }
@Override @Override

View File

@ -25,7 +25,9 @@ import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Slf4j @Slf4j
@RequestMapping("/ums/fans/") @RequestMapping("/ums/fans/")
@ -85,67 +87,122 @@ public class FansController {
return R.ok(service.removeById(id)); return R.ok(service.removeById(id));
} }
// 提取IM关注处理逻辑为私有方法
private void handleImFollow(Long myId, List<Long> vloggerIds) {
if (myId != null && vloggerIds != null) {
for (Long vloggerId : vloggerIds) {
service.doFollow(myId, vloggerId);
}
}
}
@PostMapping("follow") @PostMapping("follow")
public R<Object> follow(@RequestParam Long myId, public Object follow(@RequestBody(required = false) Map<String, Object> callbackData,
@RequestParam Long vloggerId) { @RequestParam(required = false) Long myId,
@RequestParam(required = false) Long vloggerId) {
// 1. IM回调格式
// 判断两个id不能为空 if (callbackData != null && callbackData.containsKey("CallbackCommand")) {
if (myId ==null|| vloggerId==null) { log.info("收到IM关注回调: {}", callbackData);
return R.fail("id不能为空"); String fromAccount = (String) callbackData.get("From_Account");
List<Map<String, String>> followList = (List<Map<String, String>>) callbackData.get("FollowList");
if (fromAccount != null && followList != null) {
Long fromId = Long.valueOf(fromAccount.replace("UserID_", ""));
List<Long> vloggerIds = new java.util.ArrayList<>();
for (Map<String, String> 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<String, Object> resp = new HashMap<>();
resp.put("ActionStatus", "OK");
resp.put("ErrorCode", 0);
resp.put("ErrorInfo", "");
return resp;
} }
// 获取拉黑数据 // 2. 兼容JSON方式传递myId和vloggerId
boolean hasblock = memberBlockService.hasBlocked(myId, vloggerId); if (callbackData != null && callbackData.containsKey("myId") && callbackData.containsKey("vloggerId")) {
if (hasblock) { log.info("收到JSON关注回调: {}", callbackData);
return R.fail("已经拉黑"); 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);
}
} }
// 判断当前用户自己不能关注自己 // 3. 普通参数自动组装成IM格式处理
if (myId ==vloggerId) { if (myId != null && vloggerId != null) {
return R.fail("自己不能关注自己"); log.info("收到参数关注回调: myId={}, vloggerId={}", myId, vloggerId);
handleImFollow(myId, java.util.Arrays.asList(vloggerId));
log.info("参数回调处理成功: myId={}, vloggerId={}", myId, vloggerId);
return R.ok("关注成功");
} }
// 是否已经存在关系 log.error("关注回调失败,参数为空: callbackData={}, myId={}, vloggerId={}", callbackData, myId, vloggerId);
boolean flow = service.queryDoIFollowVloger(myId, vloggerId); return R.fail("id不能为空");
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("关注成功");
} }
@PostMapping("cancel") @PostMapping("cancel")
public R<Object> cancel(@RequestParam Long myId, public Object cancel(@RequestBody(required = false) Map<String, Object> callbackData,
@RequestParam Long vloggerId) { @RequestParam(required = false) Long myId,
// 判断两个id不能为空 @RequestParam(required = false) Long vloggerId) {
if ( myId==null || vloggerId==null) { // 1. 判断是否为IM回调格式
if (callbackData != null && callbackData.containsKey("CallbackCommand")) {
log.info("收到IM取消关注回调: {}", callbackData);
String fromAccount = (String) callbackData.get("From_Account");
List<String> toAccounts = null;
// 兼容腾讯IM的 To_Account 可能是 List<String> List<Map<String, String>>
Object toAccountObj = callbackData.get("To_Account");
if (toAccountObj instanceof List) {
List<?> list = (List<?>) toAccountObj;
if (!list.isEmpty() && list.get(0) instanceof String) {
toAccounts = (List<String>) 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<String, Object> 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不能为空"); return R.fail("id不能为空");
} }
// 是否已经存在关系
boolean flow = service.queryDoIFollowVloger(myId, vloggerId); boolean flow = service.queryDoIFollowVloger(myId, vloggerId);
if (!flow) { if (!flow) {
return R.fail("没有关注信息"); return R.fail("没有关注信息");
} }
// 删除业务的执行
service.doCancel(myId, vloggerId); service.doCancel(myId, vloggerId);
// 博主的粉丝-1我的关注-1 // 博主的粉丝-1我的关注-1
RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FANS + ":" + vloggerId); RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FANS + ":" + vloggerId);
RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FOLLOW + ":" + myId); RedisUtils.decrAtomicValue(CacheConstants.MEMBER_FOLLOW + ":" + myId);
return R.ok("取消成功"); return R.ok("取消成功");
} }

View File

@ -22,6 +22,10 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.HashMap;
import lombok.extern.slf4j.Slf4j;
/** /**
* 会员信息Controller * 会员信息Controller
* *
@ -31,6 +35,7 @@ import java.util.List;
@Tag(name = "会员信息接口列表") @Tag(name = "会员信息接口列表")
@RequestMapping("/ums/member/") @RequestMapping("/ums/member/")
@RestController @RestController
@Slf4j
public class MemberController extends BaseController { public class MemberController extends BaseController {
@Autowired @Autowired
private IMemberService service; private IMemberService service;
@ -76,8 +81,120 @@ public class MemberController extends BaseController {
@SaCheckPermission("ums:member:edit") @SaCheckPermission("ums:member:edit")
@Log(title = "会员信息", businessType = BusinessType.UPDATE) @Log(title = "会员信息", businessType = BusinessType.UPDATE)
@PostMapping("update") @PostMapping("update")
public R edit(@RequestBody MemberBO member) { public Object edit(@RequestBody(required = false) Map<String, Object> callbackData,
return R.ok(service.updateById(convert.toPo(member))); @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<Map<String, Object>> profileItems = (List<Map<String, Object>>) 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<String, Object> 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<String, Object> 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 ="修改会员备注信息") @Tag(name ="修改会员备注信息")

View File

@ -97,14 +97,21 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
if (fan != null && YesOrNo.YES.type.equals(fan.getFriendFlag())) { if (fan != null && YesOrNo.YES.type.equals(fan.getFriendFlag())) {
// 抹除双方的朋友关系自己的关系删除即可 // 抹除双方的朋友关系自己的关系删除即可
Fans pendingFan = queryFansRelationship(vloggerId, myId); Fans pendingFan = queryFansRelationship(vloggerId, myId);
pendingFan.setBothFriend(YesOrNo.NO.type); if (pendingFan != null) {
baseMapper.updateById(pendingFan); pendingFan.setBothFriend(YesOrNo.NO.type);
baseMapper.updateById(pendingFan);
} else {
log.warn("取消关注时未找到对方的粉丝关系myId={}, vloggerId={}", vloggerId, myId);
}
} }
// 删除自己的关注关联表记录 // 删除自己的关注关联表记录
LambdaQueryWrapper<Fans> deleteWrapper = new LambdaQueryWrapper<>(); if (fan != null) {
deleteWrapper.eq(Fans::getId, fan.getId()); LambdaQueryWrapper<Fans> deleteWrapper = new LambdaQueryWrapper<>();
baseMapper.delete(deleteWrapper); deleteWrapper.eq(Fans::getId, fan.getId());
baseMapper.delete(deleteWrapper);
} else {
log.warn("取消关注时未找到自己的粉丝关系myId={}, vloggerId={}", myId, vloggerId);
}
// 推送取关消息 // 推送取关消息
Member follower = memberService.getById(myId); Member follower = memberService.getById(myId);
Member vlogger = memberService.getById(vloggerId); Member vlogger = memberService.getById(vloggerId);