feat(消息): 添加回复ID字段支持消息回复功能

在Message和MessageDto中添加replyid字段,支持消息回复功能
添加删除所有评论的API端点
重构消息控制器方法顺序
```

```msg
feat(文章): 实现文章浏览量增加功能

添加incrementViewCount方法用于增加文章浏览量
在文章实体中添加likes字段记录点赞数
更新API文档说明新增字段
```

```msg
chore: 移除数据初始化类

注释掉CategoryDataInit和MessageDataInit类
这些初始化功能将由其他方式实现
This commit is contained in:
qingfeng1121
2025-10-22 13:28:30 +08:00
parent 848b13506c
commit f53e251d46
15 changed files with 3227 additions and 1175 deletions

View File

@@ -318,6 +318,7 @@ GET /api/messages
"content": "留言内容", "content": "留言内容",
"createdAt": "2023-01-01T10:00:00", "createdAt": "2023-01-01T10:00:00",
"parentid": null, // 父留言IDnull表示主留言 "parentid": null, // 父留言IDnull表示主留言
"replyid": null, // 回复留言IDnull表示无回复
"articleid": null // 关联的文章IDnull表示无关联 "articleid": null // 关联的文章IDnull表示无关联
}, },
// 更多留言... // 更多留言...

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -81,10 +81,6 @@ public class ArticleController {
public ResponseMessage<List<Article>> getLatestArticlesByAttribute(@PathVariable Integer attributeId) { public ResponseMessage<List<Article>> getLatestArticlesByAttribute(@PathVariable Integer attributeId) {
return articleService.getLatestArticlesByAttribute(attributeId); return articleService.getLatestArticlesByAttribute(attributeId);
} }
/**
*
* @return ar
*/
/** /**
* 获取浏览量最高的文章列表 * 获取浏览量最高的文章列表
* @return 返回包含热门文章列表的ResponseMessage对象 * @return 返回包含热门文章列表的ResponseMessage对象
@@ -104,7 +100,15 @@ public class ArticleController {
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) { public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
return articleService.saveArticle(articleDto); return articleService.saveArticle(articleDto);
} }
/**文章浏览量
* 增加文章浏览量
* @param id 文章ID
* @return 返回包含更新后文章信息的ResponseMessage对象
*/
@PostMapping("/view/{id}")
public ResponseMessage<Article> incrementViewCount(@PathVariable Integer id) {
return articleService.incrementViewCount(id);
}
/** /**
* 更新现有文章 * 更新现有文章
* 仅限AUTHOR角色用户访问 * 仅限AUTHOR角色用户访问

View File

@@ -37,26 +37,6 @@ public class MessageController {
logger.info("接收根据ID获取消息的请求: {}", id); logger.info("接收根据ID获取消息的请求: {}", id);
return messageService.getMessageById(id); return messageService.getMessageById(id);
} }
/**
* 创建新消息
*/
@PostMapping
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
return messageService.saveMessage(message);
}
/**
* 根据ID删除消息
*/
@DeleteMapping("/{id}")
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
logger.info("接收删除消息的请求: {}", id);
return messageService.deleteMessage(id);
}
// 新增API端点
/** /**
* 根据文章ID获取消息列表 * 根据文章ID获取消息列表
@@ -102,4 +82,29 @@ public class MessageController {
logger.info("接收获取文章评论数量的请求: {}", articleId); logger.info("接收获取文章评论数量的请求: {}", articleId);
return messageService.getMessageCountByArticleId(articleId); return messageService.getMessageCountByArticleId(articleId);
} }
/**
* 创建新消息
*/
@PostMapping
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
return messageService.saveMessage(message);
}
/**
* 根据ID删除消息
*/
@DeleteMapping("/{id}")
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
logger.info("接收删除消息的请求: {}", id);
return messageService.deleteMessage(id);
}
//删除所有评论
@DeleteMapping("/all")
public ResponseMessage<Void> deleteAllMessages() {
logger.info("接收删除所有消息的请求");
return messageService.deleteAllMessages();
}
// 新增API端点
} }

View File

@@ -1,85 +1,85 @@
package com.qf.myafterprojecy.init; // package com.qf.myafterprojecy.init;
import com.qf.myafterprojecy.pojo.Category; // import com.qf.myafterprojecy.pojo.Category;
import com.qf.myafterprojecy.repository.CategoryRepository; // import com.qf.myafterprojecy.repository.CategoryRepository;
import org.slf4j.Logger; // import org.slf4j.Logger;
import org.slf4j.LoggerFactory; // import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; // import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments; // import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; // import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; // import org.springframework.stereotype.Component;
import java.time.LocalDateTime; // import java.time.LocalDateTime;
import java.util.ArrayList; // import java.util.ArrayList;
import java.util.List; // import java.util.List;
/** // /**
* 分类数据初始化类,用于在应用启动时初始化分类数据 // * 分类数据初始化类,用于在应用启动时初始化分类数据
*/ // */
@Component // @Component
public class CategoryDataInit implements ApplicationRunner { // public class CategoryDataInit implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(CategoryDataInit.class); // private static final Logger logger = LoggerFactory.getLogger(CategoryDataInit.class);
@Autowired // @Autowired
private CategoryRepository categoryRepository; // private CategoryRepository categoryRepository;
@Override // @Override
public void run(ApplicationArguments args) throws Exception { // public void run(ApplicationArguments args) throws Exception {
logger.info("===== 分类数据初始化开始 ====="); // logger.info("===== 分类数据初始化开始 =====");
// 检查数据库中是否已有分类数据 // // 检查数据库中是否已有分类数据
long count = categoryRepository.count(); // long count = categoryRepository.count();
logger.info("当前数据库中分类数量: {}", count); // logger.info("当前数据库中分类数量: {}", count);
// 如果没有分类数据,添加一些测试数据 // // 如果没有分类数据,添加一些测试数据
if (count == 0) { // if (count == 0) {
logger.info("数据库中没有分类数据,开始添加初始化数据..."); // logger.info("数据库中没有分类数据,开始添加初始化数据...");
addInitialCategories(); // addInitialCategories();
} else { // } else {
logger.info("数据库中已存在分类数据,无需初始化"); // logger.info("数据库中已存在分类数据,无需初始化");
} // }
logger.info("===== 分类数据初始化结束 ====="); // logger.info("===== 分类数据初始化结束 =====");
} // }
/** // /**
* 添加初始分类数据 // * 添加初始分类数据
*/ // */
private void addInitialCategories() { // private void addInitialCategories() {
List<Category> categories = new ArrayList<>(); // List<Category> categories = new ArrayList<>();
// 创建几个常见的文章分类 // // 创建几个常见的文章分类
Category category1 = new Category(); // Category category1 = new Category();
category1.setTypename("技术分享"); // category1.setTypename("技术分享");
category1.setDescription("技术文章、教程、经验分享等"); // category1.setDescription("技术文章、教程、经验分享等");
category1.setCreatedAt(LocalDateTime.now()); // category1.setCreatedAt(LocalDateTime.now());
category1.setUpdatedAt(LocalDateTime.now()); // category1.setUpdatedAt(LocalDateTime.now());
categories.add(category1); // categories.add(category1);
Category category2 = new Category(); // Category category2 = new Category();
category2.setTypename("生活随笔"); // category2.setTypename("生活随笔");
category2.setDescription("日常生活、心情记录、随笔等"); // category2.setDescription("日常生活、心情记录、随笔等");
category2.setCreatedAt(LocalDateTime.now()); // category2.setCreatedAt(LocalDateTime.now());
category2.setUpdatedAt(LocalDateTime.now()); // category2.setUpdatedAt(LocalDateTime.now());
categories.add(category2); // categories.add(category2);
Category category3 = new Category(); // Category category3 = new Category();
category3.setTypename("学习笔记"); // category3.setTypename("学习笔记");
category3.setDescription("学习过程中的笔记、总结等"); // category3.setDescription("学习过程中的笔记、总结等");
category3.setCreatedAt(LocalDateTime.now()); // category3.setCreatedAt(LocalDateTime.now());
category3.setUpdatedAt(LocalDateTime.now()); // category3.setUpdatedAt(LocalDateTime.now());
categories.add(category3); // categories.add(category3);
Category category4 = new Category(); // Category category4 = new Category();
category4.setTypename("行业动态"); // category4.setTypename("行业动态");
category4.setDescription("行业新闻、趋势分析等"); // category4.setDescription("行业新闻、趋势分析等");
category4.setCreatedAt(LocalDateTime.now()); // category4.setCreatedAt(LocalDateTime.now());
category4.setUpdatedAt(LocalDateTime.now()); // category4.setUpdatedAt(LocalDateTime.now());
categories.add(category4); // categories.add(category4);
// 保存分类数据到数据库 // // 保存分类数据到数据库
categoryRepository.saveAll(categories); // categoryRepository.saveAll(categories);
logger.info("成功添加 {} 条分类数据", categories.size()); // logger.info("成功添加 {} 条分类数据", categories.size());
} // }
} // }

View File

@@ -1,96 +1,96 @@
package com.qf.myafterprojecy.init; // package com.qf.myafterprojecy.init;
import com.qf.myafterprojecy.pojo.Message; // import com.qf.myafterprojecy.pojo.Message;
import com.qf.myafterprojecy.repository.MessageRepository; // import com.qf.myafterprojecy.repository.MessageRepository;
import org.slf4j.Logger; // import org.slf4j.Logger;
import org.slf4j.LoggerFactory; // import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; // import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments; // import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; // import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; // import org.springframework.stereotype.Component;
import java.util.Date; // import java.util.Date;
/** // /**
* 消息数据初始化类用于在应用启动时为Message表添加默认的测试数据 // * 消息数据初始化类用于在应用启动时为Message表添加默认的测试数据
*/ // */
@Component // @Component
public class MessageDataInit implements ApplicationRunner { // public class MessageDataInit implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(MessageDataInit.class); // private static final Logger logger = LoggerFactory.getLogger(MessageDataInit.class);
@Autowired // @Autowired
private MessageRepository messageRepository; // private MessageRepository messageRepository;
@Override // @Override
public void run(ApplicationArguments args) throws Exception { // public void run(ApplicationArguments args) throws Exception {
logger.info("===== 消息数据初始化开始 ====="); // logger.info("===== 消息数据初始化开始 =====");
// 检查数据库中是否已有消息数据 // // 检查数据库中是否已有消息数据
long count = messageRepository.count(); // long count = messageRepository.count();
logger.info("当前数据库中消息数量: {}", count); // logger.info("当前数据库中消息数量: {}", count);
// 如果没有消息数据,添加一些测试数据 // // 如果没有消息数据,添加一些测试数据
if (count == 0) { // if (count == 0) {
logger.info("数据库中没有消息数据,开始添加初始化数据..."); // logger.info("数据库中没有消息数据,开始添加初始化数据...");
addInitialMessages(); // addInitialMessages();
} else { // } else {
logger.info("数据库中已存在消息数据,无需初始化"); // logger.info("数据库中已存在消息数据,无需初始化");
} // }
logger.info("===== 消息数据初始化结束 ====="); // logger.info("===== 消息数据初始化结束 =====");
} // }
private void addInitialMessages() { // private void addInitialMessages() {
// 添加第一篇文章的评论 // // 添加第一篇文章的评论
Message message1 = new Message(); // Message message1 = new Message();
message1.setNickname("系统用户"); // message1.setNickname("系统用户");
message1.setEmail("system@example.com"); // message1.setEmail("system@example.com");
message1.setContent("这是系统自动添加的第一条评论,欢迎使用本系统!"); // message1.setContent("这是系统自动添加的第一条评论,欢迎使用本系统!");
message1.setCreatedAt(new Date()); // message1.setCreatedAt(new Date());
message1.setArticleid(1); // message1.setArticleid(1);
message1.setParentid(null); // 根评论 // message1.setParentid(null); // 根评论
messageRepository.save(message1); // messageRepository.save(message1);
// 添加回复 // // 添加回复
Message reply1 = new Message(); // Message reply1 = new Message();
reply1.setNickname("管理员"); // reply1.setNickname("管理员");
reply1.setEmail("admin@example.com"); // reply1.setEmail("admin@example.com");
reply1.setContent("感谢您的支持,如有任何问题请随时联系我们!"); // reply1.setContent("感谢您的支持,如有任何问题请随时联系我们!");
reply1.setCreatedAt(new Date()); // reply1.setCreatedAt(new Date());
reply1.setArticleid(1); // reply1.setArticleid(1);
reply1.setParentid(message1.getMessageid()); // 回复第一条评论 // reply1.setParentid(message1.getMessageid()); // 回复第一条评论
messageRepository.save(reply1); // messageRepository.save(reply1);
// 添加第二篇文章的评论 // // 添加第二篇文章的评论
Message message2 = new Message(); // Message message2 = new Message();
message2.setNickname("访客"); // message2.setNickname("访客");
message2.setEmail("visitor@example.com"); // message2.setEmail("visitor@example.com");
message2.setContent("这篇文章写得非常好,学到了很多知识。"); // message2.setContent("这篇文章写得非常好,学到了很多知识。");
message2.setCreatedAt(new Date()); // message2.setCreatedAt(new Date());
message2.setArticleid(2); // message2.setArticleid(2);
message2.setParentid(null); // message2.setParentid(null);
messageRepository.save(message2); // messageRepository.save(message2);
// 再添加一些测试数据 // // 再添加一些测试数据
Message message3 = new Message(); // Message message3 = new Message();
message3.setNickname("测试用户1"); // message3.setNickname("测试用户1");
message3.setEmail("test1@example.com"); // message3.setEmail("test1@example.com");
message3.setContent("这是测试内容1"); // message3.setContent("这是测试内容1");
message3.setCreatedAt(new Date()); // message3.setCreatedAt(new Date());
message3.setArticleid(1); // message3.setArticleid(1);
message3.setParentid(null); // message3.setParentid(null);
messageRepository.save(message3); // messageRepository.save(message3);
Message reply2 = new Message(); // Message reply2 = new Message();
reply2.setNickname("测试用户2"); // reply2.setNickname("测试用户2");
reply2.setEmail("test2@example.com"); // reply2.setEmail("test2@example.com");
reply2.setContent("回复测试内容1"); // reply2.setContent("回复测试内容1");
reply2.setCreatedAt(new Date()); // reply2.setCreatedAt(new Date());
reply2.setArticleid(1); // reply2.setArticleid(1);
reply2.setParentid(message3.getMessageid()); // reply2.setParentid(message3.getMessageid());
messageRepository.save(reply2); // messageRepository.save(reply2);
logger.info("成功添加了{}条初始化消息数据", messageRepository.count()); // logger.info("成功添加了{}条初始化消息数据", messageRepository.count());
} // }
} // }

View File

@@ -33,14 +33,26 @@ public class Article {
@Column(name = "updated_at") @Column(name = "updated_at")
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
@Column(name = "view_count") @Column(name = "view_count")
private Integer viewCount; private Integer viewCount;
@Column(name = "likes")
private Integer likes; // 点赞数
@Column(name = "status") @Column(name = "status")
private Integer status; // 0-草稿1-已发布2-已删除 private Integer status; // 0-草稿1-已发布2-已删除
// Getters and Setters // Getters and Setters
public Integer getLikes() {
return likes;
}
public void setLikes(Integer likes) {
this.likes = likes;
}
public Integer getAttributeid() { public Integer getAttributeid() {
return attributeid; return attributeid;

View File

@@ -8,22 +8,50 @@ import java.util.Date;
public class Message { public class Message {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "messageid")
private Integer messageid; private Integer messageid;
@Column(name = "nickname")
private String nickname; private String nickname;
@Column(name = "email")
private String email; private String email;
@Column(columnDefinition = "text") @Column(name = "content", columnDefinition = "text")
private String content; private String content;
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt; private Date createdAt;
@Column(name = "parentid")
private Integer parentid; private Integer parentid;
private Integer articleid; @Column(name = "replyid")
private Integer replyid;
@Column(name = "articleid")
private Integer articleid;
@Column(name = "likes")
private Integer likes; // 点赞数
public Integer getLikes() {
return likes;
}
public void setLikes(Integer likes) {
this.likes = likes;
}
public Integer getReplyid() {
return replyid;
}
public void setReplyid(Integer replyid) {
this.replyid = replyid;
}
public Integer getMessageid() { public Integer getMessageid() {
return messageid; return messageid;

View File

@@ -14,10 +14,18 @@ public class MessageDto {
private Date createdAt; private Date createdAt;
private Integer parentid; private Integer parentid;
private Integer replyid;
private Integer articleid; private Integer articleid;
public Integer getReplyid() {
return replyid;
}
public void setReplyid(Integer replyid) {
this.replyid = replyid;
}
public Integer getMessageid() { public Integer getMessageid() {
return messageid; return messageid;
} }

View File

@@ -67,6 +67,7 @@ public interface ArticleRepository extends JpaRepository<Article, Integer> {
@Query("UPDATE Article a SET a.viewCount = a.viewCount + 1 WHERE a.articleid = :articleid") @Query("UPDATE Article a SET a.viewCount = a.viewCount + 1 WHERE a.articleid = :articleid")
void incrementViewCount(@Param("articleid") Integer articleid); void incrementViewCount(@Param("articleid") Integer articleid);
/** /**
* 根据浏览量降序查询状态为1的所有文章 * 根据浏览量降序查询状态为1的所有文章
* 该查询使用JPQL语句从Article实体中选取数据 * 该查询使用JPQL语句从Article实体中选取数据

View File

@@ -163,7 +163,28 @@ public class ArticleService implements IArticleService {
return ResponseMessage.failure("获取属性文章失败"); return ResponseMessage.failure("获取属性文章失败");
} }
} }
/**
* 增加文章浏览量
* @param id 文章ID
* @return 返回包含更新后文章信息的ResponseMessage对象
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ResponseMessage<Article> incrementViewCount(Integer id) {
try {
Article article = articleRepository.findById(id)
.orElseThrow(() -> new RuntimeException("文章不存在"));
article.setViewCount(article.getViewCount() + 1);
Article updatedArticle = articleRepository.save(article);
return ResponseMessage.success(updatedArticle);
} catch (Exception e) {
log.error("增加文章浏览量失败: {}", e.getMessage());
return ResponseMessage.failure("增加文章浏览量失败");
}
}
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public ResponseMessage<List<Article>> getLatestArticlesByAttribute(Integer attributeid) { public ResponseMessage<List<Article>> getLatestArticlesByAttribute(Integer attributeid) {

View File

@@ -39,4 +39,10 @@ public interface IArticleService {
*/ */
ResponseMessage<List<Article>> getLatestArticlesByAttribute(Integer attributeid); ResponseMessage<List<Article>> getLatestArticlesByAttribute(Integer attributeid);
ResponseMessage<List<Article>> getMostViewedArticles(); ResponseMessage<List<Article>> getMostViewedArticles();
/**
* 增加文章浏览量
* @param id 文章ID
* @return 返回包含更新后文章信息的ResponseMessage对象
*/
ResponseMessage<Article> incrementViewCount(Integer id);
} }

View File

@@ -59,7 +59,8 @@ public interface IMessageService {
* @return 匹配的消息列表 * @return 匹配的消息列表
*/ */
ResponseMessage<List<Message>> searchMessagesByNickname(String nickname); ResponseMessage<List<Message>> searchMessagesByNickname(String nickname);
//删除所有评论
ResponseMessage<Void> deleteAllMessages();
/** /**
* 获取指定文章的评论数量 * 获取指定文章的评论数量
* @param articleId 文章ID * @param articleId 文章ID

View File

@@ -191,7 +191,18 @@ public class MessageService implements IMessageService {
return ResponseMessage.failure("查询消息失败:" + e.getMessage()); return ResponseMessage.failure("查询消息失败:" + e.getMessage());
} }
} }
//删除所有评论
@Override
public ResponseMessage<Void> deleteAllMessages() {
try {
logger.info("删除所有消息");
messageRepository.deleteAll();
return ResponseMessage.success(null, "删除成功", true);
} catch (DataAccessException e) {
logger.error("删除所有消息失败", e);
return ResponseMessage.failure("删除消息失败:" + e.getMessage());
}
}
@Override @Override
public ResponseMessage<Long> getMessageCountByArticleId(Integer articleId) { public ResponseMessage<Long> getMessageCountByArticleId(Integer articleId) {
if (articleId == null || articleId <= 0) { if (articleId == null || articleId <= 0) {