diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..b48c127
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ mysql_aurora_aws
+ true
+ software.aws.rds.jdbc.mysql.Driver
+ jdbc:mysql:aws://localhost:3306/tutorial
+
+
+
+
+
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 240ee29..c54f389 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -3,6 +3,8 @@
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index fdc35ea..bada8b5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,7 +8,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/mybatisx/templates.xml b/.idea/mybatisx/templates.xml
new file mode 100644
index 0000000..47f2860
--- /dev/null
+++ b/.idea/mybatisx/templates.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/commons/pom.xml b/commons/pom.xml
index 1bf709a..439782d 100644
--- a/commons/pom.xml
+++ b/commons/pom.xml
@@ -27,5 +27,22 @@
com.alibaba.fastjson2
fastjson2
+
+ cn.hutool
+ hutool-all
+ 5.8.21
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 3.1.5
+
+
+
+ io.github.openfeign
+ feign-micrometer
+ 12.5
+
\ No newline at end of file
diff --git a/community-8073/pom.xml b/community-8073/pom.xml
new file mode 100644
index 0000000..8d30724
--- /dev/null
+++ b/community-8073/pom.xml
@@ -0,0 +1,173 @@
+
+
+ 4.0.0
+
+ com.ivmiku.tutorial
+ first-tutorial
+ 1.0-SNAPSHOT
+
+
+ community-8073
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+
+
+
+
+
+
+ io.minio
+ minio
+ 7.0.2
+
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.1.0
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.1.0
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ cn.dev33
+ sa-token-spring-boot3-starter
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+
+
+
+ cn.dev33
+ sa-token-redis-jackson
+ 1.38.0
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+
+
+
+ org.apache.dubbo
+ dubbo-registry-nacos
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ io.micrometer
+ micrometer-tracing
+
+
+
+ io.micrometer
+ micrometer-tracing-bridge-brave
+
+
+
+ io.micrometer
+ micrometer-observation
+
+
+
+ io.zipkin.reporter2
+ zipkin-reporter-brave
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-tracing-brave-zipkin-starter
+ 3.2.13
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+ com.github.binarywang
+ weixin-java-miniapp
+
+
+ com.ivmiku.tutorial
+ commons
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 3.0.13
+
+ com.ivmiku.tutorial.Main8072
+ JAR
+
+
+
+
+ repackage
+
+
+
+
+
+
+
\ No newline at end of file
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