|
@@ -0,0 +1,772 @@
|
|
|
+package com.zhentao.moment.service.impl;
|
|
|
+
|
|
|
+import com.aliyun.oss.OSSClient;
|
|
|
+import com.aliyun.oss.model.ObjectMetadata;
|
|
|
+import com.aliyun.oss.model.PutObjectRequest;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.zhentao.moment.domain.MomentComments;
|
|
|
+import com.zhentao.moment.domain.MomentLikes;
|
|
|
+import com.zhentao.moment.domain.UserMoments;
|
|
|
+import com.zhentao.moment.dto.CommentsDto;
|
|
|
+import com.zhentao.moment.dto.MonmentDto;
|
|
|
+import com.zhentao.moment.enums.ContentTypeEnum;
|
|
|
+import com.zhentao.moment.mapper.MomentCommentsMapper;
|
|
|
+import com.zhentao.moment.mapper.MomentLikesMapper;
|
|
|
+import com.zhentao.moment.service.UserMomentsService;
|
|
|
+import com.zhentao.moment.mapper.UserMomentsMapper;
|
|
|
+import com.zhentao.osspicture.OssConfig;
|
|
|
+import com.zhentao.osspicture.OssUtil;
|
|
|
+import com.zhentao.tool.TokenUtils;
|
|
|
+import com.zhentao.user.domain.UserLogin;
|
|
|
+import com.zhentao.user.mapper.UserLoginMapper;
|
|
|
+import com.zhentao.userRelationships.domain.UserRelationships;
|
|
|
+import com.zhentao.userRelationships.mapper.UserRelationshipsMapper;
|
|
|
+import com.zhentao.utils.SensitiveWordFilter;
|
|
|
+import com.zhentao.utils.SnowflakeUtil;
|
|
|
+import com.zhentao.vo.Result;
|
|
|
+import io.jsonwebtoken.Claims;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
+
|
|
|
+/**
|
|
|
+* @author 86159
|
|
|
+* @description 针对表【user_moments(朋友圈动态表)】的数据库操作Service实现
|
|
|
+* @createDate 2025-06-04 11:56:59
|
|
|
+*/
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class UserMomentsServiceImpl extends ServiceImpl<UserMomentsMapper, UserMoments>
|
|
|
+ implements UserMomentsService{
|
|
|
+ @Autowired
|
|
|
+ private UserMomentsMapper userMomentsMapper;
|
|
|
+ @Autowired
|
|
|
+ private UserLoginMapper userLoginMapper;
|
|
|
+ @Autowired
|
|
|
+ private MomentLikesMapper momentLikesMapper;
|
|
|
+ @Autowired
|
|
|
+ private OssUtil ossUtil;
|
|
|
+ @Autowired
|
|
|
+ private OssConfig ossConfig;
|
|
|
+ @Autowired
|
|
|
+ private UserRelationshipsMapper userRelationshipsMapper;
|
|
|
+ @Autowired
|
|
|
+ private MomentCommentsMapper momentCommentsMapper;
|
|
|
+ // 发送朋友圈
|
|
|
+ @Override
|
|
|
+ public Result sendMonment(String token,MonmentDto monmentDto) {
|
|
|
+ if (monmentDto.getContent()==null){
|
|
|
+ return Result.error(400,"请输入内容");
|
|
|
+ }
|
|
|
+ if (monmentDto.getContentType()==null){
|
|
|
+ return Result.error(400,"内容类型不能为空");
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ UserMoments userMoments=new UserMoments();
|
|
|
+ userMoments.setMomentId(SnowflakeUtil.nextId());
|
|
|
+ String userId = TokenUtils.getUserIdFromToken(token);
|
|
|
+ userMoments.setUserId(Long.valueOf(userId));
|
|
|
+ String filter = SensitiveWordFilter.filter(monmentDto.getContent());
|
|
|
+ userMoments.setContent(filter);
|
|
|
+ Integer typeCode = monmentDto.getContentType();
|
|
|
+ System.err.println(typeCode);
|
|
|
+ ContentTypeEnum type = ContentTypeEnum.getByCodeOrThrow(typeCode);
|
|
|
+ userMoments.setContentType(typeCode);
|
|
|
+ if (monmentDto.getFiles()!=null && !monmentDto.getFiles().isEmpty()){
|
|
|
+// if (type!=ContentTypeEnum.IMAGE){
|
|
|
+// return Result.error(400,"只有图片类型支持上传多张");
|
|
|
+// }
|
|
|
+
|
|
|
+ switch (type){
|
|
|
+ case IMAGE:
|
|
|
+ for (MultipartFile file : monmentDto.getFiles()){
|
|
|
+ if (file.isEmpty()){
|
|
|
+ return Result.error(400,"图片不能为空");
|
|
|
+ }
|
|
|
+ validateImageContent(file);
|
|
|
+ }
|
|
|
+ List<String> imageUrls = new ArrayList<>();
|
|
|
+ List<String> imageNames = new ArrayList<>();
|
|
|
+ Long totalSize = 0L;
|
|
|
+ String imageDir = ossConfig.getUpload().getImage().getDir();
|
|
|
+ for (MultipartFile file : monmentDto.getFiles()){
|
|
|
+ String imageFileName = userId + "/" + System.currentTimeMillis() +
|
|
|
+ getFileExtension(file.getOriginalFilename());
|
|
|
+ String ossFilePath = imageDir + imageFileName;
|
|
|
+// 上传OSS
|
|
|
+ String url = uploadToOss(file, ossFilePath);
|
|
|
+ imageUrls.add(url);
|
|
|
+ imageNames.add(file.getOriginalFilename());
|
|
|
+ totalSize+=file.getSize();
|
|
|
+ }
|
|
|
+ String urlJson = "[" + imageUrls.stream()
|
|
|
+ .map(url -> "\"" + url.replace("\"", "\\\"") + "\"") // 确保URL中的双引号被转义
|
|
|
+ .collect(Collectors.joining(",")) + "]";
|
|
|
+ userMoments.setUrl(urlJson);
|
|
|
+ String nameJson = "[" + imageNames.stream()
|
|
|
+ .map(name -> "\"" + name.replace("\"", "\\\"") + "\"")
|
|
|
+ .collect(Collectors.joining(",")) + "]";
|
|
|
+ userMoments.setFilename(nameJson);
|
|
|
+ userMoments.setFilesize(totalSize);
|
|
|
+
|
|
|
+ break;
|
|
|
+ case VIDEO:
|
|
|
+ MultipartFile videoFile = monmentDto.getFiles().get(0);
|
|
|
+ if (videoFile.isEmpty()){
|
|
|
+ return Result.error(400,"视频不能为空");
|
|
|
+ }
|
|
|
+ validateVideoContent(videoFile);
|
|
|
+ String videoDir = ossConfig.getUpload().getVideo().getDir();
|
|
|
+ String videoFileName = userId + "/" + System.currentTimeMillis() +
|
|
|
+ getFileExtension(videoFile.getOriginalFilename());
|
|
|
+ String ossFilePath = videoDir + videoFileName;
|
|
|
+ String url = uploadToOss(videoFile, ossFilePath);
|
|
|
+
|
|
|
+ userMoments.setUrl(url);
|
|
|
+
|
|
|
+ userMoments.setFilename(videoFile.getOriginalFilename());
|
|
|
+ userMoments.setFilesize(videoFile.getSize());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return Result.error(400,"内容类型错误");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (type!=ContentTypeEnum.TEXT){
|
|
|
+ return Result.ERR(null,"类型上传不正确");
|
|
|
+ }
|
|
|
+//// userMoments.setContentType();
|
|
|
+// userMoments.setContent(monmentDto.getContent());
|
|
|
+ userMoments.setVisibility(monmentDto.getVisible());
|
|
|
+ userMoments.setLocation(monmentDto.getLocation());
|
|
|
+ userMoments.setMomentId(SnowflakeUtil.nextId());
|
|
|
+ userMomentsMapper.insert(userMoments);
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
+ map.put("monmentId",userMoments.getMomentId());
|
|
|
+ map.put("ossFilePath",userMoments.getUrl());
|
|
|
+ return Result.OK(map,"发送成功");
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ return Result.error(500,"发送失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // 删除朋友圈
|
|
|
+ @Override
|
|
|
+ public Result deleteMonment(String token,MonmentDto monmentDto) {
|
|
|
+ if (monmentDto.getMomentId()==null){
|
|
|
+ return Result.error(400,"朋友圈id不能为空");
|
|
|
+ }
|
|
|
+ Long userId = Long.valueOf(TokenUtils.getUserIdFromToken(token));
|
|
|
+ UserMoments userMoments = userMomentsMapper.selectById(monmentDto.getMomentId());
|
|
|
+ if (userMoments.getMomentId()==null){
|
|
|
+ return Result.error(400,"没有此朋友圈");
|
|
|
+ }else{
|
|
|
+ if (!userId.equals(userMoments.getUserId())){
|
|
|
+ return Result.error(400,"没有权限");
|
|
|
+ }
|
|
|
+ userMomentsMapper.deleteById(monmentDto.getMomentId());
|
|
|
+ return Result.ERR(200,"删除成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // 查询个人信息
|
|
|
+ @Override
|
|
|
+ public Result userinfo(String token) {
|
|
|
+ String userId = TokenUtils.getUserIdFromToken(token);
|
|
|
+ if (userId==null){
|
|
|
+ return Result.error(400,"没有userid");
|
|
|
+ }
|
|
|
+ UserLogin userLogin = userLoginMapper.selectById(userId);
|
|
|
+ return Result.OK(userLogin,"查询成功");
|
|
|
+ }
|
|
|
+ // 查询我的朋友圈
|
|
|
+ @Override
|
|
|
+ public Result getMyMonment(Long userId) {
|
|
|
+ QueryWrapper<UserMoments> queryWrapper=new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("user_id",userId);
|
|
|
+ queryWrapper.orderByDesc("created_at");
|
|
|
+ UserLogin userLogin = userLoginMapper.selectById(userId);
|
|
|
+ List<UserMoments> userMoments = userMomentsMapper.selectList(queryWrapper);
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
+ map.put("userMoments",userMoments);
|
|
|
+ map.put("userLogin",userLogin);
|
|
|
+ return Result.OK(map,"查询成功");
|
|
|
+ }
|
|
|
+ // 查询好友的朋友圈
|
|
|
+ @Override
|
|
|
+ public Result getFriendMonment(Long userId) {
|
|
|
+ log.info("查询好友朋友圈,用户ID: {}", userId);
|
|
|
+
|
|
|
+ // 构建查询条件,只查询user_id=userId的好友关系
|
|
|
+ QueryWrapper<UserRelationships> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("user_id", userId)
|
|
|
+ .eq("status", 1)
|
|
|
+ .eq("is_blacklist", 0)
|
|
|
+ .eq("is_del", 0)
|
|
|
+ .eq("is_moments", 0)
|
|
|
+ .orderByDesc("created_at");
|
|
|
+
|
|
|
+ // 查询好友关系
|
|
|
+ List<UserRelationships> userRelationships = userRelationshipsMapper.selectList(queryWrapper);
|
|
|
+ log.info("查询到的好友关系数量: {}", userRelationships.size());
|
|
|
+
|
|
|
+ // 调试:打印查询到的每条好友关系
|
|
|
+ for (UserRelationships rel : userRelationships) {
|
|
|
+ log.info("好友关系: user_id={}, friend_id={}, status={}, is_blacklist={}, is_del={}, is_moments={}",
|
|
|
+ rel.getUserId(), rel.getFriendId(), rel.getStatus(),
|
|
|
+ rel.getIsBlacklist(), rel.getIsDel(), rel.getIsMoments());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取好友ID(单向查询:直接从friend_id获取)
|
|
|
+ List<Long> friendIds = userRelationships.stream()
|
|
|
+ .map(UserRelationships::getFriendId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 处理无好友情况
|
|
|
+ if (friendIds.isEmpty()) {
|
|
|
+ log.warn("没有找到好友,返回空结果");
|
|
|
+ return Result.OK(new ArrayList<>(), "没有好友的朋友圈");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询好友的朋友圈
|
|
|
+ QueryWrapper<UserMoments> momentQuery = new QueryWrapper<>();
|
|
|
+ momentQuery.in("user_id", friendIds)
|
|
|
+ .ne("visibility",2)
|
|
|
+ .orderByDesc("created_at");
|
|
|
+ List<UserMoments> userMoments = userMomentsMapper.selectList(momentQuery);
|
|
|
+
|
|
|
+ // 关联用户信息
|
|
|
+ // 1. 提取朋友圈中所有不同的userId
|
|
|
+ Set<Long> userIdsInMoments = userMoments.stream()
|
|
|
+ .map(UserMoments::getUserId)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 2. 根据userId列表查询用户信息
|
|
|
+ if (userIdsInMoments.isEmpty()) {
|
|
|
+ log.warn("好友没有发布任何朋友圈");
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("userMoments", Collections.emptyList());
|
|
|
+ map.put("userList", Collections.emptyList());
|
|
|
+ return Result.OK(map, "查询成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ QueryWrapper<UserLogin> userQuery = new QueryWrapper<>();
|
|
|
+ userQuery.in("id", userIdsInMoments);
|
|
|
+ List<UserLogin> users = userLoginMapper.selectList(userQuery);
|
|
|
+
|
|
|
+ // 3. 将用户信息转换为Map,根据userId查找
|
|
|
+ Map<Long, UserLogin> userMap = users.stream()
|
|
|
+ .collect(Collectors.toMap(UserLogin::getId, user -> user));
|
|
|
+
|
|
|
+ // 4. 包含用户信息的列表
|
|
|
+ List<Map<String, Object>> userList = userMoments.stream()
|
|
|
+ .map(moment -> {
|
|
|
+ Map<String, Object> momentMap = new HashMap<>();
|
|
|
+ BeanUtils.copyProperties(moment, momentMap);
|
|
|
+
|
|
|
+ UserLogin user = userMap.get(moment.getUserId());
|
|
|
+ if (user != null) {
|
|
|
+ momentMap.put("nickName", user.getNickName());
|
|
|
+ momentMap.put("avatar", user.getAvatar());
|
|
|
+ }
|
|
|
+ return momentMap;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.info("查询到的朋友圈数量: {}", userMoments.size());
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("userMoments", userMoments);
|
|
|
+ map.put("userList", userList);
|
|
|
+ return Result.OK(map, "查询成功");
|
|
|
+ }
|
|
|
+ // 点赞朋友圈
|
|
|
+ @Override
|
|
|
+ public Result likeMonment(Long uid, MonmentDto monmentDto) {
|
|
|
+ System.err.println("赞"+monmentDto.getMomentId());
|
|
|
+ if (monmentDto.getMomentId()==null){
|
|
|
+ return Result.error(400,"请选择要点赞的朋友圈");
|
|
|
+ }
|
|
|
+ QueryWrapper<MomentLikes> queryWrapper=new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("moment_id",monmentDto.getMomentId());
|
|
|
+ queryWrapper.eq("user_id",uid);
|
|
|
+ // 查询是否已点赞
|
|
|
+ MomentLikes momentLikes = momentLikesMapper.selectOne(queryWrapper);
|
|
|
+ if (momentLikes==null){
|
|
|
+ // 没有点赞
|
|
|
+ MomentLikes momentLikes1=new MomentLikes();
|
|
|
+ momentLikes1.setLikeId(SnowflakeUtil.nextId());
|
|
|
+ momentLikes1.setMomentId(Long.valueOf(monmentDto.getMomentId()));
|
|
|
+ momentLikes1.setUserId(uid);
|
|
|
+ momentLikesMapper.insert(momentLikes1);
|
|
|
+ return Result.OK(200,"点赞成功");
|
|
|
+ }else{
|
|
|
+ // 已点赞
|
|
|
+ momentLikesMapper.delete(queryWrapper);
|
|
|
+ return Result.error(400,"取消点赞");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 评论朋友圈
|
|
|
+ @Override
|
|
|
+ public Result commentsMonment(Long userId, CommentsDto commentsDto) {
|
|
|
+ System.err.println("轮"+commentsDto.getMomentId());
|
|
|
+ MomentComments momentComments = new MomentComments();
|
|
|
+ momentComments.setUserId(userId);
|
|
|
+ momentComments.setCommentId(SnowflakeUtil.nextId());
|
|
|
+ UserMoments userMoments = userMomentsMapper.selectById(commentsDto.getMomentId());
|
|
|
+ System.err.println(userMoments);
|
|
|
+ if (userMoments==null){
|
|
|
+ return Result.error(400,"朋友圈不存在");
|
|
|
+ }
|
|
|
+ if (commentsDto.getContent()==null){
|
|
|
+ return Result.error(400,"评论不能为空");
|
|
|
+ }
|
|
|
+ commentsDto.setReplyTo(Long.valueOf(commentsDto.getMomentId()));
|
|
|
+ commentsDto.setReplyToUser(userMoments.getUserId());
|
|
|
+ momentComments.setMomentId(Long.valueOf(commentsDto.getMomentId()));
|
|
|
+ momentComments.setContent(commentsDto.getContent());
|
|
|
+ momentComments.setReplyToUser(commentsDto.getReplyToUser());
|
|
|
+ momentComments.setReplyTo(commentsDto.getReplyTo());
|
|
|
+ momentCommentsMapper.insert(momentComments);
|
|
|
+ return Result.OK(200,"评论成功");
|
|
|
+ }
|
|
|
+ // 查询点赞列表
|
|
|
+ @Override
|
|
|
+ public Result likeList(Long uid, MonmentDto monmentDto) {
|
|
|
+ if (monmentDto.getMomentId()==null){
|
|
|
+ return Result.error(400,"朋友圈id不能为空");
|
|
|
+ }
|
|
|
+ QueryWrapper<MomentLikes> queryWrapper=new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("moment_id",monmentDto.getMomentId());
|
|
|
+ List<MomentLikes> momentLikes = momentLikesMapper.selectList(queryWrapper);
|
|
|
+// 如果没有点赞
|
|
|
+ if (CollectionUtils.isEmpty(momentLikes)){
|
|
|
+ Map<String,Object> map = new HashMap<>();
|
|
|
+ map.put("likeList", Collections.emptyList());
|
|
|
+ map.put("userList", Collections.emptyList());
|
|
|
+ map.put("total", 0);
|
|
|
+ return Result.OK(map, "查询成功,暂无点赞数据");
|
|
|
+ }
|
|
|
+ // 提取去重后的用户ID列表
|
|
|
+ List<Long> userIds = momentLikes.stream()
|
|
|
+ .map(MomentLikes::getUserId)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<Long> userLikes=new ArrayList<>();
|
|
|
+ for (MomentLikes like:momentLikes){
|
|
|
+ userLikes.add(like.getUserId());
|
|
|
+ }
|
|
|
+ // 查询用户信息(需恢复此功能)
|
|
|
+ List<UserLogin> userLogins = userLoginMapper.selectBatchIds(userIds);
|
|
|
+ Map<Long, UserLogin> userMap = userLogins.stream()
|
|
|
+ .collect(Collectors.toMap(UserLogin::getId, user -> user));
|
|
|
+
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("likeList",momentLikes);
|
|
|
+ map.put("userList",userLogins);
|
|
|
+ return Result.OK(map,"查询成功");
|
|
|
+ }
|
|
|
+ // 查询评论列表
|
|
|
+ @Override
|
|
|
+ public Result commentList(Long valueOf, CommentsDto commentsDto) {
|
|
|
+ QueryWrapper<MomentComments> queryWrapper=new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("moment_id",commentsDto.getMomentId());
|
|
|
+ queryWrapper.orderByDesc("created_at");
|
|
|
+ List<MomentComments> momentComments = momentCommentsMapper.selectList(queryWrapper);
|
|
|
+// 查询朋友圈发布者信息
|
|
|
+ UserMoments userMoments = userMomentsMapper.selectById(commentsDto.getMomentId());
|
|
|
+ Long publisherId = null;
|
|
|
+ if (userMoments!=null){
|
|
|
+ publisherId = userMoments.getUserId();
|
|
|
+ }
|
|
|
+ List<Long> replyToUserIds=new ArrayList<>(); //存储每条评论的replyToUser
|
|
|
+ List<Long> replyToMomentIds=new ArrayList<>(); //存储每条评论的朋友圈id
|
|
|
+ List<String> userUsernames=new ArrayList<>();
|
|
|
+ for (MomentComments comment:momentComments){
|
|
|
+ UserLogin user = userLoginMapper.selectById(comment.getUserId());
|
|
|
+ if (user!=null){
|
|
|
+ userUsernames.add(user.getUserUsername());
|
|
|
+ }
|
|
|
+ // 设置replyTo和replyToUser
|
|
|
+ if (comment.getReplyTo() == null) {
|
|
|
+ // 如果当前评论没有回复目标(直接评论朋友圈)
|
|
|
+ replyToMomentIds.add(comment.getMomentId()); // replyTo设为当前朋友圈ID
|
|
|
+ replyToUserIds.add(publisherId); // replyToUser设为朋友圈发布者ID
|
|
|
+ } else {
|
|
|
+ // 如果当前评论是回复其他评论
|
|
|
+ replyToMomentIds.add(comment.getReplyTo()); // replyTo设为被回复的评论ID
|
|
|
+ replyToUserIds.add(comment.getReplyToUser()); // replyToUser设为被回复的用户ID
|
|
|
+ }
|
|
|
+ }
|
|
|
+ commentsDto.setUserUsernames(userUsernames);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("commentList",momentComments);
|
|
|
+ map.put("usernames",userUsernames);
|
|
|
+ map.put("replyToUserIds", replyToUserIds); // 添加replyToUser
|
|
|
+ map.put("replyToMomentIds", replyToMomentIds); // 添加replyTo
|
|
|
+ return Result.OK(map,"查询成功");
|
|
|
+ }
|
|
|
+ // 更改朋友圈背景图
|
|
|
+ @Override
|
|
|
+ public Result updateBackground(Long userId, MultipartFile file) throws IOException {
|
|
|
+ String ossUrl = ossUtil.uploadFile(file);
|
|
|
+ UserLogin userLogin=new UserLogin();
|
|
|
+ userLogin.setId(userId);
|
|
|
+ userLogin.setLabelList(ossUrl);
|
|
|
+ userLoginMapper.updateById(userLogin);
|
|
|
+ return Result.OK(ossUrl,"修改成功");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Result allListPage(Long userId, MonmentDto monmentDto) {
|
|
|
+ try {
|
|
|
+ // 1. 校验用户ID
|
|
|
+ if (userId == null) {
|
|
|
+ return Result.error(400, "用户ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询个人信息
|
|
|
+ UserLogin userLogin = userLoginMapper.selectById(userId);
|
|
|
+ if (userLogin == null) {
|
|
|
+ return Result.error(404, "用户信息不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 查询好友关系
|
|
|
+ QueryWrapper<UserRelationships> friendRelQuery = new QueryWrapper<>();
|
|
|
+ friendRelQuery.eq("user_id", userId)
|
|
|
+ .eq("status", 1)
|
|
|
+ .eq("is_blacklist", 0)
|
|
|
+ .eq("is_del", 0)
|
|
|
+ .eq("is_moments", 0)
|
|
|
+ .orderByDesc("created_at");
|
|
|
+ List<UserRelationships> friendRelationships = userRelationshipsMapper.selectList(friendRelQuery);
|
|
|
+ List<Long> friendIds = friendRelationships.stream()
|
|
|
+ .map(UserRelationships::getFriendId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 4. 合并查询当前用户和好友的动态
|
|
|
+ Page<UserMoments> allMomentsPage = new Page<>(monmentDto.getCurrentPage(), monmentDto.getPageSize());
|
|
|
+ QueryWrapper<UserMoments> allMomentQuery = new QueryWrapper<>();
|
|
|
+
|
|
|
+ // 如果有好友,查询自己和好友的动态;否则只查询自己的
|
|
|
+ if (!friendIds.isEmpty()) {
|
|
|
+ allMomentQuery.in("user_id", Stream.concat(
|
|
|
+ Stream.of(userId),
|
|
|
+ friendIds.stream()
|
|
|
+ ).collect(Collectors.toList()));
|
|
|
+ } else {
|
|
|
+ allMomentQuery.eq("user_id", userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排除仅自己可见的动态(除了自己发布的)
|
|
|
+ allMomentQuery.and(wrapper ->
|
|
|
+ wrapper.eq("user_id", userId)
|
|
|
+ .or()
|
|
|
+ .ne("visibility", 2)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 按创建时间降序排列
|
|
|
+ allMomentQuery.orderByDesc("created_at");
|
|
|
+
|
|
|
+ // 执行分页查询
|
|
|
+ userMomentsMapper.selectPage(allMomentsPage, allMomentQuery);
|
|
|
+ List<UserMoments> allUserMoments = allMomentsPage.getRecords();
|
|
|
+
|
|
|
+ // 5. 提取所有动态相关用户ID(原有代码)
|
|
|
+ Set<Long> allUserIds = allUserMoments.stream()
|
|
|
+ .map(UserMoments::getUserId)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 6. 批量查询所有动态相关用户信息(原有代码)
|
|
|
+ QueryWrapper<UserLogin> userQuery = new QueryWrapper<>();
|
|
|
+ userQuery.in("id", allUserIds);
|
|
|
+ List<UserLogin> users = userLoginMapper.selectList(userQuery);
|
|
|
+ Map<Long, UserLogin> userMap = users.stream()
|
|
|
+ .collect(Collectors.toMap(UserLogin::getId, user -> user));
|
|
|
+
|
|
|
+ // 7. 提取所有动态ID
|
|
|
+ List<Long> allMomentIds = allUserMoments.stream()
|
|
|
+ .map(UserMoments::getMomentId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 8. 批量查询当前用户对所有动态的点赞状态(性能优化点)
|
|
|
+ Map<Long, Boolean> likedStatusMap = new HashMap<>();
|
|
|
+ if (!allMomentIds.isEmpty()) {
|
|
|
+ QueryWrapper<MomentLikes> batchLikeQuery = new QueryWrapper<>();
|
|
|
+ batchLikeQuery.in("moment_id", allMomentIds)
|
|
|
+ .eq("user_id", userId);
|
|
|
+ List<MomentLikes> likedMoments = momentLikesMapper.selectList(batchLikeQuery);
|
|
|
+
|
|
|
+ // 将结果转换为 Map<momentId, isLiked>
|
|
|
+ for (Long momentId : allMomentIds) {
|
|
|
+ likedStatusMap.put(momentId, likedMoments.stream()
|
|
|
+ .anyMatch(like -> like.getMomentId().equals(momentId)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 9. 处理动态数据,添加用户信息和点赞状态(优化后)
|
|
|
+ List<Map<String, Object>> momentList = allUserMoments.stream()
|
|
|
+ .map(moment -> {
|
|
|
+ Map<String, Object> momentMap = wrapMomentWithUser(moment, userMap);
|
|
|
+ // 从批量查询结果中获取点赞状态,避免重复查询
|
|
|
+ momentMap.put("isLiked", likedStatusMap.getOrDefault(moment.getMomentId(), false));
|
|
|
+ return momentMap;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 10. 处理点赞和评论(原有代码,略作优化)
|
|
|
+ Map<Long, Object> allLikesAndComments = new HashMap<>();
|
|
|
+ if (!allMomentIds.isEmpty()) {
|
|
|
+ // 批量查询所有动态的点赞
|
|
|
+ Map<Long, List<MomentLikes>> likesMap = new HashMap<>();
|
|
|
+ QueryWrapper<MomentLikes> likeQuery = new QueryWrapper<>();
|
|
|
+ likeQuery.in("moment_id", allMomentIds);
|
|
|
+ List<MomentLikes> allLikes = momentLikesMapper.selectList(likeQuery);
|
|
|
+ for (MomentLikes like : allLikes) {
|
|
|
+ likesMap.computeIfAbsent(like.getMomentId(), k -> new ArrayList<>()).add(like);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量查询所有动态的评论
|
|
|
+ Map<Long, List<MomentComments>> commentsMap = new HashMap<>();
|
|
|
+ QueryWrapper<MomentComments> commentQuery = new QueryWrapper<>();
|
|
|
+ commentQuery.in("moment_id", allMomentIds)
|
|
|
+ .orderByDesc("created_at");
|
|
|
+ List<MomentComments> allComments = momentCommentsMapper.selectList(commentQuery);
|
|
|
+ for (MomentComments comment : allComments) {
|
|
|
+ commentsMap.computeIfAbsent(comment.getMomentId(), k -> new ArrayList<>()).add(comment);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取所有点赞和评论涉及的用户ID
|
|
|
+ Set<Long> likeCommentUserIds = new HashSet<>();
|
|
|
+ allLikes.forEach(like -> likeCommentUserIds.add(like.getUserId()));
|
|
|
+ allComments.forEach(comment -> {
|
|
|
+ likeCommentUserIds.add(comment.getUserId());
|
|
|
+ if (comment.getReplyToUser() != null) {
|
|
|
+ likeCommentUserIds.add(comment.getReplyToUser());
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 批量查询用户信息
|
|
|
+ List<UserLogin> likeCommentUsers = new ArrayList<>();
|
|
|
+ if (!likeCommentUserIds.isEmpty()) {
|
|
|
+ likeCommentUsers = userLoginMapper.selectBatchIds(likeCommentUserIds);
|
|
|
+ }
|
|
|
+ Map<Long, UserLogin> likeCommentUserMap = likeCommentUsers.stream()
|
|
|
+ .collect(Collectors.toMap(UserLogin::getId, user -> user));
|
|
|
+
|
|
|
+ // 处理每个动态的点赞和评论信息
|
|
|
+ for (Long momentId : allMomentIds) {
|
|
|
+ Map<String, Object> momentInfo = new HashMap<>();
|
|
|
+
|
|
|
+ // 获取当前动态的点赞列表
|
|
|
+ List<MomentLikes> likes = likesMap.getOrDefault(momentId, Collections.emptyList());
|
|
|
+ List<Map<String, Object>> likeList = likes.stream()
|
|
|
+ .map(like -> {
|
|
|
+ Map<String, Object> likeInfo = new HashMap<>();
|
|
|
+ likeInfo.put("id", like.getLikeId());
|
|
|
+ likeInfo.put("userId", like.getUserId());
|
|
|
+
|
|
|
+ if (like.getCreatedAt() != null) {
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ likeInfo.put("createTime", sdf.format(like.getCreatedAt()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手动构建用户信息
|
|
|
+ UserLogin user = likeCommentUserMap.get(like.getUserId());
|
|
|
+ if (user != null) {
|
|
|
+ Map<String, Object> userInfo = new HashMap<>();
|
|
|
+ userInfo.put("id", user.getId().toString());
|
|
|
+ userInfo.put("nickName", user.getNickName());
|
|
|
+ userInfo.put("avatar", user.getAvatar());
|
|
|
+ userInfo.put("username", user.getUserUsername());
|
|
|
+ likeInfo.put("userInfo", userInfo);
|
|
|
+ }
|
|
|
+ return likeInfo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 获取当前动态的评论列表
|
|
|
+ List<MomentComments> comments = commentsMap.getOrDefault(momentId, Collections.emptyList());
|
|
|
+ List<Map<String, Object>> commentList = comments.stream()
|
|
|
+ .map(comment -> {
|
|
|
+ Map<String, Object> commentInfo = new HashMap<>();
|
|
|
+ commentInfo.put("id", comment.getCommentId());
|
|
|
+ commentInfo.put("userId", comment.getUserId());
|
|
|
+ commentInfo.put("content", comment.getContent());
|
|
|
+
|
|
|
+ if (comment.getCreatedAt() != null) {
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ commentInfo.put("createdAt", sdf.format(comment.getCreatedAt()));
|
|
|
+ }
|
|
|
+
|
|
|
+ commentInfo.put("replyTo", comment.getReplyTo());
|
|
|
+ commentInfo.put("replyToUser", comment.getReplyToUser());
|
|
|
+
|
|
|
+ UserLogin user = likeCommentUserMap.get(comment.getUserId());
|
|
|
+ if (user != null) {
|
|
|
+ Map<String, Object> userInfo = new HashMap<>();
|
|
|
+ userInfo.put("id", user.getId().toString());
|
|
|
+ userInfo.put("username", user.getUserUsername());
|
|
|
+ userInfo.put("avatar", user.getAvatar());
|
|
|
+ commentInfo.put("userInfo", userInfo);
|
|
|
+ }
|
|
|
+ return commentInfo;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 封装点赞评论信息
|
|
|
+ momentInfo.put("likeList", likeList);
|
|
|
+ momentInfo.put("commentList", commentList);
|
|
|
+ momentInfo.put("likeCount", likeList.size());
|
|
|
+ momentInfo.put("commentCount", commentList.size());
|
|
|
+
|
|
|
+ allLikesAndComments.put(momentId, momentInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 11. 封装最终结果(原有代码)
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
+ resultMap.put("userInfo", userLogin);
|
|
|
+ resultMap.put("moments", momentList);
|
|
|
+ resultMap.put("allLikesAndComments", allLikesAndComments);
|
|
|
+ resultMap.put("total", allMomentsPage.getTotal());
|
|
|
+ resultMap.put("currentPage", allMomentsPage.getCurrent());
|
|
|
+ resultMap.put("pageSize", allMomentsPage.getSize());
|
|
|
+ resultMap.put("totalPages", allMomentsPage.getPages());
|
|
|
+
|
|
|
+ return Result.OK(resultMap, "查询成功");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("综合朋友圈查询异常: {}", e.getMessage(), e);
|
|
|
+ return Result.error(500, "查询失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 封装动态数据并关联用户信息,确保包含momentId
|
|
|
+ */
|
|
|
+ private Map<String, Object> wrapMomentWithUser(UserMoments moment, Map<Long, UserLogin> userMap) {
|
|
|
+ Map<String, Object> momentMap = new HashMap<>();
|
|
|
+
|
|
|
+ // 手动添加所有需要的字段,确保momentId存在
|
|
|
+ momentMap.put("momentId", moment.getMomentId().toString());
|
|
|
+ momentMap.put("contentType", moment.getContentType());
|
|
|
+ momentMap.put("url", moment.getUrl());
|
|
|
+ momentMap.put("content", moment.getContent());
|
|
|
+ momentMap.put("location", moment.getLocation());
|
|
|
+ momentMap.put("visibility", moment.getVisibility());
|
|
|
+
|
|
|
+ // 转换日期为字符串格式
|
|
|
+ if (moment.getCreatedAt() != null) {
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ momentMap.put("createdAt", sdf.format(moment.getCreatedAt()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手动添加用户信息,只包含必要字段
|
|
|
+ UserLogin user = userMap.get(moment.getUserId());
|
|
|
+ if (user != null) {
|
|
|
+ Map<String, Object> userInfo = new HashMap<>();
|
|
|
+ userInfo.put("id", user.getId());
|
|
|
+ userInfo.put("nickName", user.getNickName());
|
|
|
+ userInfo.put("avatar", user.getAvatar());
|
|
|
+ userInfo.put("username", user.getUserUsername());
|
|
|
+ momentMap.put("userInfo", userInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ momentMap.put("isSelf", user != null && user.getId().equals(moment.getUserId()));
|
|
|
+ return momentMap;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 上传到oss
|
|
|
+ * */
|
|
|
+ private String uploadToOss(MultipartFile file, String ossFilePath) throws IOException {
|
|
|
+ OSSClient ossClient = new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
|
|
|
+ String bucketName = ossConfig.getBucketName();
|
|
|
+
|
|
|
+ // 创建PutObject请求
|
|
|
+ PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath,
|
|
|
+ file.getInputStream(), null);
|
|
|
+
|
|
|
+ // 设置对象元信息
|
|
|
+ ObjectMetadata metadata = new ObjectMetadata();
|
|
|
+ metadata.setContentType(file.getContentType());
|
|
|
+ metadata.setContentLength(file.getSize());
|
|
|
+ putObjectRequest.setMetadata(metadata);
|
|
|
+
|
|
|
+ // 上传文件
|
|
|
+ ossClient.putObject(putObjectRequest);
|
|
|
+
|
|
|
+ // 构建访问URL
|
|
|
+ String endpoint = ossConfig.getEndpoint();
|
|
|
+ String cleanEndpoint = endpoint.replaceAll("^https://", "");
|
|
|
+ String domain = "https://" + bucketName + "." + cleanEndpoint;
|
|
|
+ return domain + "/" + ossFilePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件扩展名
|
|
|
+ */
|
|
|
+ private String getFileExtension(String fileName) {
|
|
|
+ if (fileName == null || !fileName.contains(".")) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return fileName.substring(fileName.lastIndexOf("."));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证图片内容
|
|
|
+ */
|
|
|
+ private void validateImageContent(MultipartFile file) throws Exception {
|
|
|
+ if (file == null || file.isEmpty()) {
|
|
|
+ throw new Exception("图片不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String contentType = file.getContentType();
|
|
|
+ if (!contentType.startsWith("image/")) {
|
|
|
+ throw new Exception("请上传图片格式文件");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证图片大小(例如限制为10MB)
|
|
|
+ if (file.getSize() > ossConfig.getUpload().getImage().getMaxSize()) {
|
|
|
+ throw new Exception("图片大小不能超过" +
|
|
|
+ (ossConfig.getUpload().getImage().getMaxSize() / (1024 * 1024)) + "MB");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证视频内容
|
|
|
+ */
|
|
|
+ private void validateVideoContent(MultipartFile file) throws Exception {
|
|
|
+ if (file == null || file.isEmpty()) {
|
|
|
+ throw new Exception("视频不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String contentType = file.getContentType();
|
|
|
+ if (!contentType.startsWith("video/")) {
|
|
|
+ throw new Exception("请上传视频格式文件");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证视频大小(例如限制为50MB)
|
|
|
+ if (file.getSize() > ossConfig.getUpload().getVideo().getMaxSize()) {
|
|
|
+ throw new Exception("视频大小不能超过" +
|
|
|
+ (ossConfig.getUpload().getVideo().getMaxSize() / (1024 * 1024)) + "MB");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|