diff --git a/.idea/mybatisx/templates.xml b/.idea/mybatisx/templates.xml index 47f2860..f2e668e 100644 --- a/.idea/mybatisx/templates.xml +++ b/.idea/mybatisx/templates.xml @@ -39,6 +39,26 @@ diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/config/MpConfig.java b/community-8073/src/main/java/com/ivmiku/tutorial/config/MpConfig.java new file mode 100644 index 0000000..3d4bdfc --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/config/MpConfig.java @@ -0,0 +1,15 @@ +package com.ivmiku.tutorial.config; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +@Configuration +public class MpConfig { + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommentController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommentController.java index 561c3ac..fbf5ab1 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommentController.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommentController.java @@ -2,6 +2,7 @@ package com.ivmiku.tutorial.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.pagehelper.PageInfo; import com.ivmiku.tutorial.entity.Comment; import com.ivmiku.tutorial.entity.Pages; @@ -209,8 +210,7 @@ public class CommentController { public Result getPostComments(@PathVariable("postId") Long postId, @RequestBody Pages pages) { logger.info("获取帖子ID:{}的评论列表", postId); logger.info("获取pageSize:{}", pages.getPageSize()); - System.out.println("aaaaaa" + pages.getPageSize()); - PageInfo comments = commentService.getPostComments(postId, pages.getPageNum(), pages.getPageSize()); + IPage comments = commentService.getPostComments(postId, pages.getPageNum(), pages.getPageSize()); return Result.ok(comments); } @@ -224,7 +224,7 @@ public class CommentController { @Operation(summary = "获取评论下的所有回复") public Result getCommentReplies(@PathVariable Long commentId, @RequestBody Pages pages) { logger.info("获取评论ID:{}的回复列表", commentId); - PageInfo replies = commentService.getCommentReplies(commentId, pages.getPageNum(), pages.getPageSize()); + IPage replies = commentService.getCommentReplies(commentId, pages.getPageNum(), pages.getPageSize()); return Result.ok(replies); } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunityController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunityController.java index 8ec25a2..90142a7 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunityController.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunityController.java @@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import com.ivmiku.tutorial.entity.Community; import com.ivmiku.tutorial.response.Result; import com.ivmiku.tutorial.service.CommunityService; +import com.ivmiku.tutorial.service.CommunitytagService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.models.annotations.OpenAPI30; import org.apiguardian.api.API; diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunitytagController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunitytagController.java new file mode 100644 index 0000000..ca1644b --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunitytagController.java @@ -0,0 +1,47 @@ +package com.ivmiku.tutorial.controller; + +import com.ivmiku.tutorial.entity.Communitytag; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.CommunitytagService; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping("/communityTags") +public class CommunitytagController { + + @Resource + private CommunitytagService communitytagService; + + @PostMapping("/create") + public Result createCommunityTag(@RequestBody Communitytag communityTag) { + communitytagService.createCommunityTag(communityTag); + return Result.ok(); + } + + @PutMapping("/update/{id}") + public Result updateCommunityTag(@PathVariable Long id, @RequestBody Communitytag communityTag) { + communitytagService.updateCommunityTag(id, communityTag); + return Result.ok(); + } + + @DeleteMapping("/delete/{id}") + public Result deleteCommunityTag(@PathVariable Long id) { + communitytagService.deleteCommunityTag(id); + return Result.ok(); + } + + @GetMapping("/get/{id}") + public Result getCommunityTag(@PathVariable Long id) { + Communitytag communityTag = communitytagService.getCommunityTagById(id); + return Result.ok(communityTag); + } + + @GetMapping("/list/{communityId}") + public Result getCommunityTagListByCommunityId(@PathVariable Long communityId) { + List tags = communitytagService.getCommunityTagListByCommunityId(communityId); + return Result.ok(tags); + } +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/InteractionController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/InteractionController.java index d2a33f6..7e18427 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/controller/InteractionController.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/InteractionController.java @@ -2,12 +2,17 @@ package com.ivmiku.tutorial.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.lang.hash.Hash; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.ivmiku.tutorial.entity.Post; import com.ivmiku.tutorial.response.Result; import com.ivmiku.tutorial.service.InteractionService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; /** * InteractionController 是处理用户与帖子的收藏、点赞以及对评论的点赞功能的控制器类。 @@ -104,4 +109,35 @@ public class InteractionController { interactionService.unlikeComment(userOpenid, commentId); return Result.ok(); } + + + /** + * 我的收藏接口 + * @return + */ + @GetMapping("/getFavoritePosts") + public Result getFavoritePosts() { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("用户 {} 正在获取收藏的帖子", userOpenid); + IPage favoritePost = interactionService.getFavoritePosts(userOpenid); + HashMap data = new HashMap<>(); + if (favoritePost != null) { + log.info("用户 {} 收藏的帖子获取成功", userOpenid); + data.put("total", favoritePost.getTotal()); + data.put("list", favoritePost.getRecords()); + return Result.ok(data); + } + return Result.ok("用户未发表帖子"); + } + + /** + * 统计我的获赞数量 笔记数量 收藏数量 + */ + @GetMapping("/getLikeCount") + public Result getLikeCount() { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("用户 {} 正在获取用户获赞的数量", userOpenid); + HashMap res = interactionService.getLikeCount(userOpenid); + return Result.ok(); + } } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostController.java index 6e0fb22..52a4d70 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostController.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostController.java @@ -2,6 +2,7 @@ package com.ivmiku.tutorial.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.pagehelper.PageInfo; import com.ivmiku.tutorial.entity.Pages; import com.ivmiku.tutorial.entity.Post; @@ -15,7 +16,9 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.sql.Timestamp; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 帖子控制器,用于处理帖子相关的HTTP请求。 @@ -81,7 +84,8 @@ public class PostController { @GetMapping("/get/{id}") public Result getPost(@PathVariable Long id) { logger.info("开始获取帖子ID:{}的详细信息", id); - Post post = postService.getPostById(id); // 调用服务层根据ID查询帖子 + String userId = StpUtil.getLoginIdAsString(); + Post post = postService.getPostById(id, userId); // 调用服务层根据ID查询帖子 if (post != null) { logger.info("帖子ID:{}的详细信息获取成功", id); } else { @@ -110,24 +114,27 @@ public class PostController { /** * 用户获取自己所有帖子的信息 - * @return 当前用户帖子列表 + * @return 当前用户帖子列表与该用户的总发布数量 */ @GetMapping("/getPostList") public Result getPostList(@RequestBody Pages pages) { logger.info("开始获取帖子列表"); String userId = StpUtil.getLoginIdAsString(); // 获取当前登录用户的ID - PageInfo posts = postService.getPostList(userId, pages.getPageNum(), pages.getPageSize()); - return Result.ok(posts); // 调用服务层获取帖子列表 + IPage posts = postService.getPostList(userId, pages.getPageNum(), pages.getPageSize()); + Map data = new HashMap<>(); + data.put("total", posts.getTotal()); + data.put("posts", posts); + return Result.ok(data); // 调用服务层获取帖子列表 } /** * 社区获取自己所有帖子的信息 * @return 当前用户帖子列表 */ - @GetMapping("/getCommunityPostList{communityId}") + @GetMapping("/getCommunityPostList/{communityId}") public Result getCommunityPostList(@PathVariable("communityId") Long communityId, @RequestBody Pages pages) { logger.info("开始获取帖子列表"); - PageInfo posts = postService.getCommunityPostList(communityId, pages.getPageNum(), pages.getPageSize()); + IPage posts = postService.getCommunityPostList(communityId, pages.getPageNum(), pages.getPageSize()); return Result.ok(posts); // 调用服务层获取帖子列表 } @@ -136,7 +143,7 @@ public class PostController { * @return */ @GetMapping("/official") - public PageInfo getOfficialPosts(@RequestBody Pages pages) { + public IPage getOfficialPosts(@RequestBody Pages pages) { return postService.getOfficialPosts(pages.getPageNum(), pages.getPageSize()); } @@ -145,7 +152,7 @@ public class PostController { * @return */ @GetMapping("/nonOfficial") - public PageInfo getNonOfficialPosts(@RequestBody Pages pages) { + public IPage getNonOfficialPosts(@RequestBody Pages pages) { return postService.getNonOfficialPosts(pages.getPageNum(), pages.getPageSize()); } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/BrowingHistory.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/BrowingHistory.java new file mode 100644 index 0000000..fc963e3 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/BrowingHistory.java @@ -0,0 +1,30 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * @TableName browing_history + */ +@TableName(value ="browing_history") +@Data +public class BrowingHistory implements Serializable { + @TableId(type = IdType.AUTO) + private Long browingId; + + private String userOpenid; + + + private Long postId; + + + private Date createAt; + + @TableLogic + private Integer isDelete; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Communitytag.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Communitytag.java new file mode 100644 index 0000000..9d0d8f8 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Communitytag.java @@ -0,0 +1,27 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * @TableName communitytag + */ +@TableName(value ="communitytag") +@Data +public class Communitytag implements Serializable { + + @TableId + private Long smallCTagId; + + private String cTagName; + + private Long cId; + + private Integer isDelete; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/BrowingHistoryMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/BrowingHistoryMapper.java new file mode 100644 index 0000000..09e62fa --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/BrowingHistoryMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.BrowingHistory; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【browing_history】的数据库操作Mapper +* @createDate 2024-08-23 11:29:33 +* @Entity com.ivmiku.tutorial.entity.BrowingHistory +*/ +public interface BrowingHistoryMapper extends BaseMapper { + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunitytagMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunitytagMapper.java new file mode 100644 index 0000000..641085c --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunitytagMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Communitytag; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【communitytag】的数据库操作Mapper +* @createDate 2024-08-16 09:40:06 +* @Entity com.ivmiku.tutorial.entity.Communitytag +*/ +public interface CommunitytagMapper extends BaseMapper { + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/LikeMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/LikeMapper.java index b951e47..77b9297 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/LikeMapper.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/LikeMapper.java @@ -2,6 +2,8 @@ package com.ivmiku.tutorial.mapper; import com.ivmiku.tutorial.entity.Likee; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; /** * @author rog @@ -11,6 +13,14 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface LikeMapper extends BaseMapper { + // 获取帖子获赞数 + @Select("SELECT SUM(like_count) FROM posts WHERE user_openid = #{userOpenid}") + Long getPostLikeCount(@Param("userOpenid") String userOpenid); + + // 获取评论获赞数 + @Select("SELECT SUM(like_count) FROM comments WHERE user_openid = #{userOpenid}") + Long getCommentLikeCount(@Param("userOpenid") String userOpenid); + } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/BrowingHistoryService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/BrowingHistoryService.java new file mode 100644 index 0000000..2ba13dd --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/BrowingHistoryService.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.BrowingHistory; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** +* @author rog +* @description 针对表【browing_history】的数据库操作Service +* @createDate 2024-08-23 11:29:33 +*/ +public interface BrowingHistoryService extends IService { + + void deleteBrowingRecordById(Long browingId); + + void deleteBrowingRecordsByIds(List browingIds); +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/CommentService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommentService.java index acb020c..5d17878 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/CommentService.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommentService.java @@ -1,5 +1,6 @@ package com.ivmiku.tutorial.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.pagehelper.PageInfo; import com.ivmiku.tutorial.entity.Comment; import com.baomidou.mybatisplus.extension.service.IService; @@ -50,9 +51,9 @@ public interface CommentService extends IService { void deleteComment(Long commentId, String userId); - PageInfo getPostComments(Long postId, int pageNum, int pageSize); + IPage getPostComments(Long postId, int pageNum, int pageSize); - PageInfo getCommentReplies(Long commentId, int pageNum, int pageSize); + IPage getCommentReplies(Long commentId, int pageNum, int pageSize); /** * 回复评论。 diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunitytagService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunitytagService.java new file mode 100644 index 0000000..4561c71 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunitytagService.java @@ -0,0 +1,24 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Communitytag; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** +* @author rog +* @description 针对表【communitytag】的数据库操作Service +* @createDate 2024-08-16 09:40:06 +*/ +public interface CommunitytagService extends IService { + + void createCommunityTag(Communitytag communityTag); + + void updateCommunityTag(Long id, Communitytag communityTag); + + void deleteCommunityTag(Long id); + + Communitytag getCommunityTagById(Long id); + + List getCommunityTagListByCommunityId(Long communityId); +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/InteractionService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/InteractionService.java index 981a552..bf8c9f0 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/InteractionService.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/InteractionService.java @@ -1,5 +1,11 @@ package com.ivmiku.tutorial.service; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.ivmiku.tutorial.entity.Post; + +import java.util.HashMap; +import java.util.List; + /** * InteractionService接口定义用户对帖子和评论的收藏与点赞操作。 */ @@ -10,4 +16,8 @@ public interface InteractionService { void unlikePost(String userOpenid, Long postId); void likeComment(String userOpenid, Long commentId); void unlikeComment(String userOpenid, Long commentId); + + IPage getFavoritePosts(String userOpenid); + + HashMap getLikeCount(String userOpenid); } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/PostService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/PostService.java index 0a37130..05a2a2d 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/PostService.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/PostService.java @@ -1,5 +1,6 @@ package com.ivmiku.tutorial.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.pagehelper.PageInfo; import com.ivmiku.tutorial.entity.Post; import com.baomidou.mybatisplus.extension.service.IService; @@ -8,17 +9,18 @@ import java.util.List; public interface PostService extends IService { void createPost(Post post); - Post getPostById(Long postId); + Post getPostById(Long postId, String userOpenid); + void updatePost(Long postId, String userId, Post post); void deletePost(Long postId, String userId); - PageInfo getPostList(String userId, int pageNum, int pageSize); + IPage getPostList(String userId, int pageNum, int pageSize); - PageInfo getCommunityPostList(Long communityId, int pageNum, int pageSize); + IPage getCommunityPostList(Long communityId, int pageNum, int pageSize); - PageInfo getOfficialPosts(int pageNum, int pageSize); + IPage getOfficialPosts(int pageNum, int pageSize); - PageInfo getNonOfficialPosts(int pageNum, int pageSize); + IPage getNonOfficialPosts(int pageNum, int pageSize); void changePublic(Long postId, Integer isPublic); } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/BrowingHistoryServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/BrowingHistoryServiceImpl.java new file mode 100644 index 0000000..4c6e129 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/BrowingHistoryServiceImpl.java @@ -0,0 +1,60 @@ +package com.ivmiku.tutorial.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ivmiku.tutorial.entity.BrowingHistory; +import com.ivmiku.tutorial.service.BrowingHistoryService; +import com.ivmiku.tutorial.mapper.BrowingHistoryMapper; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** +* @author rog +* @description 针对表【browing_history】的数据库操作Service实现 +* @createDate 2024-08-23 11:29:33 +*/ +@Service +@Slf4j +public class BrowingHistoryServiceImpl extends ServiceImpl + implements BrowingHistoryService{ + + private static final Logger logger = LoggerFactory.getLogger(BrowingHistoryServiceImpl.class); + @Override + public void deleteBrowingRecordById(Long browingId) { + logger.info("开始删除浏览记录,浏览记录ID:{}", browingId); + BrowingHistory browingHistory = getById(browingId); + if (browingHistory != null) { + browingHistory.setIsDelete(1); // 标记为已删除 + updateById(browingHistory); + logger.info("浏览记录ID:{} 删除成功", browingId); + } else { + logger.warn("浏览记录ID:{} 不存在", browingId); + } + } + + @Override + public void deleteBrowingRecordsByIds(List browingIds) { + logger.info("开始批量删除浏览记录,浏览记录ID列表:{}", browingIds); + if (browingIds != null && !browingIds.isEmpty()) { + List browingHistories = listByIds(browingIds); + if (!browingHistories.isEmpty()) { + for (BrowingHistory browingHistory : browingHistories) { + browingHistory.setIsDelete(1); // 标记为已删除 + } + updateBatchById(browingHistories); // 批量更新删除状态 + logger.info("批量删除浏览记录成功"); + } else { + logger.warn("提供的浏览记录ID列表中没有找到匹配的记录"); + } + } else { + logger.warn("浏览记录ID列表为空,无法删除"); + } + } +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommentServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommentServiceImpl.java index 72587b2..67acb96 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommentServiceImpl.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommentServiceImpl.java @@ -2,6 +2,8 @@ package com.ivmiku.tutorial.service.impl; import cn.dev33.satoken.stp.StpUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.ivmiku.tutorial.entity.Comment; @@ -103,16 +105,17 @@ public class CommentServiceImpl extends ServiceImpl impl * @return List 返回评论列表 */ @Override - public PageInfo getPostComments(Long postId, int pageNum, int pageSize) { + public IPage getPostComments(Long postId, int pageNum, int pageSize) { logger.info("开始获取帖子ID:{}的评论列表,第{}页,每页{}条", postId, pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); // 查询评论 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Comment::getPostId, postId).eq(Comment::getIsDeleted, 0); - List comments = commentMapper.selectList(wrapper); + IPage comments = commentMapper.selectPage(page, wrapper); if (comments != null) { logger.info("获取帖子ID:{}的评论列表成功", postId); @@ -121,7 +124,7 @@ public class CommentServiceImpl extends ServiceImpl impl } // 使用 PageInfo 包装结果 - return new PageInfo<>(comments); + return comments; } @@ -132,16 +135,16 @@ public class CommentServiceImpl extends ServiceImpl impl * @return List 返回回复列表 */ @Override - public PageInfo getCommentReplies(Long commentId, int pageNum, int pageSize) { + public IPage getCommentReplies(Long commentId, int pageNum, int pageSize) { logger.info("开始获取评论ID:{}的回复列表,第{}页,每页{}条", commentId, pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); - +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); // 查询回复 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Comment::getParentCommentId, commentId).eq(Comment::getIsDeleted, 0); - List replies = commentMapper.selectList(wrapper); + IPage replies = commentMapper.selectPage(page, wrapper); if (replies != null) { logger.info("获取评论ID:{}的回复列表成功", commentId); @@ -150,7 +153,7 @@ public class CommentServiceImpl extends ServiceImpl impl } // 使用 PageInfo 包装结果 - return new PageInfo<>(replies); + return replies; } /** * 回复评论。 diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunitytagServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunitytagServiceImpl.java new file mode 100644 index 0000000..2396be0 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunitytagServiceImpl.java @@ -0,0 +1,50 @@ +package com.ivmiku.tutorial.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ivmiku.tutorial.entity.Communitytag; +import com.ivmiku.tutorial.service.CommunitytagService; +import com.ivmiku.tutorial.mapper.CommunitytagMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** +* @author rog +* @description 针对表【communitytag】的数据库操作Service实现 +* @createDate 2024-08-16 09:40:06 +*/ +@Service +public class CommunitytagServiceImpl extends ServiceImpl + implements CommunitytagService{ + + @Override + public void createCommunityTag(Communitytag communityTag) { + this.save(communityTag); + } + + @Override + public void updateCommunityTag(Long id, Communitytag communityTag) { + communityTag.setSmallCTagId(id); + this.updateById(communityTag); + } + + @Override + public void deleteCommunityTag(Long id) { + this.removeById(id); + } + + @Override + public Communitytag getCommunityTagById(Long id) { + return this.getById(id); + } + + @Override + public List getCommunityTagListByCommunityId(Long communityId) { + return this.lambdaQuery().eq(Communitytag::getCId, communityId).list(); + } + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/InteractionServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/InteractionServiceImpl.java index 4ff63bf..1a4f10c 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/InteractionServiceImpl.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/InteractionServiceImpl.java @@ -1,15 +1,22 @@ package com.ivmiku.tutorial.service.impl; +import cn.hutool.core.lang.hash.Hash; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.ivmiku.tutorial.entity.Favorite; import com.ivmiku.tutorial.entity.Likee; +import com.ivmiku.tutorial.entity.Post; import com.ivmiku.tutorial.mapper.FavoriteMapper; import com.ivmiku.tutorial.mapper.LikeMapper; import com.ivmiku.tutorial.service.InteractionService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ivmiku.tutorial.service.PostService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; /** * InteractionServiceImpl 实现了 InteractionService 接口,处理用户对帖子和评论的收藏与点赞操作。 @@ -24,6 +31,9 @@ public class InteractionServiceImpl implements InteractionService { @Resource private LikeMapper likeMapper; + @Resource + private PostService postService; + @Override public void favoritePost(String userOpenid, Long postId) { log.info("User {} is favoriting post {}", userOpenid, postId); @@ -95,4 +105,60 @@ public class InteractionServiceImpl implements InteractionService { likeMapper.updateById(likee); } } + + @Override + public IPage getFavoritePosts(String userOpenid) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Favorite::getUserOpenid, userOpenid); + List favorites = favoriteMapper.selectList(wrapper); + if (favorites != null && !favorites.isEmpty()) { + List postIds = favorites.stream().map(Favorite::getPostId).toList(); + return postService.getPostList(userOpenid, 1, 10); + } + return null; + } + + @Override + public HashMap getLikeCount(String userOpenid) { + HashMap res = new HashMap<>(); + + // 获取帖子获赞数 + Long postLikeCount = likeMapper.getPostLikeCount(userOpenid); + // 获取评论获赞数 + Long commentLikeCount = likeMapper.getCommentLikeCount(userOpenid); + + // 如果帖子获赞数不为空,加入结果 + if (postLikeCount != null) { + res.put("postLikeCount", postLikeCount); + } else { + res.put("postLikeCount", 0L); // 如果为空,设置为0 + } + + // 如果评论获赞数不为空,加入结果 + if (commentLikeCount != null) { + res.put("commentLikeCount", commentLikeCount); + } else { + res.put("commentLikeCount", 0L); // 如果为空,设置为0 + } + + // 计算总的获赞数 + Long totalLikeCount = (postLikeCount == null ? 0 : postLikeCount) + + (commentLikeCount == null ? 0 : commentLikeCount); + + res.put("totalLikeCount", totalLikeCount); + + // 获取收藏数量 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Favorite::getUserOpenid, userOpenid); + Long favoriteCount = favoriteMapper.selectCount(wrapper); + + if (favoriteCount != null) { + res.put("favoriteCount", favoriteCount); + } else { + res.put("favoriteCount", 0L); // 如果为空,设置为0 + } + Long myTotalPost = getFavoritePosts(userOpenid).getTotal(); + res.put("myTotalPost", myTotalPost); + return res; + } } diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostServiceImpl.java index 69dc5c4..98d7adc 100644 --- a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostServiceImpl.java +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostServiceImpl.java @@ -1,19 +1,20 @@ package com.ivmiku.tutorial.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.github.pagehelper.PageHelper; -import com.github.pagehelper.PageInfo; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ivmiku.tutorial.entity.BrowingHistory; import com.ivmiku.tutorial.entity.Post; import com.ivmiku.tutorial.mapper.PostMapper; +import com.ivmiku.tutorial.service.BrowingHistoryService; import com.ivmiku.tutorial.service.PostService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - import java.sql.Timestamp; -import java.util.List; +import java.util.Date; @Service public class PostServiceImpl extends ServiceImpl implements PostService { @@ -23,6 +24,9 @@ public class PostServiceImpl extends ServiceImpl implements Po @Autowired private PostMapper postMapper; + @Autowired + private BrowingHistoryService browingHistoryService; + @Override public void createPost(Post post) { logger.info("开始创建帖子"); @@ -34,15 +38,24 @@ public class PostServiceImpl extends ServiceImpl implements Po } @Override - public Post getPostById(Long postId) { - logger.info("开始根据ID获取帖子详情,帖子ID:{}", postId); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Post::getIsPublic, 1); - Post post = postMapper.selectById(wrapper); - if (post == null) { - logger.warn("帖子ID:{}不存在", postId); + public Post getPostById(Long postId, String userOpenid) { + logger.info("用户openid:{} 开始根据ID获取帖子详情,帖子ID:{}", userOpenid, postId); + + // 查找帖子信息 + Post post = postMapper.selectById(postId); + if (post == null || post.getIsDeleted() == 1) { + logger.warn("帖子ID:{}不存在或已删除", postId); return null; } + + // 创建浏览记录 + BrowingHistory browingHistory = new BrowingHistory(); + browingHistory.setUserOpenid(userOpenid); + browingHistory.setPostId(postId); + browingHistory.setCreateAt(new Date()); + browingHistory.setIsDelete(0); // 未删除标记 + browingHistoryService.save(browingHistory); + logger.info("用户openid:{}的浏览记录创建成功", userOpenid); return post; } @@ -70,83 +83,83 @@ public class PostServiceImpl extends ServiceImpl implements Po } @Override - public PageInfo getPostList(String userId, int pageNum, int pageSize) { + public IPage getPostList(String userId, int pageNum, int pageSize) { logger.info("用户ID:{}开始获取帖子列表,第{}页,每页{}条", userId, pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); - +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Post::getUserOpenid, userId); wrapper.eq(Post::getIsDeleted, 0); wrapper.eq(Post::getIsPublic, 1); - List posts = postMapper.selectList(wrapper); + IPage posts = postMapper.selectPage(page, wrapper); // 使用PageInfo封装分页结果 - PageInfo pageInfo = new PageInfo<>(posts); +// PageInfo pageInfo = new PageInfo<>(posts); - return pageInfo; + return posts; } @Override - public PageInfo getCommunityPostList(Long communityId, int pageNum, int pageSize) { + public IPage getCommunityPostList(Long communityId, int pageNum, int pageSize) { logger.info("开始获取社区ID:{}的帖子列表,第{}页,每页{}条", communityId, pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); - +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Post::getCommunityId, communityId); wrapper.eq(Post::getIsDeleted, 0); wrapper.eq(Post::getIsPublic, 1); - List posts = postMapper.selectList(wrapper); + IPage posts = postMapper.selectPage(page, wrapper); // 使用PageInfo封装分页结果 - PageInfo pageInfo = new PageInfo<>(posts); +// PageInfo pageInfo = new PageInfo<>(posts); - return pageInfo; + return posts; } @Override - public PageInfo getOfficialPosts(int pageNum, int pageSize) { + public IPage getOfficialPosts(int pageNum, int pageSize) { logger.info("开始获取所有官方创建的帖子,第{}页,每页{}条", pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); - +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Post::getIsOfficial, 1); wrapper.eq(Post::getIsDeleted, 0); wrapper.eq(Post::getIsPublic, 1); - List posts = postMapper.selectList(wrapper); + IPage posts = postMapper.selectPage(page, wrapper); // 使用PageInfo封装分页结果 - PageInfo pageInfo = new PageInfo<>(posts); +// PageInfo pageInfo = new PageInfo<>(posts); - return pageInfo; + return posts; } @Override - public PageInfo getNonOfficialPosts(int pageNum, int pageSize) { + public IPage getNonOfficialPosts(int pageNum, int pageSize) { logger.info("开始获取所有非官方创建的帖子,第{}页,每页{}条", pageNum, pageSize); // 设置分页参数 - PageHelper.startPage(pageNum, pageSize); - +// PageHelper.startPage(pageNum, pageSize); + IPage page = new Page<>(pageNum, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Post::getIsOfficial, 0); wrapper.eq(Post::getIsDeleted, 0); wrapper.eq(Post::getIsPublic, 1); - List posts = postMapper.selectList(wrapper); + IPage posts = postMapper.selectPage(page, wrapper); // 使用PageInfo封装分页结果 - PageInfo pageInfo = new PageInfo<>(posts); +// PageInfo pageInfo = new PageInfo<>(posts); - return pageInfo; + return posts; } @Override diff --git a/community-8073/src/main/resources/application-dev.properties b/community-8073/src/main/resources/application-dev.properties index b25407e..abec73c 100644 --- a/community-8073/src/main/resources/application-dev.properties +++ b/community-8073/src/main/resources/application-dev.properties @@ -27,3 +27,7 @@ minio.accessKey=minio_root minio.secretKey=minio_123456 minio.bucketName=haixia +## Nacos?? +#spring.cloud.nacos.discovery.server-addr=/192.168.146.1:8848 +#dubbo.registry.address=nacos:///192.168.146.1:8848 + diff --git a/community-8073/src/main/resources/mapper/BrowingHistoryMapper.xml b/community-8073/src/main/resources/mapper/BrowingHistoryMapper.xml new file mode 100644 index 0000000..cb4fe77 --- /dev/null +++ b/community-8073/src/main/resources/mapper/BrowingHistoryMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + browing_id,user_openid,post_id, + create_at,is_delete + + diff --git a/community-8073/src/main/resources/mapper/CommunitytagMapper.xml b/community-8073/src/main/resources/mapper/CommunitytagMapper.xml new file mode 100644 index 0000000..a995906 --- /dev/null +++ b/community-8073/src/main/resources/mapper/CommunitytagMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + small_c_tag_id,c_tag_name,c_id, + is_delete + + diff --git a/navigate-8432/pom.xml b/navigate-8432/pom.xml index 97f02c0..e3aa5f4 100644 --- a/navigate-8432/pom.xml +++ b/navigate-8432/pom.xml @@ -29,6 +29,7 @@ com.baomidou mybatis-plus-spring-boot3-starter + 3.5.7 com.alibaba.cloud @@ -103,5 +104,10 @@ tencentcloud-sdk-java-tts 3.1.1076 + + com.tencentcloudapi + tencentcloud-sdk-java-asr + 3.1.1083 + \ No newline at end of file diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java index afef15d..c32bcee 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java @@ -24,11 +24,4 @@ public class AssistantController { } return Result.ok(map); } - - @GetMapping("/tts") - public Object textToSpeech(@RequestParam String input) { - Map map = new HashMap<>(); - map.put("content", assistantService.textToSpeech(input)); - return Result.ok(map); - } } diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java new file mode 100644 index 0000000..9b16ab0 --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java @@ -0,0 +1,14 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@TableName("guidance") +@Data +public class Guidance { + @TableId + private String id; + private String tag; + private String content; +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java new file mode 100644 index 0000000..4bdea0f --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Guidance; + +public interface GuidanceMapper extends BaseMapper { + +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java index f060c58..c06c723 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java @@ -2,11 +2,15 @@ package com.ivmiku.tutorial.service; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; -import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ivmiku.tutorial.entity.Guidance; +import com.ivmiku.tutorial.mapper.GuidanceMapper; import com.ivmiku.tutorial.utils.SnowflakeUtil; -import com.tencentcloudapi.common.AbstractModel; +import com.tencentcloudapi.asr.v20190614.AsrClient; +import com.tencentcloudapi.asr.v20190614.models.SentenceRecognitionRequest; +import com.tencentcloudapi.asr.v20190614.models.SentenceRecognitionResponse; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.common.profile.ClientProfile; @@ -14,18 +18,23 @@ import com.tencentcloudapi.common.profile.HttpProfile; import com.tencentcloudapi.tts.v20190823.TtsClient; import com.tencentcloudapi.tts.v20190823.models.TextToVoiceRequest; import com.tencentcloudapi.tts.v20190823.models.TextToVoiceResponse; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.HashMap; +import java.util.List; import java.util.Map; @Service public class AssistantService { + @Resource + private GuidanceMapper guidanceMapper; + private final String auth = "bad1f6cad39a4c26aa9fe9e4324e096f:ZDczMDIwOTg3NjlhODdmYWVjYTY0YjM1"; private final String secretId = "AKID09INNYxYEFFJH3g9VhljVF3qbDiFdx50"; private final String secretKey = "KajjcNyNaaUCqQroqpzNoMtTHNj4Lbil"; - public Map getResponse(String userInput) { + public Map getAiResponse(String userInput) { Map message1 = new HashMap<>(); message1.put("role", "system"); message1.put("content", "模仿语音助手,对用户的问题给出简短的回答"); @@ -74,4 +83,75 @@ public class AssistantService { throw new RuntimeException(e); } } + + public String speechRecognition(String content, Integer length) { + try{ + Credential cred = new Credential(secretId, secretKey); + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("asr.tencentcloudapi.com"); + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + AsrClient client = new AsrClient(cred, "", clientProfile); + SentenceRecognitionRequest req = new SentenceRecognitionRequest(); + req.setEngSerViceType("16k_zh"); + req.setSourceType(1L); + req.setVoiceFormat("wav"); + req.setData(content); + req.setDataLen(Long.valueOf(length)); + SentenceRecognitionResponse resp = client.SentenceRecognition(req); + return resp.getResult(); + } catch (TencentCloudSDKException e) { + throw new RuntimeException(e); + } + } + + public String searchGuidance(String tag) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.like("tag", tag); + List list = guidanceMapper.selectList(queryWrapper); + if (list.isEmpty()) { + return null; + } + return list.getFirst().getContent(); + } + + public String extractTag(String query) { + Map message1 = new HashMap<>(); + message1.put("role", "system"); + message1.put("content", "根据给出的句子的意思,从以下标签中返回最匹配的一个:安全带、安检、飞机"); + Map message2 = new HashMap<>(); + message2.put("role", "user"); + message2.put("content", query); + JSONArray array = new JSONArray(); + array.add(message1); + array.add(message2); + JSONObject params = new JSONObject(); + params.put("model", "general"); + params.put("messages", array); + HttpResponse response = HttpRequest.post("https://spark-api-open.xf-yun.com/v1/chat/completions") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + auth) + .body(params.toJSONString()) + .execute(); + JSONObject result = JSONObject.parseObject(response.body()); + response.close(); + if (result.getInteger("code") != 0) { + return null; + } + JSONArray choices = result.getJSONArray("choices"); + JSONObject message = choices.getJSONObject(0); + return String.valueOf(message.getJSONObject("message")); + } + + public Map getResponse(String query) { + Map result = new HashMap<>(); + String tag = extractTag(query); + String content; + content = searchGuidance(tag); + if (content != null) { + result.put("content", content); + return result; + } + return getAiResponse(query); + } } diff --git a/user-8072/pom.xml b/user-8072/pom.xml index 7b5121b..5ca0ed8 100644 --- a/user-8072/pom.xml +++ b/user-8072/pom.xml @@ -117,6 +117,14 @@ commons 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-websocket + + + org.springframework.boot + spring-boot-starter-amqp + diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java new file mode 100644 index 0000000..71ed480 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ +package com.ivmiku.tutorial.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan("com.ivmiku.tutorial.mapper") +public class MybatisPlusConfig { + + /** + * 添加分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType + return interceptor; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java new file mode 100644 index 0000000..d9ee381 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java @@ -0,0 +1,27 @@ +package com.ivmiku.tutorial.config; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitMqConfig { + @Bean + public Queue queue1() { + return new Queue("queue1",true); + } + + @Bean + public FanoutExchange exchange1() { + return new FanoutExchange("exchange1",true, false); + } + + @Bean + public Binding binding1() { + return BindingBuilder.bind(queue1()).to(exchange1()); + } +} + diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java new file mode 100644 index 0000000..85ca18f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java @@ -0,0 +1,15 @@ +package com.ivmiku.tutorial.config; + +import cn.dev33.satoken.interceptor.SaInterceptor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class SaTokenConfigure implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册 Sa-Token 拦截器,打开注解式鉴权功能 + registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java new file mode 100644 index 0000000..b36ddc7 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java @@ -0,0 +1,34 @@ +package com.ivmiku.tutorial.config; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; +import org.springframework.web.util.WebAppRootListener; + +@Configuration +public class WebSocketConfig implements ServletContextInitializer { + @Bean + public ServerEndpointExporter serverEndpointExporter (){ + return new ServerEndpointExporter(); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + servletContext.addListener(WebAppRootListener.class); + servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","102400000"); + } + + @Bean + public ServletServerContainerFactoryBean createWebSocketContainer() { + ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); + // 在此处设置bufferSize + container.setMaxTextMessageBufferSize(50*1024*1024); + container.setMaxBinaryMessageBufferSize(50*1024*1024); + container.setMaxSessionIdleTimeout(15 * 60000L); + return container; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java new file mode 100644 index 0000000..326b872 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java @@ -0,0 +1,39 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.HistoryQuery; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.MessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; + +@SaCheckLogin +@RestController +@RequestMapping("/api/message") +public class MessageController { + @Autowired + private MessageService messageService; + + @PostMapping("/history") + public Object getChatHistory(@RequestBody HistoryQuery input) throws ParseException { + Result result = Result.ok(); + if (input.getStartDate() != null && input.getEndDate() != null) { + result.setData(messageService.getChatHistoryByDate(input.getUser1Id(), input.getUser2Id(), input.getStartDate(), input.getEndDate(), input.getPage(), input.getSize())); + } else { + if (input.getPage() <= 0 || input.getSize() <=0) { + return Result.error("请输入合法分页参数"); + } else { + result.setData(messageService.getChatHistory(input.getUser1Id(), input.getUser2Id(), input.getPage(), input.getSize())); + } + } + return JSON.toJSON(result); + } + + @GetMapping("/list") + public Object getChatList(@RequestParam String user_id, @RequestParam int page, @RequestParam int size) { + return Result.ok(messageService.getChatList(user_id, page, size)); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java new file mode 100644 index 0000000..d7dcc88 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java @@ -0,0 +1,42 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.stp.StpUtil; +import com.ivmiku.tutorial.entity.IgnoreUser; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.RelationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@SaCheckLogin +@RestController +@RequestMapping("/api/relation") +public class RelationController { + @Autowired + private RelationService relationService; + + @PostMapping("/ignore") + public Object ignoreUser(@RequestBody IgnoreUser input) { + relationService.IgnoreUser(input.getUserId(), input.getToIgnore()); + return Result.ok(); + } + + @GetMapping("subscribe") + public Object subscribe(@RequestParam String subId) { + String userId = (String) StpUtil.getLoginId(); + relationService.subscribe(userId, subId); + return Result.ok(); + } + + @GetMapping("fan") + public Object getFanList(@RequestParam int page, @RequestParam int size) { + String userId = (String) StpUtil.getLoginId(); + return Result.ok(relationService.getFanList(userId, page, size)); + } + + @GetMapping("follow") + public Object getFollowList(@RequestParam int page, @RequestParam int size) { + String userId = (String) StpUtil.getLoginId(); + return Result.ok(relationService.getSubList(userId, page, size)); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java new file mode 100644 index 0000000..993c05f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java @@ -0,0 +1,142 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.Message; +import com.ivmiku.tutorial.service.MessageService; +import com.ivmiku.tutorial.service.RelationService; +import com.ivmiku.tutorial.utils.DateUtil; +import com.ivmiku.tutorial.utils.MessageUtil; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Controller; + +import java.io.IOException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import static jakarta.websocket.CloseReason.CloseCodes.CLOSED_ABNORMALLY; + +@Controller +@ServerEndpoint(value = "/chat/{satoken}") +public class WebSocketServer implements ApplicationContextAware { + public static Map sessionMap = new ConcurrentHashMap<>(); + + public static Map controlMap = new HashMap<>(); + + private static ApplicationContext applicationContext; + + @Autowired + private MessageService messageService; + + private RabbitTemplate rabbitTemplate; + + private RelationService relationService; + + @OnMessage + public void onMessage(String message, Session session) throws IOException { + Message msg = JSON.parseObject(message, Message.class); + msg.setDate(DateUtil.getCurrentTime()); + if (MessageUtil.checkMessage(msg.getMessage())) { + session.getBasicRemote().sendText("发送的信息含有敏感词,请进行调整"); + if (!controlMap.containsKey(msg.getFromId())){ + controlMap.put(msg.getFromId(), 0); + } + if (controlMap.get(msg.getFromId()) == 4){ + session.getBasicRemote().sendText("由于多次违反社区规则,您已被封禁1小时"); + session.close(new CloseReason(CLOSED_ABNORMALLY, "账号被封禁")); + StpUtil.kickout(msg.getFromId()); + StpUtil.disable(msg.getFromId(), 3600); + controlMap.put(msg.getFromId(), 0); + } + controlMap.put(msg.getFromId(), controlMap.get(msg.getFromId())+1); + } else + if (relationService.ifIgnored(msg.getToId(), msg.getFromId())) { + session.getBasicRemote().sendText("您已被对方屏蔽"); + } else { + rabbitTemplate.convertAndSend("exchange1", "", JSON.toJSONString(msg)); + } + } + + + @OnOpen + public void onOpen(Session session, EndpointConfig endpointConfig, @PathParam("satoken") String satoken) throws IOException { + String userId = (String) StpUtil.getLoginIdByToken(satoken); + if (userId == null) { + session.getBasicRemote().sendText("Invalid Token"); + session.close(); + } + this.messageService = WebSocketServer.applicationContext.getBean(MessageService.class); + this.rabbitTemplate = WebSocketServer.applicationContext.getBean(RabbitTemplate.class); + this.relationService = WebSocketServer.applicationContext.getBean(RelationService.class); + sessionMap.put(userId, session); + List unreadList = messageService.getUnreadMsg(userId); + for(Message msg : unreadList) { + session.getBasicRemote().sendText(JSON.toJSONString(msg)); + } + } + + @OnClose + public void onClose(CloseReason closeReason, Session session){ + sessionMap.remove(session.getId()); + } + + @OnError + public void onError(Throwable throwable) throws IOException { + throwable.printStackTrace(); + } + + public void sendToUser(Message msg) throws IOException, ParseException { + if (sessionMap.containsKey(msg.getToId())){ + sessionMap.get(msg.getToId()).getBasicRemote().sendText(JSON.toJSONString(msg)); + } + else { + messageService.insertUnreadMsg(msg.getToId(), msg); + } + msg.setChatId(messageService.getChatId(msg.getFromId(), msg.getToId())); + messageService.insertToMysql(msg); + messageService.insertToRedis(msg); + } + + public void sendToPublic(Message msg) throws IOException, ParseException { + for (Session session : sessionMap.values()) { + session.getBasicRemote().sendText(JSON.toJSONString(msg)); + } + msg.setChatId(messageService.getChatId(msg.getFromId(), msg.getToId())); + messageService.insertToMysql(msg); + messageService.insertToRedis(msg); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + WebSocketServer.applicationContext = applicationContext; + } + + @RabbitHandler + @RabbitListener(bindings = @QueueBinding( + value = @Queue(), + exchange = @Exchange(value = "exchange1",type = ExchangeTypes.FANOUT) + )) + public void sendMsg(String message) throws IOException, ParseException { + Message msg = JSON.parseObject(message, Message.class); + if (sessionMap.containsKey(msg.getToId())) { + sessionMap.get(msg.getToId()).getBasicRemote().sendText(JSON.toJSONString(msg)); + } + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java new file mode 100644 index 0000000..7da0f60 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author Aurora + */ +@Data +@TableName("chatid") +public class ChatId { + @TableId(type = IdType.ASSIGN_ID) + private String id; + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java new file mode 100644 index 0000000..11cb2e4 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Aurora + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("friend") +public class Friend { + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java new file mode 100644 index 0000000..b31d876 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java @@ -0,0 +1,12 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +/** + * @author Aurora + */ +@Data +public class FriendQuery { + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java new file mode 100644 index 0000000..8b6149e --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java @@ -0,0 +1,16 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +/** + * @author Aurora + */ +@Data +public class HistoryQuery { + private String user1Id; + private String user2Id; + private int page; + private int size; + private String startDate; + private String endDate; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java new file mode 100644 index 0000000..d3c592f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java @@ -0,0 +1,21 @@ +package com.ivmiku.tutorial.entity; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Aurora + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("blacklist") +public class IgnoreUser { + @JSONField(ordinal = 1) + private String userId; + @JSONField(ordinal = 2) + private String toIgnore; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java new file mode 100644 index 0000000..e96f45a --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java @@ -0,0 +1,25 @@ +package com.ivmiku.tutorial.entity; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Aurora + */ +@Data +@TableName("message") +public class Message implements Serializable { + @JSONField(ordinal = 1) + private String chatId; + @JSONField(ordinal = 2) + private String fromId; + @JSONField(ordinal = 3) + private String toId; + @JSONField(ordinal = 4) + private String message; + @JSONField(ordinal = 5) + private String date; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java new file mode 100644 index 0000000..60bccb5 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +@Data +public class SubUser { + private String id; + private String username; + private String avatarUrl; + + public static SubUser setUser(User user) { + SubUser subUser = new SubUser(); + subUser.setId(user.getOpenid()); + subUser.setUsername(user.getNickname()); + subUser.setAvatarUrl(user.getAvatarUrl()); + return subUser; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java new file mode 100644 index 0000000..054070f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java @@ -0,0 +1,13 @@ +package com.ivmiku.tutorial.entity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author Aurora + */ +@TableName("subscribe") +@Data +public class Subscribe { + private Long id; + private Long subId; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java new file mode 100644 index 0000000..7d99648 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.IgnoreUser; + +public interface BlackListMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java new file mode 100644 index 0000000..ec9ddaa --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.ChatId; + +public interface ChatIdMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java new file mode 100644 index 0000000..32ea471 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Friend; + +public interface FriendMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java new file mode 100644 index 0000000..b6d5ee1 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Message; + +public interface MessageMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java new file mode 100644 index 0000000..53d67c9 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Subscribe; + +public interface SubscribeMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java new file mode 100644 index 0000000..d7e3c88 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java @@ -0,0 +1,236 @@ +package com.ivmiku.tutorial.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ivmiku.tutorial.entity.ChatId; +import com.ivmiku.tutorial.entity.Message; +import com.ivmiku.tutorial.mapper.ChatIdMapper; +import com.ivmiku.tutorial.mapper.MessageMapper; +import com.ivmiku.tutorial.utils.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author Aurora + */ +@Service +public class MessageService { + @Autowired + private MessageMapper messageMapper; + + @Autowired + private ChatIdMapper chatIdMapper; + + @Autowired + private RedisUtil redisUtil; + + /** + * 获取会话id + * @param user1Id 用户1id + * @param user2Id 用户2id + * @return 查询结果 + */ + public String getChatId(String user1Id, String user2Id) { + if (Objects.equals(user1Id, "public") || Objects.equals(user2Id, "public")) { + return "0"; + } + String id1, id2; + if (user1Id.compareTo(user2Id) < 0) { + id1 = user1Id; + id2 = user2Id; + } else { + id1 = user2Id; + id2 = user1Id; + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user1_id", id1); + queryWrapper.eq("user2_id", id2); + ChatId chatId = chatIdMapper.selectOne(queryWrapper); + if (chatId == null) { + chatId = new ChatId(); + chatId.setUser1Id(id1); + chatId.setUser2Id(id2); + chatIdMapper.insert(chatId); + } + return chatIdMapper.selectOne(queryWrapper).getId(); + } + + /** + * 聊天记录写redis + * @param msg 要写入的信息 + * @throws ParseException + */ + @Async + public void insertToRedis(Message msg) throws ParseException { + if (!(msg.getMessage().length() >1000)) { + if (redisUtil.getZsetSize("history:" + msg.getChatId()) >= 50) { + redisUtil.zsetRightPop("history:" + msg.getChatId()); + } + redisUtil.zsetAdd("history:" + msg.getChatId(), msg); + redisUtil.setExpireTime("history:" + msg.getChatId()); + } + } + + /** + * 聊天记录写入mysql + * @param msg 要写入的消息 + */ + @Async + public void insertToMysql(Message msg) { + if (!(msg.getMessage().length() >1000)) { + messageMapper.insert(msg); + } + } + + /** + * 未读消息写入redis + * @param userId 用户id + * @param msg 未读消息 + */ + @Async + public void insertUnreadMsg(String userId, Message msg) { + redisUtil.listAdd("unread:" + userId, msg); + } + + /** + * 获取未读消息列表 + * @param userId 用户id + * @return 查询结果 + */ + public List getUnreadMsg(String userId) { + List result = redisUtil.listGet("unread:" + userId, 0, -1); + redisUtil.listClear(userId); + return result; + } + + /** + * 从数据库获取聊天记录 + * @param chatId 会话id + * @param current 分页参数 + * @param size 分页参数 + * @return 返回的查询结果 + */ + public List getChatHistoryFromDB(String chatId, int current, int size) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page page = new Page<>(current, size); + queryWrapper.eq("chat_id", chatId); + queryWrapper.orderByDesc("date"); + return messageMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * 从数据库获取聊天记录,查询一定范围内 + * @param chatId 会话id + * @param current 分页参数 + * @param size 分页参数 + * @param startDate 开始日期 + * @param endDate 结束日期 + * @return 返回的查询结果 + */ + public List getChatHistoryFromDBByDate(String chatId, int current, int size, String startDate, String endDate) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.between("date", startDate, endDate); + Page page = new Page<>(current, size); + queryWrapper.eq("chat_id", chatId); + queryWrapper.orderByDesc("date"); + return messageMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * redis获取聊天记录 + * @param chatId 会话id + * @param s 开始 + * @param e 结束 + * @return 查询结果 + */ + public List getChatHistoryFromRedis(String chatId, int s, int e) { + return redisUtil.zsetGet("history:" + chatId, s, e); + } + + /** + * 查询聊天记录 + * @param user1Id 用户1id + * @param user2Id 用户2id + * @param page 分页参数 + * @param size 分页参数 + * @return 查询结果 + * @throws ParseException + */ + public List getChatHistory(String user1Id, String user2Id, int page, int size) throws ParseException { + int start = page * size - size; + int end = page * size - 1; + String chatId = getChatId(user1Id, user2Id); + loadCache(chatId); + List result = new ArrayList<>(redisUtil.zsetGet("history:" + chatId, start, end)); + if ((end -start + 1) == result.size()) { + return result; + } + int redisSize = result.size(); + List dbList = getChatHistoryFromDB(chatId, ((end - result.size()) / size) + 1, size); + result.addAll(dbList.subList(redisSize, dbList.size())); + redisUtil.refreshExpire("history:" + chatId); + return result; + } + + /** + * 在一定时间范围内查询聊天记录 + * @param user1Id 用户1id + * @param user2Id 用户2id + * @param startDate 开始日期 + * @param endDate 结束日期 + * @param page 分页参数 + * @param size 分页参数 + * @return 查询结果 + * @throws ParseException + */ + public List getChatHistoryByDate(String user1Id, String user2Id, String startDate, String endDate, int page, int size) throws ParseException { + int start = page * size - size; + int end = page * size - 1; + String chatId = getChatId(user1Id, user2Id); + loadCache(chatId); + List result = new ArrayList<>(redisUtil.zsetGetByDate("history:" + chatId, startDate, endDate, start, size)); + redisUtil.refreshExpire("history:" + chatId); + if (result.size() == (end - start + 1)) { + return result; + } + int redisSize = result.size(); + List dbList = getChatHistoryFromDBByDate(chatId, ((end - result.size()) / size) + 1, size, startDate, endDate).subList(result.size(), size); + result.addAll(dbList.subList(redisSize, dbList.size())); + return result; + } + + /** + * 获取会话列表 + * @param userId 用户id + * @param current 分页参数 + * @param size 分页参数 + * @return 查询结果 + */ + public List getChatList(String userId, int current, int size) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user1_id", userId).or().eq("user2_id", userId); + queryWrapper.orderByDesc("id"); + Page page = new Page<>(current, size); + return chatIdMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * 加载聊天记录到redis + * @param chatId 会话id + * @throws ParseException + */ + public void loadCache(String chatId) throws ParseException { + if (!redisUtil.ifExist("history:" + chatId)) { + List list = getChatHistoryFromDB(chatId, 1, 20); + for (Message message : list) { + insertToRedis(message); + } + } + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java new file mode 100644 index 0000000..8dc4bd3 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java @@ -0,0 +1,120 @@ +package com.ivmiku.tutorial.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import com.ivmiku.tutorial.entity.*; +import com.ivmiku.tutorial.mapper.BlackListMapper; +import com.ivmiku.tutorial.mapper.FriendMapper; +import com.ivmiku.tutorial.mapper.SubscribeMapper; +import com.ivmiku.tutorial.utils.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Aurora + */ +@Service +public class RelationService { + @Autowired + private BlackListMapper blackListMapper; + + @Autowired + private FriendMapper friendMapper; + + @Autowired + private RedisUtil redisUtil; + + @Autowired + private SubscribeMapper subscribeMapper; + + @Autowired + private UserService userService; + + /** + * 屏蔽用户 + * @param userId 用户id + * @param toIgnore 要屏蔽的用户id + */ + public void IgnoreUser(String userId, String toIgnore) { + blackListMapper.insert(new IgnoreUser(userId, toIgnore)); + if (redisUtil.ifExist("blacklist:" + userId)) { + redisUtil.listAdd("blacklist:" + userId, toIgnore); + } + } + + /** + * 查询用户是否屏蔽了该用户 + * @param userId 用户id + * @param ignoreId 要查询的id + * @return 查询结果 + */ + public boolean ifIgnored(String userId, String ignoreId) { + loadCache(userId); + List blackList = redisUtil.getStringList("blacklist:" + userId, 0, -1); + redisUtil.refreshExpire("blacklist:" + userId); + return blackList.contains(ignoreId); + } + + /** + * 加载缓存 + * @param userId 用户id + */ + public void loadCache(String userId) { + if (!redisUtil.ifExist("blacklist:" + userId)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", userId); + List list = blackListMapper.selectList(queryWrapper); + List result = new ArrayList<>(); + if (list != null) { + for (IgnoreUser object : list) { + result.add(object.getToIgnore()); + } + } + for (String toIgnore : result) { + redisUtil.listAdd("blacklist:" + userId, toIgnore); + } + redisUtil.setExpireTime("blacklist:" + userId); + } + } + + public void subscribe(String id, String toId) { + Subscribe subscribe = new Subscribe(); + subscribe.setId(Long.valueOf(id)); + subscribe.setSubId(Long.valueOf(toId)); + subscribeMapper.insert(subscribe); + } + + public List getFanList(String userId, int page, int size) { + List list = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page pager = new Page<>(page, size); + queryWrapper.eq("sub_id", userId); + List array = subscribeMapper.selectPage(pager, queryWrapper).getRecords(); + for (Subscribe subscribe : array) { + String queryId = String.valueOf(subscribe.getId()); + User user = userService.selectUserById(queryId); + SubUser subUser = SubUser.setUser(user); + list.add(subUser); + } + return list; + } + + public List getSubList(String userId, int page, int size) { + List list = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page pager = new Page<>(page, size); + queryWrapper.eq("id", userId); + List array = subscribeMapper.selectPage(pager, queryWrapper).getRecords(); + for (Subscribe subscribe : array) { + String queryId = String.valueOf(subscribe.getSubId()); + User user = userService.selectUserById(queryId); + SubUser subUser = SubUser.setUser(user); + list.add(subUser); + } + return list; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java new file mode 100644 index 0000000..86c6c77 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java @@ -0,0 +1,16 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.User; +import com.ivmiku.tutorial.mapper.UserMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +@Service +public class UserService { + @Resource + private UserMapper userMapper; + + public User selectUserById(String id) { + return userMapper.selectById(id); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java new file mode 100644 index 0000000..8430632 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java @@ -0,0 +1,43 @@ +package com.ivmiku.tutorial.utils; + +import jakarta.annotation.PostConstruct; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +/** + * @author Aurora + */ +public class DateUtil { + /** + * 获取当前时间 + * @return 当前时间字符串 + */ + public static String getCurrentTime() { + Date date = new Date(); + SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return ft.format(date); + } + + /** + * 转换为时间戳 + * @param time 时间字符串 + * @return 时间戳 + * @throws ParseException + */ + public static long toTimeSig(String time) throws ParseException { + SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = ft.parse(time); + return date.getTime(); + } + + /** + * 设置当前时区GMT+8 + */ + @PostConstruct + public void setTimeZone() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java new file mode 100644 index 0000000..da73040 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java @@ -0,0 +1,36 @@ +package com.ivmiku.tutorial.utils; + +import com.ivmiku.tutorial.service.RelationService; +import org.springframework.stereotype.Component; + +/** + * 敏感词检测 + * @author Aurora + */ +@Component +public class MessageUtil { + private static final String[] SENSITIVE = {"你妈", "你妈逼的"}; + + private static RelationService relationService = null; + + public MessageUtil(RelationService relationService) { + MessageUtil.relationService = relationService; + } + + /** + * 查看发送的信息是否含有敏感词 + * @param message 要发送的信息 + * @return 检查结果 + */ + public static boolean checkMessage(String message) { + if (message != null) { + for(String keyword : SENSITIVE) { + if (message.contains(keyword)){ + return true; + } + } + } + return false; + } + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java index 8ff2877..4f03f73 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java @@ -1,9 +1,18 @@ package com.ivmiku.tutorial.utils; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; + /** * @author Aurora */ @@ -12,11 +21,97 @@ public class RedisUtil { @Autowired private RedisTemplate redisTemplate; - public void insertKey(String userId, String sessionKey) { - redisTemplate.opsForValue().set("sessionkey:" + userId, sessionKey); + public void listAdd(String key, Object value) { + redisTemplate.opsForList().leftPush(key, value); } - public String getKey(String userId) { - return (String) redisTemplate.opsForValue().get("sessionkey:" + userId); + public List listGet(String key, int s, int e) { + List list = redisTemplate.opsForList().range(key, s, e); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.class)); + } + } + return result; + } + + public void listClear(String key) { + redisTemplate.opsForList().trim(key, 1, 0); + } + + public Long getListSize(String key) { + return redisTemplate.opsForList().size(key); + } + + public Set getKey() { + return redisTemplate.keys("history:*"); + } + + public Object rightPop(String key) { + return redisTemplate.opsForList().rightPop(key); + } + + public void zsetAdd(String key, Message value) throws ParseException { + redisTemplate.opsForZSet().add(key, value, DateUtil.toTimeSig(value.getDate())); + } + + public List zsetGet(String key, int s, int e) { + Set list = redisTemplate.opsForZSet().reverseRange(key, s, e); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.class)); + } + } + return result; + } + + public Long getzsetSize(String key) { + return redisTemplate.opsForZSet().size(key); + } + + public List zsetGetByDate(String key, String startDate, String endDate, int offset, int count) throws ParseException { + Set list = redisTemplate.opsForZSet().reverseRangeByScore(key, DateUtil.toTimeSig(startDate), DateUtil.toTimeSig(endDate), offset, count); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.class)); + } + } + return result; + } + + public Message zsetRightPop(String key) { + return JSON.parseObject(JSON.toJSONString(Objects.requireNonNull(redisTemplate.opsForZSet().popMin(key)).getValue()), Message.class); + } + + public Long getZsetSize(String key) { + return redisTemplate.opsForZSet().size(key); + } + + public void setExpireTime(String key) { + if (redisTemplate.opsForValue().getOperations().getExpire(key) > 0) { + redisTemplate.expire(key, 3, TimeUnit.DAYS); + } + } + + public void refreshExpire(String key) { + redisTemplate.persist(key); + redisTemplate.expire(key, 3, TimeUnit.DAYS); + } + + public boolean ifExist(String key) { + return Boolean.TRUE.equals(redisTemplate.hasKey(key)); + } + + public List getStringList(String key, int s, int e) { + List list = redisTemplate.opsForList().range(key, s, e); + List result = new ArrayList<>(); + assert list != null; + for (Object object : list) { + result.add((String) object); + } + return result; } }