diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/Main8073.java b/community-8073/src/main/java/com/ivmiku/tutorial/Main8073.java new file mode 100644 index 0000000..8fcc7f6 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/Main8073.java @@ -0,0 +1,15 @@ +package com.ivmiku.tutorial; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(exclude = { + org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration.class +}) +@MapperScan("com.ivmiku.tutorial.mapper") +public class Main8073 { + public static void main(String[] args) { + SpringApplication.run(Main8073.class, args); + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/config/MinioConfig.java b/community-8073/src/main/java/com/ivmiku/tutorial/config/MinioConfig.java new file mode 100644 index 0000000..8ae432c --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/config/MinioConfig.java @@ -0,0 +1,27 @@ +package com.ivmiku.tutorial.config; + +import io.minio.MinioClient; +import io.minio.errors.InvalidEndpointException; +import io.minio.errors.InvalidPortException; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +/*加载yml文件中以minio开头的配置项*/ +@ConfigurationProperties(prefix = "minio") +public class MinioConfig { + /*会自动的对应配置项中对应的key*/ + private String endpoint;//minio.endpoint + private String accessKey; + private String secretKey; + private Integer port; + /*把官方提供的MinioClient客户端注册到IOC容器中*/ + @Bean + public MinioClient getMinioClient() throws InvalidPortException, InvalidEndpointException { + MinioClient minioClient = new MinioClient(getEndpoint(), getPort(), getAccessKey(), getSecretKey(), false); + return minioClient; + } +} \ 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 new file mode 100644 index 0000000..9289589 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommentController.java @@ -0,0 +1,256 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.ivmiku.tutorial.entity.Comment; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.CommentService; +import com.ivmiku.tutorial.service.FileService; +import io.swagger.v3.oas.annotations.Operation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 评论控制器,用于处理评论相关的HTTP请求。 + */ +@RestController +@RequestMapping("/comments") +public class CommentController { + + private static final Logger logger = LoggerFactory.getLogger(CommentController.class); + + @Resource + private CommentService commentService; + + @Resource + private FileService fileService; + + /** + * 创建评论接口。 + * + * @param content 评论内容 + * @param postId 帖子的ID + * @param mentionedUserId 提及的用户ID(可选) + * @param imageFiles 图片文件(可选) + * @param videoFile 视频文件(可选) + * @return 返回操作结果 + */ + @PostMapping("/create") + @Operation(summary = "创建评论") + public Result createComment(@RequestParam("content") String content, + @RequestParam("postId") Long postId, + @RequestParam(value = "mentionedUserId", required = false) String mentionedUserId, + @RequestParam(value = "imageFiles", required = false) MultipartFile[] imageFiles, + @RequestParam(value = "videoFile", required = false) MultipartFile videoFile) { + logger.info("创建评论请求开始,用户ID:{}", StpUtil.getLoginIdAsString()); + + Comment comment = new Comment(); + comment.setUserOpenid(StpUtil.getLoginIdAsString()); + comment.setPostId(postId); + comment.setContent(content); + comment.setParentCommentId(0l); + comment.setMentionedUserId(mentionedUserId); + + try { + // 上传视频 + if (videoFile != null && !videoFile.isEmpty()) { + String uploadResult = fileService.uploadMinio(videoFile); + comment.setVideoUrl(uploadResult); + } + + // 上传图片 + if (imageFiles != null && imageFiles.length > 0) { + StringBuilder imageUrls = new StringBuilder(); + for (MultipartFile file : imageFiles) { + String uploadResult = fileService.uploadMinio(file); + imageUrls.append(uploadResult + ";"); + } + comment.setImageUrls(imageUrls.toString()); + } + } catch (Exception e) { + logger.error("文件上传失败", e); + return Result.error("文件上传失败"); + } + + commentService.createComment(comment); + logger.info("评论创建成功,评论ID:{}", comment.getCommentId()); + return Result.ok(comment); + } + + /** + * 回复评论接口。 + * + * @param parentCommentId 父评论的ID + * @param postId 帖子的ID + * @param content 回复内容 + * @param mentionedUserId 提及的用户ID(可选) + * @param imageFiles 图片文件(可选) + * @param videoFile 视频文件(可选) + * @return 返回操作结果 + */ + @PostMapping("/reply") + @Operation(summary = "回复评论") + public Result replyComment(@RequestParam Long parentCommentId, + @RequestParam Long postId, + @RequestParam String content, + @RequestParam(required = false) String mentionedUserId, + @RequestParam(value = "imageFiles", required = false) MultipartFile[] imageFiles, + @RequestParam(value = "videoFile", required = false) MultipartFile videoFile) { + logger.info("回复评论请求开始,用户ID:{}", StpUtil.getLoginIdAsString()); + + // 检查父评论是否存在 + Comment parentComment = commentService.getCommentById(parentCommentId); + if (parentComment == null) { + logger.warn("父评论ID:{}不存在", parentCommentId); + return Result.error("父评论不存在"); + } + + Comment reply = new Comment(); + reply.setUserOpenid(StpUtil.getLoginIdAsString()); + reply.setParentCommentId(parentCommentId); + reply.setPostId(postId); + reply.setContent(content); + reply.setMentionedUserId(mentionedUserId); + + try { + // 上传视频 + if (videoFile != null && !videoFile.isEmpty()) { + String uploadResult = fileService.uploadMinio(videoFile); + reply.setVideoUrl(uploadResult); + } + + // 上传图片 + if (imageFiles != null && imageFiles.length > 0) { + StringBuilder imageUrls = new StringBuilder(); + for (MultipartFile file : imageFiles) { + String uploadResult = fileService.uploadMinio(file); + imageUrls.append(uploadResult + ";"); + } + reply.setImageUrls(imageUrls.toString()); + } + } catch (Exception e) { + logger.error("文件上传失败", e); + return Result.error("文件上传失败"); + } + + commentService.createComment(reply); + logger.info("评论回复成功,评论ID:{}", reply.getCommentId()); + return Result.ok(reply); + } + + /** + * 获取评论详情接口。 + * + * @param id 评论的唯一标识ID + * @return 返回操作结果和评论详情 + */ + @GetMapping("/get/{id}") + @Operation(summary = "获取评论详情") + public Result getComment(@PathVariable Long id) { + logger.info("获取评论请求开始,评论ID:{}", id); + Comment comment = commentService.getCommentById(id); + if (comment != null) { + logger.info("评论获取成功,评论内容:{}", comment.getContent()); + } else { + logger.warn("获取评论失败,未找到ID为:{}的评论", id); + } + return Result.ok(comment); + } + + /** + * 更新评论接口。 + * + * @param id 要更新的评论的唯一标识ID + * @param comment 更新后的评论数据 + * @return 返回操作结果 + */ + @PutMapping("/update/{id}") + @Operation(summary = "更新评论") + public Result updateComment(@PathVariable Long id, @RequestBody Comment comment) { + logger.info("更新评论请求开始,评论ID:{}", id); + String userId = StpUtil.getLoginIdAsString(); + commentService.updateComment(id, userId, comment); + logger.info("评论更新成功,评论ID:{}", id); + return Result.ok(); + } + + /** + * 删除评论接口。 + * + * @param id 要删除的评论的唯一标识ID + * @return 返回操作结果 + */ + @DeleteMapping("/delete/{id}") + @Operation(summary = "删除评论") + public Result deleteComment(@PathVariable Long id) { + logger.info("删除评论请求开始,评论ID:{}", id); + String userId = StpUtil.getLoginIdAsString(); + commentService.deleteComment(id, userId); + logger.info("评论删除成功,评论ID:{}", id); + return Result.ok(); + } + + /** + * 获取帖子下的所有评论。 + * + * @param postId 帖子的唯一标识ID + * @return 返回操作结果和评论列表 + */ + @GetMapping("/post/{postId}") + @Operation(summary = "获取帖子下的所有评论") + public Result getPostComments(@PathVariable("postId") Long postId) { + logger.info("获取帖子ID:{}的评论列表", postId); + List comments = commentService.getPostComments(postId); + return Result.ok(comments); + } + + /** + * 获取评论下的所有回复。 + * + * @param commentId 评论的唯一标识ID + * @return 返回操作结果和回复列表 + */ + @GetMapping("/replies/{commentId}") + @Operation(summary = "获取评论下的所有回复") + public Result getCommentReplies(@PathVariable Long commentId) { + logger.info("获取评论ID:{}的回复列表", commentId); + List replies = commentService.getCommentReplies(commentId); + return Result.ok(replies); + } + + /** + * @评论接口。 + * + * @param comment 包含@信息的评论数据 + * @return 返回操作结果 + */ + @PostMapping("/mention") + @Operation(summary = "@评论") + public Result mentionUser(@RequestBody Comment comment) { + logger.info("用户ID:{}提交@评论请求", StpUtil.getLoginIdAsString()); + + // 检查父评论是否存在(如果有父评论ID) + if (comment.getParentCommentId() != null) { + Comment parentComment = commentService.getCommentById(comment.getParentCommentId()); + if (parentComment == null) { + logger.warn("父评论ID:{}不存在", comment.getParentCommentId()); + return Result.error("父评论不存在"); + } + } + + // 检查帖子ID是否存在 + if (comment.getPostId() == null) { + logger.warn("帖子ID不能为空"); + return Result.error("帖子ID不能为空"); + } + + comment.setUserOpenid(StpUtil.getLoginIdAsString()); + commentService.createComment(comment); + logger.info("@评论创建成功,评论ID:{}", comment.getCommentId()); + return Result.ok(); + } +} 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 new file mode 100644 index 0000000..c5b0329 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/CommunityController.java @@ -0,0 +1,103 @@ +package com.ivmiku.tutorial.controller; + +import com.ivmiku.tutorial.entity.Community; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.CommunityService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.models.annotations.OpenAPI30; +import org.apiguardian.api.API; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * CommunityController 是处理社区相关请求的控制器类。 + */ +@RestController +@RequestMapping("/communities") + +public class CommunityController { + + // 使用SLF4J的LoggerFactory来创建一个日志记录器 + private static final Logger logger = LoggerFactory.getLogger(CommunityController.class); + + @Resource + private CommunityService communityService; + + /** + * 创建一个新的社区。 + * + * @param community 要创建的社区对象 + * @return 创建结果的响应 + */ + @PostMapping("/create") + @Operation(summary = "创建社区") + public Result createCommunity(@RequestBody Community community) { + communityService.createCommunity(community); // 调用服务层创建社区 + return Result.ok(); // 返回成功结果 + } + + /** + * 根据ID获取社区信息。 + * + * @param id 社区的ID + * @return 包含社区信息的响应 + */ + @GetMapping("/get/{id}") + public Result getCommunity(@PathVariable Long id) { + Community community = communityService.getById(id); // 根据ID获取社区信息 + return Result.ok(community); // 返回包含社区信息的成功结果 + } + + /** + * 更新社区信息。 + * + * @param id 要更新的社区ID + * @param community 更新后的社区对象 + * @return 更新结果的响应 + */ + @PutMapping("/update/{id}") + public Result updateCommunity(@PathVariable Long id, @RequestBody Community community) { + communityService.updateCommunity(id, community); // 调用服务层更新社区信息 + return Result.ok(); // 返回成功结果 + } + + /** + * 删除社区。 + * + * @param id 要删除的社区ID + * @return 删除结果的响应 + */ + @DeleteMapping("/delete/{id}") + public Result deleteCommunity(@PathVariable Long id) { + communityService.deleteCommunity(id); // 调用服务层删除社区 + return Result.ok(); // 返回成功结果 + } + + /** + * 根据name获取社区信息。 + * + * @param name 社区的name + * @return 包含社区信息的响应 + */ + @GetMapping("/getByName/{name}") + public Result getCommunityByName(@PathVariable String name) { + logger.info("社区名称为: {}", name); + List communitys = communityService.getByName(name); // 根据ID获取社区信息 + return Result.ok(communitys); // 返回包含社区信息的成功结果 + } + + /** + * 获取所有社区。 + * + * @return 包含社区信息的响应 + */ + @GetMapping("/list") + public Result getCommunityList() { + List communities = communityService.getCommunityList(); // 获取社区列表 + return Result.ok(communities); // 返回包含社区信息的成功结果 + } +} 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 new file mode 100644 index 0000000..5a4b23c --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/InteractionController.java @@ -0,0 +1,105 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +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; + +/** + * InteractionController 是处理用户与帖子的收藏、点赞以及对评论的点赞功能的控制器类。 + */ +@Slf4j +@RestController +@RequestMapping("/interaction") +public class InteractionController { + + @Resource + private InteractionService interactionService; + + /** + * 收藏帖子 + * + * @param postId 帖子ID + * @return 操作结果 + */ + @PostMapping("/favorite") + public Result favoritePost(@RequestParam Long postId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is favoriting post {}", userOpenid, postId); + interactionService.favoritePost(userOpenid, postId); + return Result.ok(); + } + + /** + * 对帖子点赞 + * + * @param postId 帖子ID + * @return 操作结果 + */ + @PostMapping("/likePost") + public Result likePost(@RequestParam Long postId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is liking post {}", userOpenid, postId); + interactionService.likePost(userOpenid, postId); + return Result.ok(); + } + + /** + * 对评论点赞 + * + * @param commentId 评论ID + * @return 操作结果 + */ + @PostMapping("/likeComment") + public Result likeComment(@RequestParam Long commentId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is liking comment {}", userOpenid, commentId); + interactionService.likeComment(userOpenid, commentId); + return Result.ok(); + } + + /** + * 取消收藏帖子 + * + * @param postId 帖子ID + * @return 操作结果 + */ + @DeleteMapping("/unfavorite") + public Result unfavoritePost(@RequestParam Long postId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is unfavoriting post {}", userOpenid, postId); + interactionService.unfavoritePost(userOpenid, postId); + return Result.ok(); + } + + /** + * 取消对帖子的点赞 + * + * @param postId 帖子ID + * @return 操作结果 + */ + @DeleteMapping("/unlikePost") + public Result unlikePost(@RequestParam Long postId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is unliking post {}", userOpenid, postId); + interactionService.unlikePost(userOpenid, postId); + return Result.ok(); + } + + /** + * 取消对评论的点赞 + * + * @param commentId 评论ID + * @return 操作结果 + */ + @DeleteMapping("/unlikeComment") + public Result unlikeComment(@RequestParam Long commentId) { + String userOpenid = StpUtil.getLoginIdAsString(); + log.info("User {} is unliking comment {}", userOpenid, commentId); + interactionService.unlikeComment(userOpenid, commentId); + 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 new file mode 100644 index 0000000..517f544 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostController.java @@ -0,0 +1,143 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.FileService; +import com.ivmiku.tutorial.service.PostService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.sql.Timestamp; +import java.util.List; + +/** + * 帖子控制器,用于处理帖子相关的HTTP请求。 + */ +@RestController +@RequestMapping("/post") +public class PostController { + + private static final Logger logger = LoggerFactory.getLogger(PostController.class); + + @Resource + private PostService postService; + + @Resource + private FileService fileService; + + @PostMapping("/create") + public Result createPost(@RequestParam("title") String title, + @RequestParam("content") String content, + @RequestParam("communityId") Long communityId, + @RequestParam("imageFiles") MultipartFile[] imageFiles, + @RequestParam("videoFile") MultipartFile videoFile) { + String userId = StpUtil.getLoginIdAsString(); + logger.info("用户ID:{}开始创建帖子", userId); + + Post post = new Post(); + post.setUserOpenid(userId); + post.setTitle(title); + post.setContent(content); + post.setCommunityId(communityId); + try { + // 上传视频 + if (videoFile != null && !videoFile.isEmpty()) { + String uploadResult = fileService.uploadMinio(videoFile); + post.setVideoUrl(uploadResult); + } + + // 上传图片 + if (imageFiles != null && imageFiles.length > 0) { + StringBuilder imageUrls = new StringBuilder(); + for (MultipartFile file : imageFiles) { + String uploadResult = fileService.uploadMinio(file); + imageUrls.append(uploadResult).append(";"); + } + post.setImageUrls(imageUrls.toString()); + } + } catch (Exception e) { + logger.error("文件上传失败", e); + return Result.error("文件上传失败"); + } + + postService.createPost(post); + logger.info("用户ID:{}的帖子创建成功", userId); + return Result.ok(post); + } + + + @GetMapping("/get/{id}") + public Result getPost(@PathVariable Long id) { + logger.info("开始获取帖子ID:{}的详细信息", id); + Post post = postService.getPostById(id); // 调用服务层根据ID查询帖子 + if (post != null) { + logger.info("帖子ID:{}的详细信息获取成功", id); + } else { + logger.warn("帖子ID:{}不存在", id); + } + return Result.ok(post); + } + + @PutMapping("/update/{id}") + public Result updatePost(@PathVariable Long id, @RequestBody Post post) { + String userId = StpUtil.getLoginIdAsString(); // 获取当前登录用户的ID + logger.info("用户ID:{}开始更新帖子ID:{}", userId, id); + postService.updatePost(id, userId, post); // 调用服务层更新帖子 + logger.info("用户ID:{}的帖子ID:{}更新成功", userId, id); + return Result.ok(); + } + + @DeleteMapping("/delete/{id}") + public Result deletePost(@PathVariable Long id) { + String userId = StpUtil.getLoginIdAsString(); // 获取当前登录用户的ID + logger.info("用户ID:{}开始删除帖子ID:{}", userId, id); + postService.deletePost(id, userId); // 调用服务层删除帖子 + logger.info("用户ID:{}的帖子ID:{}删除成功", userId, id); + return Result.ok(); + } + + /** + * 用户获取自己所有帖子的信息 + * @return 当前用户帖子列表 + */ + @GetMapping("/getPostList") + public Result getPostList() { + logger.info("开始获取帖子列表"); + String userId = StpUtil.getLoginIdAsString(); // 获取当前登录用户的ID + List posts = postService.getPostList(userId); + return Result.ok(posts); // 调用服务层获取帖子列表 + } + + /** + * 社区获取自己所有帖子的信息 + * @return 当前用户帖子列表 + */ + @GetMapping("/getCommunityPostList{communityId}") + public Result getCommunityPostList(@PathVariable("communityId") Long communityId) { + logger.info("开始获取帖子列表"); + List posts = postService.getCommunityPostList(communityId); + return Result.ok(posts); // 调用服务层获取帖子列表 + } + + /** + * 获取所有官方创建的帖子 + * @return + */ + @GetMapping("/official") + public List getOfficialPosts() { + return postService.getOfficialPosts(); + } + + /** + * 获取所有非官方创建的帖子 + * @return + */ + @GetMapping("/nonOfficial") + public List getNonOfficialPosts() { + return postService.getNonOfficialPosts(); + } +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostTagController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostTagController.java new file mode 100644 index 0000000..96b606c --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/PostTagController.java @@ -0,0 +1,112 @@ +package com.ivmiku.tutorial.controller; + +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.entity.PostTag; +import com.ivmiku.tutorial.entity.Tag; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.PostTagService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/post-tag") +public class PostTagController { + + // 日志记录器,用于记录控制器中的日志信息 + private static final Logger logger = LoggerFactory.getLogger(PostTagController.class); + + // 通过@Autowired注解自动装配PostTagService服务 + @Autowired + private PostTagService postTagService; + + /** + * 创建帖子标签接口。 + * 用户通过POST请求提交帖子标签数据,服务端接收并保存帖子标签。 + * + * @param postTag 提交的帖子标签数据 + * @return Result 返回操作结果 + */ + @PostMapping("/create") + public Result createPostTag(@RequestBody PostTag postTag) { + logger.info("开始创建帖子标签"); + postTagService.createPostTag(postTag); + logger.info("帖子标签创建成功,ID:{}", postTag.getPostTagId()); + return Result.ok(); + } + + /** + * 获取帖子标签详情接口。 + * 根据帖子标签ID获取帖子标签的详细信息。 + * + * @param id 帖子标签的唯一标识ID + * @return Result 返回操作结果和帖子标签详情 + */ + @GetMapping("/get/{id}") + public Result getPostTag(@PathVariable Long id) { + logger.info("开始获取帖子标签ID:{}的详细信息", id); + PostTag postTag = postTagService.getPostTagById(id); + if (postTag != null) { + logger.info("帖子标签ID:{}的详细信息获取成功", id); + } else { + logger.warn("未找到ID为:{}的帖子标签", id); + } + return Result.ok(postTag); + } + + /** + * 更新帖子标签接口。 + * 用户通过PUT请求提交更新后的帖子标签数据,服务端接收并更新帖子标签。 + * + * @param id 要更新的帖子标签的唯一标识ID + * @param postTag 更新后的帖子标签数据 + * @return Result 返回操作结果 + */ + @PutMapping("/update/{id}") + public Result updatePostTag(@PathVariable Long id, @RequestBody PostTag postTag) { + logger.info("开始更新帖子标签ID:{}", id); + postTagService.updatePostTag(id, postTag); + logger.info("帖子标签ID:{}更新成功", id); + return Result.ok(); + } + + /** + * 删除帖子标签接口。 + * 根据帖子标签ID删除指定的帖子标签。 + * + * @param id 要删除的帖子标签的唯一标识ID + * @return Result 返回操作结果 + */ + @DeleteMapping("/delete/{id}") + public Result deletePostTag(@PathVariable Long id) { + logger.info("开始删除帖子标签ID:{}", id); + postTagService.deletePostTag(id); + logger.info("帖子标签ID:{}删除成功", id); + return Result.ok(); + } + + /** + * 获取当前帖子所有标签列表接口。 + * @return + */ + @GetMapping("/getPostTagList{postId}") + public Result getPostTagList(@PathVariable("postId") Long postId) { + logger.info("开始获取帖子标签列表"); + List tags = postTagService.getPostTagList(postId); + return Result.ok(tags); + } + + /** + * 获取当前标签所有帖子列表接口。 + * @return + */ + @GetMapping("/getTagPostList{tagId}") + public Result getTagPostList(@PathVariable("tagId") Long tagId) { + logger.info("开始获取帖子标签列表"); + List posts = postTagService.getTagPostList(tagId); + return Result.ok(posts); + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/controller/TagController.java b/community-8073/src/main/java/com/ivmiku/tutorial/controller/TagController.java new file mode 100644 index 0000000..c8ef367 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/controller/TagController.java @@ -0,0 +1,114 @@ +package com.ivmiku.tutorial.controller; + +import com.ivmiku.tutorial.entity.Tag; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.PostTagService; +import com.ivmiku.tutorial.service.TagService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/tag") +public class TagController { + + // 日志记录器,用于记录控制器中的日志信息 + private static final Logger logger = LoggerFactory.getLogger(TagController.class); + + // 通过@Autowired注解自动装配TagService服务 + @Autowired + private TagService tagService; + + @Autowired + private PostTagService postTagService; + + /** + * 创建标签接口。 + * 用户通过POST请求提交标签数据,服务端接收并保存标签。 + * + * @param tag 提交的标签数据 + * @return Result 返回操作结果 + */ + @PostMapping("/create") + public Result createTag(@RequestBody Tag tag) { + logger.info("开始创建标签:{}", tag.getName()); + tagService.createTag(tag); + logger.info("标签创建成功,标签ID:{}", tag.getTagId()); + return Result.ok(); + } + + /** + * 获取标签详情接口。 + * 根据标签ID获取标签的详细信息。 + * + * @param id 标签的唯一标识ID + * @return Result 返回操作结果和标签详情 + */ + @GetMapping("/get/{id}") + public Result getTag(@PathVariable Long id) { + logger.info("开始获取标签ID:{}的详细信息", id); + Tag tag = tagService.getTagById(id); + if (tag != null) { + logger.info("标签ID:{}的详细信息获取成功", id); + } else { + logger.warn("未找到ID为:{}的标签", id); + } + return Result.ok(tag); + } + + /** + * 更新标签接口。 + * 用户通过PUT请求提交更新后的标签数据,服务端接收并更新标签。 + * + * @param id 要更新的标签的唯一标识ID + * @param tag 更新后的标签数据 + * @return Result 返回操作结果 + */ + @PutMapping("/update/{id}") + public Result updateTag(@PathVariable Long id, @RequestBody Tag tag) { + logger.info("开始更新标签ID:{}的信息", id); + tagService.updateTag(id, tag); + logger.info("标签ID:{}更新成功", id); + return Result.ok(); + } + + /** + * 删除标签接口。 + * 根据标签ID删除指定的标签。 + * + * @param id 要删除的标签的唯一标识ID + * @return Result 返回操作结果 + */ + @DeleteMapping("/delete/{id}") + public Result deleteTag(@PathVariable Long id) { + logger.info("开始删除标签ID:{}", id); + tagService.deleteTag(id); + logger.info("标签ID:{}删除成功", id); + return Result.ok(); + } + + /** + * 获取所有标签详情接口。 + * + * @return Result 返回操作结果和标签详情 + */ + @GetMapping("/getTagList") + public Result getTagList() { + List tags = tagService.getTagList(); + return Result.ok(tags); + } + + /** + * 获取排序后的标签列表接口。 + * @return Result 返回操作结果和排序后的标签列表 + */ + @GetMapping("/sorted-tag-list") + public Result getSortedTagList() { + logger.info("开始获取排序后的标签列表"); + List tags = postTagService.getSortedTagList(); + return Result.ok(tags); + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Comment.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Comment.java new file mode 100644 index 0000000..5eb554c --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Comment.java @@ -0,0 +1,44 @@ +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 java.util.Date; +import lombok.Data; + +/** + * @TableName comment + */ +@TableName(value ="comment") +@Data +public class Comment implements Serializable { + @TableId(type = IdType.AUTO) + private Long commentId; + + private String userOpenid; + + private Long postId; + + private String content; + + private Long parentCommentId; + + private Integer isDeleted; + + private Date createdAt; + + private Date updatedAt; + + @TableField(exist = false) + private String mentionedUserId; // @功能提到的用户ID + + @TableField(exist = false) + private String imageUrls; // 存储图片URL(多个URL用分号分隔) + + @TableField(exist = false) + private String videoUrl; // 存储视频URL + + private static final long serialVersionUID = 1L; +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Community.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Community.java new file mode 100644 index 0000000..72bdf04 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Community.java @@ -0,0 +1,24 @@ +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 community + */ +@TableName(value ="community") +@Data +public class Community implements Serializable { + @TableId + private Long communityId; + + private String name; + + private String description; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Favorite.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Favorite.java new file mode 100644 index 0000000..7d38acf --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Favorite.java @@ -0,0 +1,26 @@ +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 favorite + */ +@TableName(value ="favorite") +@Data +public class Favorite implements Serializable { + @TableId + private Long id; + + private String userOpenid; + + private Long postId; + + private Integer isDeleted; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Likee.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Likee.java new file mode 100644 index 0000000..f972a11 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Likee.java @@ -0,0 +1,26 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * @TableName like + */ +@TableName(value ="likee") +@Data +public class Likee implements Serializable { + @TableId + private Long id; + + private String userOpenid; + + private Long postId; + + private Long commentId; + + private Integer isDeleted; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Post.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Post.java new file mode 100644 index 0000000..30497a5 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Post.java @@ -0,0 +1,41 @@ +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 java.util.Date; +import lombok.Data; + +/** + * @TableName post + */ +@TableName(value ="post") +@Data +public class Post implements Serializable { + @TableId + private Long postId; + + private String userOpenid; + + private Long communityId; + + private String title; + + private String content; + + private String videoUrl; // 新增字段,存储视频URL + + private String imageUrls; // 新增字段,存储图片URL(多个URL用分号分隔) + + private Integer isDeleted; + + private Integer isOfficial; // 新增字段,标记是否为官方创建的帖子 + + private Date createdAt; + + private Date updatedAt; + + private static final long serialVersionUID = 1L; +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/PostTag.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/PostTag.java new file mode 100644 index 0000000..f33175a --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/PostTag.java @@ -0,0 +1,22 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * @TableName posttag + */ +@TableName(value ="posttag") +@Data +public class PostTag implements Serializable { + @TableId + private Long postTagId; + + private Long postId; + + private Long tagId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Tag.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Tag.java new file mode 100644 index 0000000..f6de7ef --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Tag.java @@ -0,0 +1,25 @@ +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 tag + */ +@TableName(value ="tag") +@Data +public class Tag implements Serializable { + @TableId + private Long tagId; + + private String name; + + // 新增的字段,用于区分标签是否为官方标签 + private Integer isOfficial; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/User.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/User.java new file mode 100644 index 0000000..7dd39f4 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/User.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; + +@Data +@TableName("User") +public class User { + @TableId + private String openid; + private String nickname; + private String avatarUrl; +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/entity/Usercommunity.java b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Usercommunity.java new file mode 100644 index 0000000..325cb02 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/entity/Usercommunity.java @@ -0,0 +1,24 @@ +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 usercommunity + */ +@TableName(value ="usercommunity") +@Data +public class Usercommunity implements Serializable { + @TableId + private Long userCommunityId; + + private String userOpenid; + + private Long communityId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommentMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommentMapper.java new file mode 100644 index 0000000..b92f252 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommentMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Comment; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【comment】的数据库操作Mapper +* @createDate 2024-08-05 14:14:14 +* @Entity com.ivmiku.tutorial.entity.Comment +*/ +public interface CommentMapper extends BaseMapper { + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunityMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunityMapper.java new file mode 100644 index 0000000..12b11b3 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/CommunityMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Community; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【community】的数据库操作Mapper +* @createDate 2024-08-05 14:15:04 +* @Entity com.ivmiku.tutorial.entity.Community +*/ +public interface CommunityMapper extends BaseMapper { + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/FavoriteMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/FavoriteMapper.java new file mode 100644 index 0000000..342f7f8 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/FavoriteMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Favorite; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【favorite】的数据库操作Mapper +* @createDate 2024-08-05 14:20:25 +* @Entity com.ivmiku.tutorial.entity.Favorite +*/ +public interface FavoriteMapper 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 new file mode 100644 index 0000000..b951e47 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/LikeMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Likee; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author rog +* @description 针对表【like】的数据库操作Mapper +* @createDate 2024-08-05 14:20:52 +* @Entity com.ivmiku.tutorial.entity.Like +*/ +public interface LikeMapper extends BaseMapper { + +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostMapper.java new file mode 100644 index 0000000..0a93921 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostMapper.java @@ -0,0 +1,24 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Post; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** +* @author rog +* @description 针对表【post】的数据库操作Mapper +* @createDate 2024-08-05 14:15:26 +* @Entity com.ivmiku.tutorial.entity.Post +*/ +public interface PostMapper extends BaseMapper { + + + List getTagPostList(Long tagId); +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostTagMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostTagMapper.java new file mode 100644 index 0000000..d4dca81 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/PostTagMapper.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.entity.PostTag; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** +* @author rog +* @description 针对表【posttag】的数据库操作Mapper +* @createDate 2024-08-05 14:15:42 +* @Entity com.ivmiku.tutorial.entity.Posttag +*/ +public interface PostTagMapper extends BaseMapper { + + +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/TagMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/TagMapper.java new file mode 100644 index 0000000..233c9e1 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/TagMapper.java @@ -0,0 +1,33 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.entity.Tag; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** +* @author rog +* @description 针对表【tag】的数据库操作Mapper +* @createDate 2024-08-05 14:15:58 +* @Entity com.ivmiku.tutorial.entity.Tag +*/ +public interface TagMapper extends BaseMapper { + + List getPostTagList(@Param("postId") Long postId); + + + // 获取按条件排序的标签列表 + @Select("SELECT t.*, COUNT(pt.post_id) AS postCount " + + "FROM tag t " + + "LEFT JOIN posttag pt ON t.tag_id = pt.tag_id " + + "GROUP BY t.tag_id " + + "ORDER BY t.is_official DESC, postCount DESC") + List getSortedTagList(); +} + + + + diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/mapper/UsercommunityMapper.java b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/UsercommunityMapper.java new file mode 100644 index 0000000..01a5d63 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/mapper/UsercommunityMapper.java @@ -0,0 +1,21 @@ +package com.ivmiku.tutorial.mapper; + +import com.ivmiku.tutorial.entity.Community; +import com.ivmiku.tutorial.entity.Usercommunity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** +* @author rog +* @description 针对表【usercommunity】的数据库操作Mapper +* @createDate 2024-08-05 14:53:55 +* @Entity com.ivmiku.tutorial.entity.Usercommunity +*/ + +public interface UsercommunityMapper extends BaseMapper { + + List getCommunityList(@Param("user_openid") String userId); +} 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 new file mode 100644 index 0000000..a5b1573 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommentService.java @@ -0,0 +1,71 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Comment; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.sql.Timestamp; +import java.util.List; + +/** + * 评论服务接口,定义评论相关的业务操作方法。 + */ +public interface CommentService extends IService { + /** + * 保存评论。 + * 将评论数据保存到数据库。 + * + * @param comment 要保存的评论数据 + */ + + void createComment(Comment comment); + + /** + * 根据ID获取评论详情。 + * 从数据库中根据评论ID获取评论的详细信息。 + * + * @param commentId 评论的唯一标识ID + * @return Comment 返回查询到的评论对象 + */ + + Comment getCommentById(Long commentId); + + /** + * 更新评论。 + * 根据评论ID和用户ID更新评论内容。 + * + * @param commentId 要更新的评论的唯一标识ID + * @param userId 更新评论的用户ID + * @param comment 更新后的评论数据 + */ + + void updateComment(Long commentId, String userId, Comment comment); + /** + * 删除评论。 + * 根据评论ID删除指定的评论。 + * + * @param commentId 要删除的评论的唯一标识ID + * @param userId 删除评论的用户ID + */ + + void deleteComment(Long commentId, String userId); + + List getPostComments(Long postId); + + List getCommentReplies(Long commentId); + + + /** + * 回复评论。 + * 用户通过POST请求提交回复数据,服务端接收并保存回复。 + * + * @param parentCommentId 父评论的ID + * @param postId 帖子的ID + * @param content 回复内容 + * @param mentionedUserId (可选)@的用户ID + * @return Result 返回操作结果 + */ + void createReply(Long parentCommentId, Long postId, String content, String mentionedUserId); + + + +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunityService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunityService.java new file mode 100644 index 0000000..22cab09 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/CommunityService.java @@ -0,0 +1,49 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Community; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +public interface CommunityService extends IService { + + /** + * 创建社区。 + * 根据社区信息创建一个新的社区记录。 + * + * @param community 社区信息 + */ + void createCommunity(Community community); + + /** + * 更新社区信息。 + * 根据社区ID更新社区的相关信息。 + * + * @param id 社区的唯一标识ID + * @param community 更新后的社区信息 + */ + void updateCommunity(Long id, Community community); + + /** + * 删除社区。 + * 根据社区ID删除指定的社区记录。 + * + * @param id 社区的唯一标识ID + */ + void deleteCommunity(Long id); + + /** + * 根据社区名称获取社区信息。 + * + * @param name 社区名称 + * @return 社区信息 + */ + List getByName(String name); + + /** + * 获取社区列表。 + * + * @return 社区列表 + */ + List getCommunityList(); +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/FileService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/FileService.java new file mode 100644 index 0000000..fe316b9 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/FileService.java @@ -0,0 +1,14 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.response.Result; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.UUID; + +public interface FileService { + + String uploadMinio(MultipartFile file) throws Exception; + + Result downLoadMinio(String url, HttpServletResponse response) throws Exception; +} 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 new file mode 100644 index 0000000..981a552 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/InteractionService.java @@ -0,0 +1,13 @@ +package com.ivmiku.tutorial.service; + +/** + * InteractionService接口定义用户对帖子和评论的收藏与点赞操作。 + */ +public interface InteractionService { + void favoritePost(String userOpenid, Long postId); + void unfavoritePost(String userOpenid, Long postId); + void likePost(String userOpenid, Long postId); + void unlikePost(String userOpenid, Long postId); + void likeComment(String userOpenid, Long commentId); + void unlikeComment(String userOpenid, Long commentId); +} 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 new file mode 100644 index 0000000..0749157 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/PostService.java @@ -0,0 +1,21 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Post; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +public interface PostService extends IService { + void createPost(Post post); + Post getPostById(Long postId); + void updatePost(Long postId, String userId, Post post); + void deletePost(Long postId, String userId); + + List getPostList(String userId); + + List getCommunityPostList(Long communityId); + + List getOfficialPosts(); // 新增获取官方帖子的方法 + + List getNonOfficialPosts(); // 新增获取非官方帖子的方法 +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/PostTagService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/PostTagService.java new file mode 100644 index 0000000..049193e --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/PostTagService.java @@ -0,0 +1,54 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.entity.PostTag; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ivmiku.tutorial.entity.Tag; + +import java.util.List; + +public interface PostTagService extends IService { + /** + * 创建帖子标签。 + * 将帖子标签数据保存到数据库。 + * + * @param postTag 要保存的帖子标签数据 + */ + + void createPostTag(PostTag postTag); + + /** + * 根据ID获取帖子标签详情。 + * 从数据库中根据帖子标签ID获取帖子标签的详细信息。 + * + * @param postTagId 帖子标签的唯一标识ID + * @return PostTag 返回查询到的帖子标签对象 + */ + + PostTag getPostTagById(Long postTagId); + + /** + * 更新帖子标签。 + * 根据帖子标签ID更新帖子标签的内容。 + * + * @param postTagId 要更新的帖子标签的唯一标识ID + * @param postTag 更新后的帖子标签数据 + */ + + void updatePostTag(Long postTagId, PostTag postTag); + + /** + * 删除帖子标签。 + * 根据帖子标签ID删除指定的帖子标签。 + * + * @param postTagId 要删除的帖子标签的唯一标识ID + */ + + void deletePostTag(Long postTagId); + + List getPostTagList(Long postId); + + List getTagPostList(Long tagId); + + List getSortedTagList(); +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/TagService.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/TagService.java new file mode 100644 index 0000000..e54a401 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/TagService.java @@ -0,0 +1,37 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.Tag; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +public interface TagService extends IService { + /** + * 创建标签 + * @param tag 标签实体对象 + */ + void createTag(Tag tag); + + /** + * 根据ID获取标签 + * @param tagId 标签ID + * @return 标签实体对象 + */ + Tag getTagById(Long tagId); + + /** + * 更新标签信息 + * @param tagId 标签ID + * @param tag 更新后的标签实体对象 + */ + void updateTag(Long tagId, Tag tag); + + /** + * 删除标签 + * @param tagId 标签ID + */ + + void deleteTag(Long tagId); + + List getTagList(); +} 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 new file mode 100644 index 0000000..51337ef --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommentServiceImpl.java @@ -0,0 +1,172 @@ +package com.ivmiku.tutorial.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ivmiku.tutorial.entity.Comment; +import com.ivmiku.tutorial.mapper.CommentMapper; +import com.ivmiku.tutorial.service.CommentService; +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 javax.annotation.Resource; +import java.sql.Timestamp; +import java.util.List; + +/** + * 评论服务实现类。 + */ +@Service +public class CommentServiceImpl extends ServiceImpl implements CommentService { + + // 日志记录器,用于记录服务层的日志信息 + private static final Logger logger = LoggerFactory.getLogger(CommentServiceImpl.class); + + @Autowired + protected CommentMapper commentMapper; + + /** + * 保存评论。 + * 将评论数据保存到数据库。 + * + * @param comment 要保存的评论数据 + */ + @Override + public void createComment(Comment comment) { + logger.info("开始保存评论数据"); + comment.setCreatedAt(new Timestamp(System.currentTimeMillis())); + comment.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + comment.setIsDeleted(0); + + save(comment); + logger.info("评论数据保存成功,评论ID:{}", comment.getCommentId()); + } + + /** + * 根据ID获取评论详情。 + * 从数据库中根据评论ID获取评论的详细信息。 + * + * @param commentId 评论的唯一标识ID + * @return Comment 返回查询到的评论对象 + */ + @Override + public Comment getCommentById(Long commentId) { + logger.info("开始根据ID获取评论详情,评论ID:{}", commentId); + return getById(commentId); + } + + /** + * 更新评论。 + * 根据评论ID和用户ID更新评论内容。 + * + * @param commentId 要更新的评论的唯一标识ID + * @param userId 更新评论的用户ID + * @param comment 更新后的评论数据 + */ + @Override + public void updateComment(Long commentId, String userId, Comment comment) { + logger.info("用户ID:{}开始更新评论,评论ID:{}", userId, commentId); + comment.setCommentId(commentId); + comment.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + updateById(comment); + logger.info("用户ID:{}的评论ID:{}更新成功", userId, commentId); + } + + /** + * 删除评论。 + * 根据评论ID删除指定的评论。 + * + * @param commentId 要删除的评论的唯一标识ID + * @param userId 删除评论的用户ID + */ + @Override + public void deleteComment(Long commentId, String userId) { + logger.info("用户ID:{}开始删除评论,评论ID:{}", userId, commentId); + Comment comment = getById(commentId); + if (comment != null) { + comment.setIsDeleted(1); // 标记为已删除 + comment.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + updateById(comment); + logger.info("用户ID:{}的评论ID:{}删除成功", userId, commentId); + } else { + logger.warn("尝试删除的评论ID:{}不存在", commentId); + } + } + + /** + * 获取帖子下的所有评论。 + * + * @param postId 帖子的唯一标识ID + * @return List 返回评论列表 + */ + @Override + public List getPostComments(Long postId) { + logger.info("开始获取帖子ID:{}的评论列表", postId); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Comment::getPostId, postId).eq(Comment::getIsDeleted, 0); + List comments = commentMapper.selectList(wrapper); + if (comments != null) { + logger.info("获取帖子ID:{}的评论列表成功", postId); + } else { + logger.warn("帖子ID:{}的评论列表为空", postId); + } + return comments; + } + + /** + * 获取评论下的所有回复。 + * + * @param commentId 评论的唯一标识ID + * @return List 返回回复列表 + */ + @Override + public List getCommentReplies(Long commentId) { + logger.info("开始获取评论ID:{}的回复列表", commentId); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Comment::getParentCommentId, commentId).eq(Comment::getIsDeleted, 0); + List replies = commentMapper.selectList(wrapper); + if (replies != null) { + logger.info("获取评论ID:{}的回复列表成功", commentId); + } else { + logger.warn("评论ID:{}的回复列表为空", commentId); + } + return replies; + } + /** + * 回复评论。 + * 用户通过POST请求提交回复数据,服务端接收并保存回复。 + * + * @param parentCommentId 父评论的ID + * @param postId 帖子的ID + * @param content 回复内容 + * @param mentionedUserId (可选)@的用户ID + * @return Result 返回操作结果 + */ + @Override + public void createReply(Long parentCommentId, Long postId, String content, String mentionedUserId) { + logger.info("回复评论请求开始,父评论ID:{},帖子ID:{}", parentCommentId, postId); + + // 检查父评论是否存在 + Comment parentComment = getCommentById(parentCommentId); + if (parentComment == null) { + logger.warn("父评论ID:{}不存在", parentCommentId); + throw new RuntimeException("父评论不存在"); + } + + // 创建回复评论对象 + Comment reply = new Comment(); + reply.setUserOpenid(StpUtil.getLoginIdAsString()); + reply.setParentCommentId(parentCommentId); + reply.setPostId(postId); + reply.setContent(content); + if (mentionedUserId != null) { + reply.setMentionedUserId(mentionedUserId); + } + createComment(reply); + + logger.info("评论回复成功,评论ID:{}", reply.getCommentId()); + } + +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunityServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunityServiceImpl.java new file mode 100644 index 0000000..41a47b2 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/CommunityServiceImpl.java @@ -0,0 +1,91 @@ +package com.ivmiku.tutorial.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ivmiku.tutorial.entity.Community; +import com.ivmiku.tutorial.mapper.CommunityMapper; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.CommunityService; +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.util.List; + +/** + * 社区服务实现类。 + */ +@Service +public class CommunityServiceImpl extends ServiceImpl implements CommunityService { + + // 日志记录器,用于记录服务层的日志信息 + private static final Logger logger = LoggerFactory.getLogger(CommunityServiceImpl.class); + + @Autowired + private CommunityMapper communityMapper; + + /** + * 创建社区。 + * 根据社区信息创建一个新的社区记录。 + * + * @param community 社区信息 + */ + @Override + public void createCommunity(Community community) { + logger.info("开始创建社区"); + save(community); + logger.info("社区创建成功,社区ID:{}", community.getCommunityId()); + } + + /** + * 更新社区信息。 + * 根据社区ID更新社区的相关信息。 + * + * @param id 社区的唯一标识ID + * @param community 更新后的社区信息 + */ + @Override + public void updateCommunity(Long id, Community community) { + logger.info("开始更新社区信息,社区ID:{}", id); + community.setCommunityId(id); + updateById(community); + logger.info("社区信息更新成功,社区ID:{}", id); + } + + /** + * 删除社区。 + * 根据社区ID删除指定的社区记录。 + * + * @param id 社区的唯一标识ID + */ + @Override + public void deleteCommunity(Long id) { + logger.info("开始删除社区,社区ID:{}", id); + removeById(id); + logger.info("社区删除成功,社区ID:{}", id); + } + + /** + * 根据社区名称获取社区信息。 + * @param name + * @return + */ + @Override + public List getByName(String name) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + //根据社区名称模糊查询 + wrapper.like(Community::getName, name); + List communitys = communityMapper.selectList(wrapper); + return communitys; + } + + /** + * 获取社区列表 + * @return 社区列表 + */ + @Override + public List getCommunityList() { + return communityMapper.selectList(null); + } +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/FileServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..782f20b --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/FileServiceImpl.java @@ -0,0 +1,49 @@ +package com.ivmiku.tutorial.service.impl; + + +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.FileService; +import com.ivmiku.tutorial.util.MinioClientUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.UUID; + +@Service +public class FileServiceImpl implements FileService { + @Autowired + private MinioClientUtil minioClientUtil; + + @Value("${minio.endpoint}") + private String endpoint; + + @Value("${minio.port}") + private String port; + + @Value("${minio.bucketName}") + private String bucketName; + + @Override + public String uploadMinio(MultipartFile file) throws Exception { + String filename = file.getOriginalFilename(); + String uuid = UUID.randomUUID().toString(); + String imgType = filename.substring(filename.lastIndexOf(".")); + String fileName = uuid + imgType; + + boolean flag = minioClientUtil.putObject(fileName, file.getInputStream()); + String path = "http://" + endpoint + ":" + port + "/" + bucketName + "/" + fileName; + return flag ? path : "上传失败"; + } + + + @Override + public Result downLoadMinio(String url, HttpServletResponse response) throws Exception { + String trim = url.trim(); + String path = trim.substring(trim.indexOf("/", 1), trim.length()); + minioClientUtil.getObject(path, response); + return Result.ok(); + } +} 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 new file mode 100644 index 0000000..4ff63bf --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/InteractionServiceImpl.java @@ -0,0 +1,98 @@ +package com.ivmiku.tutorial.service.impl; + +import com.ivmiku.tutorial.entity.Favorite; +import com.ivmiku.tutorial.entity.Likee; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * InteractionServiceImpl 实现了 InteractionService 接口,处理用户对帖子和评论的收藏与点赞操作。 + */ +@Slf4j +@Service +public class InteractionServiceImpl implements InteractionService { + + @Resource + private FavoriteMapper favoriteMapper; + + @Resource + private LikeMapper likeMapper; + + @Override + public void favoritePost(String userOpenid, Long postId) { + log.info("User {} is favoriting post {}", userOpenid, postId); + Favorite favorite = new Favorite(); + favorite.setUserOpenid(userOpenid); + favorite.setPostId(postId); + favorite.setIsDeleted(0); + favoriteMapper.insert(favorite); + } + + @Override + public void unfavoritePost(String userOpenid, Long postId) { + log.info("User {} is unfavoriting post {}", userOpenid, postId); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_openid", userOpenid) + .eq("post_id", postId) + .eq("is_deleted", 0); + Favorite favorite = favoriteMapper.selectOne(queryWrapper); + if (favorite != null) { + favorite.setIsDeleted(1); + favoriteMapper.updateById(favorite); + } + } + + @Override + public void likePost(String userOpenid, Long postId) { + log.info("User {} is liking post {}", userOpenid, postId); + Likee likee = new Likee(); + likee.setUserOpenid(userOpenid); + likee.setPostId(postId); + likee.setIsDeleted(0); + likeMapper.insert(likee); + } + + @Override + public void unlikePost(String userOpenid, Long postId) { + log.info("User {} is unliking post {}", userOpenid, postId); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_openid", userOpenid) + .eq("post_id", postId) + .eq("is_deleted", 0); + Likee likee = likeMapper.selectOne(queryWrapper); + if (likee != null) { + likee.setIsDeleted(1); + likeMapper.updateById(likee); + } + } + + @Override + public void likeComment(String userOpenid, Long commentId) { + log.info("User {} is liking comment {}", userOpenid, commentId); + Likee likee = new Likee(); + likee.setUserOpenid(userOpenid); + likee.setCommentId(commentId); + likee.setIsDeleted(0); + likeMapper.insert(likee); + } + + @Override + public void unlikeComment(String userOpenid, Long commentId) { + log.info("User {} is unliking comment {}", userOpenid, commentId); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_openid", userOpenid) + .eq("comment_id", commentId) + .eq("is_deleted", 0); + Likee likee = likeMapper.selectOne(queryWrapper); + if (likee != null) { + likee.setIsDeleted(1); + likeMapper.updateById(likee); + } + } +} 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 new file mode 100644 index 0000000..8a39929 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostServiceImpl.java @@ -0,0 +1,99 @@ +package com.ivmiku.tutorial.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.mapper.PostMapper; +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 javax.annotation.Resource; +import java.sql.Timestamp; +import java.util.List; + +@Service +public class PostServiceImpl extends ServiceImpl implements PostService { + + private static final Logger logger = LoggerFactory.getLogger(PostServiceImpl.class); + + @Autowired + private PostMapper postMapper; + + @Override + public void createPost(Post post) { + logger.info("开始创建帖子"); + post.setCreatedAt(new Timestamp(System.currentTimeMillis())); // 设置创建时间 + post.setUpdatedAt(new Timestamp(System.currentTimeMillis())); // 设置更新时间 + post.setIsDeleted(0); // 初始化为未删除 + save(post); + logger.info("帖子创建成功,帖子ID:{}", post.getPostId()); + } + + @Override + public Post getPostById(Long postId) { + logger.info("开始根据ID获取帖子详情,帖子ID:{}", postId); + return getById(postId); + } + + @Override + public void updatePost(Long postId, String userId, Post post) { + logger.info("用户ID:{}开始更新帖子,帖子ID:{}", userId, postId); + post.setPostId(postId); + post.setUpdatedAt(new Timestamp(System.currentTimeMillis())); // 更新修改时间 + updateById(post); + logger.info("用户ID:{}的帖子ID:{}更新成功", userId, postId); + } + + @Override + public void deletePost(Long postId, String userId) { + logger.info("用户ID:{}开始删除帖子,帖子ID:{}", userId, postId); + Post post = getById(postId); + if (post != null) { + post.setIsDeleted(1); // 设置为已删除 + post.setUpdatedAt(new Timestamp(System.currentTimeMillis())); // 更新修改时间 + updateById(post); + logger.info("用户ID:{}的帖子ID:{}删除成功", userId, postId); + } else { + logger.warn("尝试删除的帖子ID:{}不存在", postId); + } + } + + @Override + public List getPostList(String userId) { + logger.info("用户ID:{}开始获取帖子列表", userId); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Post::getUserOpenid, userId); + List posts = postMapper.selectList(wrapper); + return posts; + } + + @Override + public List getCommunityPostList(Long communityId) { + logger.info("开始获取社区ID:{}的帖子列表", communityId); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Post::getCommunityId, communityId); + List posts = postMapper.selectList(wrapper); + return posts; + } + + @Override + public List getOfficialPosts() { + logger.info("开始获取所有官方创建的帖子"); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Post::getIsOfficial, 1); + List posts = postMapper.selectList(wrapper); + return posts; + } + + @Override + public List getNonOfficialPosts() { + logger.info("开始获取所有非官方创建的帖子"); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Post::getIsOfficial, 0); + List posts = postMapper.selectList(wrapper); + return posts; + } +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostTagServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostTagServiceImpl.java new file mode 100644 index 0000000..c15b75a --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/PostTagServiceImpl.java @@ -0,0 +1,107 @@ +package com.ivmiku.tutorial.service.impl; + +import com.ivmiku.tutorial.entity.Post; +import com.ivmiku.tutorial.entity.PostTag; +import com.ivmiku.tutorial.entity.Tag; +import com.ivmiku.tutorial.mapper.PostMapper; +import com.ivmiku.tutorial.mapper.PostTagMapper; +import com.ivmiku.tutorial.mapper.TagMapper; +import com.ivmiku.tutorial.service.PostTagService; +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.util.List; + +/** + * 帖子标签服务实现类。 + */ +@Service +public class PostTagServiceImpl extends ServiceImpl implements PostTagService { + + // 日志记录器,用于记录服务层的日志信息 + private static final Logger logger = LoggerFactory.getLogger(PostTagServiceImpl.class); + + @Autowired + private TagMapper tagMapper; + + @Autowired + private PostMapper postMapper; + + @Autowired + private PostTagMapper postTagMapper; + + /** + * 创建帖子标签。 + * 将帖子标签数据保存到数据库。 + * + * @param postTag 要保存的帖子标签数据 + */ + @Override + public void createPostTag(PostTag postTag) { + logger.info("开始创建帖子标签"); + save(postTag); + logger.info("帖子标签创建成功,标签ID:{}", postTag.getPostTagId()); + } + + /** + * 根据ID获取帖子标签详情。 + * 从数据库中根据帖子标签ID获取帖子标签的详细信息。 + * + * @param postTagId 帖子标签的唯一标识ID + * @return PostTag 返回查询到的帖子标签对象 + */ + @Override + public PostTag getPostTagById(Long postTagId) { + logger.info("开始根据ID获取帖子标签详情,标签ID:{}", postTagId); + return getById(postTagId); + } + + /** + * 更新帖子标签。 + * 根据帖子标签ID更新帖子标签的内容。 + * + * @param postTagId 要更新的帖子标签的唯一标识ID + * @param postTag 更新后的帖子标签数据 + */ + @Override + public void updatePostTag(Long postTagId, PostTag postTag) { + logger.info("开始更新帖子标签,标签ID:{}", postTagId); + postTag.setPostTagId(postTagId); + updateById(postTag); + logger.info("帖子标签更新成功,标签ID:{}", postTagId); + } + + /** + * 删除帖子标签。 + * 根据帖子标签ID删除指定的帖子标签。 + * + * @param postTagId 要删除的帖子标签的唯一标识ID + */ + @Override + public void deletePostTag(Long postTagId) { + logger.info("开始删除帖子标签,标签ID:{}", postTagId); + removeById(postTagId); + logger.info("帖子标签删除成功,标签ID:{}", postTagId); + } + + @Override + public List getPostTagList(Long postId) { + logger.info("开始获取帖子标签列表,帖子ID:{}", postId); + return tagMapper.getPostTagList(postId); + } + + @Override + public List getTagPostList(Long tagId) { + logger.info("开始获取标签帖子列表,标签ID:{}", tagId); + return postMapper.getTagPostList(tagId); + } + + @Override + public List getSortedTagList() { + logger.info("开始获取排序后的标签列表"); + return tagMapper.getSortedTagList(); + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/TagServiceImpl.java b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/TagServiceImpl.java new file mode 100644 index 0000000..371a831 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/service/impl/TagServiceImpl.java @@ -0,0 +1,97 @@ +package com.ivmiku.tutorial.service.impl; + +import com.ivmiku.tutorial.entity.Tag; +import com.ivmiku.tutorial.mapper.TagMapper; +import com.ivmiku.tutorial.service.TagService; +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.util.List; + +/** + * 标签服务实现类 + */ +@Service +public class TagServiceImpl extends ServiceImpl implements TagService { + + // 使用SLF4J的LoggerFactory创建一个Logger实例 + private static final Logger logger = LoggerFactory.getLogger(TagServiceImpl.class); + + @Autowired + private TagMapper tagMapper; + + /** + * 创建标签 + * @param tag 标签实体对象 + */ + @Override + public void createTag(Tag tag) { + try { + // 保存标签到数据库 + save(tag); + logger.info("Tag created successfully: {}", tag); + } catch (Exception e) { + logger.error("Failed to create tag: {}", tag, e); + } + } + + /** + * 根据ID获取标签 + * @param tagId 标签ID + * @return 标签实体对象 + */ + @Override + public Tag getTagById(Long tagId) { + try { + // 根据ID查询标签 + return getById(tagId); + } catch (Exception e) { + logger.error("Failed to get tag by id: {}", tagId, e); + return null; + } + } + + /** + * 更新标签信息 + * @param tagId 标签ID + * @param tag 更新后的标签实体对象 + */ + @Override + public void updateTag(Long tagId, Tag tag) { + try { + // 设置标签ID并更新标签信息 + tag.setTagId(tagId); + updateById(tag); + logger.info("Tag updated successfully: {}", tag); + } catch (Exception e) { + logger.error("Failed to update tag with id {}: {}", tagId, tag, e); + } + } + + /** + * 删除标签 + * @param tagId 标签ID + */ + @Override + public void deleteTag(Long tagId) { + try { + // 根据ID删除标签 + removeById(tagId); + logger.info("Tag deleted successfully with id: {}", tagId); + } catch (Exception e) { + logger.error("Failed to delete tag with id: {}", tagId, e); + } + } + + @Override + public List getTagList() { + List tags = tagMapper.selectList(null); + if (tags != null) { + return tags; + } + return null; + } +} \ No newline at end of file diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/util/BusinessControllerAdvice.java b/community-8073/src/main/java/com/ivmiku/tutorial/util/BusinessControllerAdvice.java new file mode 100644 index 0000000..1336c8f --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/util/BusinessControllerAdvice.java @@ -0,0 +1,37 @@ +package com.ivmiku.tutorial.util; + + +import com.ivmiku.tutorial.response.Result; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +@RestControllerAdvice +public class BusinessControllerAdvice { + @ExceptionHandler(CustomException.class) + public Result customException(CustomException e) { + + return new Result(500, e.getMessage(), null); + } + + + @ExceptionHandler(MethodArgumentNotValidException.class) + public Result methodArgumentNotValidException(MethodArgumentNotValidException e) { + BindingResult bindingResult = e.getBindingResult(); + List fieldErrors = bindingResult.getFieldErrors(); + HashMap allErrors = new HashMap<>(); + List errors = new ArrayList<>(); + for (FieldError fieldError : fieldErrors) { + allErrors.put(fieldError.getField(), fieldError.getDefaultMessage()); + } + + return new Result(500, "参数校验失败", allErrors); + } + +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/util/CustomException.java b/community-8073/src/main/java/com/ivmiku/tutorial/util/CustomException.java new file mode 100644 index 0000000..0e24804 --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/util/CustomException.java @@ -0,0 +1,13 @@ +package com.ivmiku.tutorial.util; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CustomException extends Exception{ + String message; +} diff --git a/community-8073/src/main/java/com/ivmiku/tutorial/util/MinioClientUtil.java b/community-8073/src/main/java/com/ivmiku/tutorial/util/MinioClientUtil.java new file mode 100644 index 0000000..2ddedca --- /dev/null +++ b/community-8073/src/main/java/com/ivmiku/tutorial/util/MinioClientUtil.java @@ -0,0 +1,121 @@ +package com.ivmiku.tutorial.util; + +import io.minio.MinioClient; +import io.minio.ObjectStat; +import io.minio.PutObjectOptions; +import io.minio.Result; +import io.minio.errors.*; +import io.minio.messages.DeleteError; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; + +@Component +public class MinioClientUtil { + @Value("${minio.bucketName}") + private String bucketName; + + @Resource + private MinioClient minioClient; + + private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600; + + public boolean bucketExists(String bucketName) { + try { + return minioClient.bucketExists(bucketName); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean putObject(String objectName, InputStream stream) { + try { + if (bucketExists(bucketName)) { + minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1)); + ObjectStat statObject = statObject(objectName); + return statObject != null && statObject.length() > 0; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public boolean removeObject(String objectName) { + try { + if (bucketExists(bucketName)) { + minioClient.removeObject(bucketName, objectName); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public List removeObject(List objectNames) { + List deleteErrorNames = new ArrayList<>(); + try { + if (bucketExists(bucketName)) { + Iterable> results = minioClient.removeObjects(bucketName, objectNames); + for (Result result : results) { + DeleteError error = result.get(); + deleteErrorNames.add(error.objectName()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return deleteErrorNames; + } + + public ObjectStat statObject(String objectName) { + try { + if (bucketExists(bucketName)) { + return minioClient.statObject(bucketName, objectName); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getObjectUrl(String objectName) { + try { + if (bucketExists(bucketName)) { + return minioClient.getObjectUrl(bucketName, objectName); + } + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + public void getObject(String filename, HttpServletResponse response) { + try (InputStream in = minioClient.getObject(bucketName, filename); + OutputStream out = response.getOutputStream()) { + response.reset(); + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.setContentType("application/octet-stream"); + + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) > 0) { + out.write(buffer, 0, length); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/community-8073/src/main/resources/application-dep.properties b/community-8073/src/main/resources/application-dep.properties new file mode 100644 index 0000000..afe6821 --- /dev/null +++ b/community-8073/src/main/resources/application-dep.properties @@ -0,0 +1,24 @@ +wx.miniapp.configs[0].appid=wx0d4fdb5c7bf3b12b +wx.miniapp.configs[0].secret=989f155fcc3aee616568473faf1b1d3b + +spring.data.redis.host=127.0.0.1 +spring.data.redis.port=6379 +spring.data.redis.database=0 + +spring.application.name=community + +server.port=8073 + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.username=root +spring.datasource.password=123456 +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai + +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 +spring.cloud.nacos.discovery.enabled=true + +management.zipkin.tracing.endpoint=http://127.0.0.1:9411/api/v2/spans +management.tracing.sampling.probability=1.0 + + + diff --git a/community-8073/src/main/resources/application-dev.properties b/community-8073/src/main/resources/application-dev.properties new file mode 100644 index 0000000..5553089 --- /dev/null +++ b/community-8073/src/main/resources/application-dev.properties @@ -0,0 +1,26 @@ +wx.miniapp.configs[0].appid=wx0d4fdb5c7bf3b12b +wx.miniapp.configs[0].secret=989f155fcc3aee616568473faf1b1d3b + +spring.data.redis.host=localhost +spring.data.redis.port=6379 +spring.data.redis.database=0 + +spring.application.name=community + +server.port=8073 + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.username=root +spring.datasource.password=123456 +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai + +dubbo.application.qos-enable=false + +mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl + +minio.endpoint=120.26.243.81 +minio.port=9000 +minio.accessKey=minio_root +minio.secretKey=minio_123456 +minio.bucketName=haixia + diff --git a/community-8073/src/main/resources/application.properties b/community-8073/src/main/resources/application.properties new file mode 100644 index 0000000..257b306 --- /dev/null +++ b/community-8073/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.active=dev \ No newline at end of file diff --git a/community-8073/src/main/resources/mapper/CommentMapper.xml b/community-8073/src/main/resources/mapper/CommentMapper.xml new file mode 100644 index 0000000..ba57632 --- /dev/null +++ b/community-8073/src/main/resources/mapper/CommentMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + comment_id, user_openid, post_id, content, + parent_comment_id, is_deleted, created_at, updated_at, + mentioned_user_id, image_urls, video_url + + + + + + + + + + + INSERT INTO comment ( + user_openid, post_id, content, parent_comment_id, + is_deleted, created_at, updated_at, mentioned_user_id + ) VALUES ( + #{userOpenid}, #{postId}, #{content}, #{parentCommentId}, + #{isDeleted}, #{createdAt}, #{updatedAt}, #{mentionedUserId}, #{imageUrls}, #{videoUrl} + ) + + + + + UPDATE comment + SET + user_openid = #{userOpenid}, + post_id = #{postId}, + content = #{content}, + parent_comment_id = #{parentCommentId}, + is_deleted = #{isDeleted}, + created_at = #{createdAt}, + updated_at = #{updatedAt}, + mentioned_user_id = #{mentionedUserId}, + image_urls = #{imageUrls}, + video_url = #{videoUrl} + WHERE comment_id = #{commentId} + + + + + UPDATE comment + SET is_deleted = 1, updated_at = CURRENT_TIMESTAMP + WHERE comment_id = #{commentId} + + diff --git a/community-8073/src/main/resources/mapper/CommunityMapper.xml b/community-8073/src/main/resources/mapper/CommunityMapper.xml new file mode 100644 index 0000000..d942632 --- /dev/null +++ b/community-8073/src/main/resources/mapper/CommunityMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + community_id,name,description + + diff --git a/community-8073/src/main/resources/mapper/FavoriteMapper.xml b/community-8073/src/main/resources/mapper/FavoriteMapper.xml new file mode 100644 index 0000000..9053e01 --- /dev/null +++ b/community-8073/src/main/resources/mapper/FavoriteMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + id,user_openid,post_id, + is_deleted + + diff --git a/community-8073/src/main/resources/mapper/LikeMapper.xml b/community-8073/src/main/resources/mapper/LikeMapper.xml new file mode 100644 index 0000000..9845bac --- /dev/null +++ b/community-8073/src/main/resources/mapper/LikeMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + id,user_openid,post_id, + comment_id,is_deleted + + diff --git a/community-8073/src/main/resources/mapper/PostMapper.xml b/community-8073/src/main/resources/mapper/PostMapper.xml new file mode 100644 index 0000000..238898e --- /dev/null +++ b/community-8073/src/main/resources/mapper/PostMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + post_id, user_openid, community_id, title, content, + video_url, image_urls, + is_deleted, is_official, created_at, updated_at + + + + + + + + INSERT INTO post ( + post_id, user_openid, community_id, title, content, + video_url, image_urls, + is_deleted, is_official, created_at, updated_at + ) VALUES ( + #{postId}, #{userOpenid}, #{communityId}, #{title}, #{content}, + #{videoUrl}, #{imageUrls}, + #{isDeleted}, #{isOfficial}, #{createdAt}, #{updatedAt} + ) + + + + + UPDATE post + SET + user_openid = #{userOpenid}, + community_id = #{communityId}, + title = #{title}, + content = #{content}, + video_url = #{videoUrl}, + image_urls = #{imageUrls}, + is_deleted = #{isDeleted}, + is_official = #{isOfficial}, + created_at = #{createdAt}, + updated_at = #{updatedAt} + WHERE post_id = #{postId} + + + + + UPDATE post + SET is_deleted = 1, updated_at = CURRENT_TIMESTAMP + WHERE post_id = #{postId} + + + + + + diff --git a/community-8073/src/main/resources/mapper/PostTagMapper.xml b/community-8073/src/main/resources/mapper/PostTagMapper.xml new file mode 100644 index 0000000..7a52d94 --- /dev/null +++ b/community-8073/src/main/resources/mapper/PostTagMapper.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + post_tag_id,post_id,tag_id + + + diff --git a/community-8073/src/main/resources/mapper/TagMapper.xml b/community-8073/src/main/resources/mapper/TagMapper.xml new file mode 100644 index 0000000..a03c6c1 --- /dev/null +++ b/community-8073/src/main/resources/mapper/TagMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + tag_id,name + + + + diff --git a/community-8073/src/main/resources/mapper/UsercommunityMapper.xml b/community-8073/src/main/resources/mapper/UsercommunityMapper.xml new file mode 100644 index 0000000..773c6f9 --- /dev/null +++ b/community-8073/src/main/resources/mapper/UsercommunityMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + user_community_id,user_openid,community_id + + + diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/TestController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/TestController.java new file mode 100644 index 0000000..877b3b6 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/TestController.java @@ -0,0 +1,41 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.response.Result; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; + +@RestController +@RequestMapping("/test") +public class TestController { + @GetMapping("/login1") + public Object getToken1() { + StpUtil.login("1"); + String token = StpUtil.getTokenValue(); + HashMap map = new HashMap<>(); + map.put("token", token); + return JSON.toJSON(Result.ok(map)); + } + + @GetMapping("/login2") + public Object getToken2() { + StpUtil.login("2"); + String token = StpUtil.getTokenValue(); + HashMap map = new HashMap<>(); + map.put("token", token); + return JSON.toJSON(Result.ok(map)); + } + + @PostMapping("test") + public Object test() { + //添加请求头"satoken",值为上方接口返回的token后可以获取token对应的用户id + String userId = (String) StpUtil.getLoginId(); + //其他业务逻辑 + return Result.ok(); + } +}