feat: 实现消息、文章和分类的树形结构展示功能
refactor: 重构消息、文章和疯言疯语的分页查询接口 refactor(controller): 调整疯言疯语控制器的更新接口参数 refactor(service): 优化消息服务的分页查询逻辑 fix: 修复JWT认证过滤器中的令牌验证问题 fix(properties): 修正生产环境数据库配置 style: 清理无用代码并删除HelpController
This commit is contained in:
3604
logs/web_project.log
3604
logs/web_project.log
File diff suppressed because it is too large
Load Diff
BIN
logs/web_project.log.2025-12-22.0.gz
Normal file
BIN
logs/web_project.log.2025-12-22.0.gz
Normal file
Binary file not shown.
@@ -44,25 +44,52 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
try {
|
||||
// 获取token
|
||||
String token = getTokenFromRequest(request);
|
||||
System.out.println(token);
|
||||
if (token != null && validateToken(token)) {
|
||||
// 从token中获取用户名
|
||||
String username = jwtUtils.getUsernameFromToken(token);
|
||||
System.out.println("username: " + username);
|
||||
// 加载用户信息
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
// System.out.println(token);
|
||||
if (token != null) {
|
||||
if (validateToken(token)) {
|
||||
// 从token中获取用户名
|
||||
String username = jwtUtils.getUsernameFromToken(token);
|
||||
// System.out.println("username: " + username);
|
||||
// 加载用户信息
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
|
||||
// 创建认证对象
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
// 创建认证对象
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
|
||||
// 设置认证信息到上下文
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 设置认证信息到上下文
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
} else {
|
||||
// 如果token无效但不为空,返回401
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write("{\"message\":\"无效的认证令牌\"}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (io.jsonwebtoken.ExpiredJwtException e) {
|
||||
// 专门处理令牌过期,返回401和明确的错误信息
|
||||
logger.error("令牌已过期: {}", e.getMessage());
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write("{\"message\":\"认证令牌已过期\"}");
|
||||
return;
|
||||
} catch (io.jsonwebtoken.JwtException e) {
|
||||
// 其他JWT异常
|
||||
logger.error("无效的token格式: {}", e.getMessage());
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write("{\"message\":\"无效的令牌格式\"}");
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
logger.error("无法设置用户认证: {}", e);
|
||||
SecurityContextHolder.clearContext();
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write("{\"message\":\"认证失败\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
@@ -88,8 +115,17 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
String username = jwtUtils.getUsernameFromToken(token);
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
return jwtUtils.validateToken(token, userDetails);
|
||||
} catch (io.jsonwebtoken.ExpiredJwtException e) {
|
||||
// 专门处理令牌过期,记录日志但不抛出异常
|
||||
logger.error("令牌已过期: {}", e.getMessage());
|
||||
return false;
|
||||
} catch (io.jsonwebtoken.JwtException e) {
|
||||
// 其他JWT异常
|
||||
logger.error("无效的token格式: {}", e.getMessage());
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
logger.error("无效的token: {}", e);
|
||||
// 其他异常
|
||||
logger.error("验证token失败: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package com.qf.myafterprojecy.controller;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleTreeDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||
import com.qf.myafterprojecy.service.IArticleService;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -52,7 +50,7 @@ public class ArticleController {
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/status/{status}")
|
||||
public ResponseMessage<List<Article>> getArticlesByStatus(@PathVariable Integer status) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByStatus(@PathVariable Integer status) {
|
||||
return articleService.getArticlesByStatus(status);
|
||||
}
|
||||
|
||||
@@ -66,7 +64,7 @@ public class ArticleController {
|
||||
// api/articles/status/page?status=1&page=1&size=2
|
||||
// get 只能这样不能传递json
|
||||
@GetMapping("/status/page")
|
||||
public ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto pageDto) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByStatusWithPagination(ArriclePageDto pageDto) {
|
||||
return articleService.getArticlesByStatusWithPagination(pageDto);
|
||||
}
|
||||
|
||||
@@ -93,7 +91,7 @@ public class ArticleController {
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/title/{title}")
|
||||
public ResponseMessage<List<Article>> getArticlesByTitle(@PathVariable String title) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByTitle(@PathVariable String title) {
|
||||
return articleService.getArticlesByTitle(title);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/category-attributes")
|
||||
@RequestMapping("/api/categoryattributes")
|
||||
@Validated
|
||||
public class CategoryAttributeController {
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.qf.myafterprojecy.controller;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryTreeDto;
|
||||
import com.qf.myafterprojecy.service.ICategoryService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -49,7 +50,16 @@ public class CategoryController {
|
||||
log.info("接收获取所有分类列表的请求");
|
||||
return categoryService.getAllCategories();
|
||||
}
|
||||
|
||||
// 分类树
|
||||
/**
|
||||
* 获取分类树结构
|
||||
* @return 返回分类树结构
|
||||
*/
|
||||
@GetMapping("/tree")
|
||||
public ResponseMessage<List<CategoryTreeDto>> getCategoryTree() {
|
||||
log.info("接收获取分类树结构的请求");
|
||||
return categoryService.getCategoryTree();
|
||||
}
|
||||
/**
|
||||
* 创建新分类
|
||||
* @param categoryDto 分类数据传输对象
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package com.qf.myafterprojecy.controller;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 帮助控制器类,处理前端调用api/help请求
|
||||
* 提供README_API.md文件的读取和返回功能
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/help")
|
||||
public class HelpController {
|
||||
|
||||
/**
|
||||
* 获取README_API.md文件内容
|
||||
* @return 返回包含README_API.md文件内容的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping
|
||||
public ResponseMessage<String> getReadmeApi() {
|
||||
try {
|
||||
// 获取项目根目录
|
||||
String rootPath = System.getProperty("user.dir") ;
|
||||
// 构建README_API.md文件路径
|
||||
File readmeFile = new File(rootPath, "README_API.md");
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!readmeFile.exists() || !readmeFile.isFile()) {
|
||||
// 如果不存在,尝试使用类路径资源加载
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource("README_API.md");
|
||||
String markdownContent = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()), StandardCharsets.UTF_8);
|
||||
// 将Markdown转换为HTML
|
||||
String htmlContent = convertMarkdownToHtml(markdownContent);
|
||||
return ResponseMessage.success(htmlContent, "获取API文档成功");
|
||||
} catch (IOException e) {
|
||||
return ResponseMessage.error("未找到README_API.md文件");
|
||||
}
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
String markdownContent = new String(FileCopyUtils.copyToByteArray(new FileInputStream(readmeFile)), StandardCharsets.UTF_8);
|
||||
// 将Markdown转换为HTML
|
||||
String htmlContent = convertMarkdownToHtml(markdownContent);
|
||||
return ResponseMessage.success(htmlContent, "获取API文档成功");
|
||||
} catch (IOException e) {
|
||||
return ResponseMessage.error("读取README_API.md文件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Markdown文本转换为HTML
|
||||
* @param markdown 原始Markdown文本
|
||||
* @return 转换后的HTML字符串
|
||||
*/
|
||||
private String convertMarkdownToHtml(String markdown) {
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(markdown);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
return renderer.render(document);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageTreeDto;
|
||||
import com.qf.myafterprojecy.service.IMessageService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -35,7 +36,7 @@ public class MessageController {
|
||||
* 分页查询消息
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||
public ResponseMessage<List<MessageTreeDto>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||
logger.info("接收分页查询消息的请求: {}", messagePageDto);
|
||||
return messageService.getMessagesByPage(messagePageDto);
|
||||
}
|
||||
@@ -45,8 +46,8 @@ public class MessageController {
|
||||
* @return 消息数量
|
||||
* 文章ID为null时返回所有消息数量
|
||||
*/
|
||||
@GetMapping("/count")
|
||||
public ResponseMessage<Integer> getMessageCount( Integer articleId) {
|
||||
@GetMapping("/count/{articleId}")
|
||||
public ResponseMessage<Integer> getMessageCount(@PathVariable Integer articleId) {
|
||||
logger.info("接收获取消息数量的请求: {}", articleId);
|
||||
return messageService.getMessageCountByArticleId(articleId);
|
||||
}
|
||||
@@ -62,11 +63,11 @@ public class MessageController {
|
||||
/**
|
||||
* 根据文章ID获取消息列表
|
||||
*/
|
||||
@GetMapping("/article/{articleId}")
|
||||
public ResponseMessage<List<Message>> getMessagesByArticleId(@PathVariable Integer articleId) {
|
||||
logger.info("接收根据文章ID获取消息的请求: {}", articleId);
|
||||
return messageService.getMessagesByArticleId(articleId);
|
||||
}
|
||||
// @GetMapping("/article/{articleId}")
|
||||
// public ResponseMessage<List<Message>> getMessagesByArticleId(@PathVariable Integer articleId) {
|
||||
// logger.info("接收根据文章ID获取消息的请求: {}", articleId);
|
||||
// return messageService.getMessagesByArticleId(articleId);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取所有根消息(非回复的消息)
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.qf.myafterprojecy.controller;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsensePageDto;
|
||||
|
||||
import com.qf.myafterprojecy.service.INonsenseService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -37,15 +39,14 @@ public class NonsenseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态获取疯言疯语内容
|
||||
* @param status 状态:0未发表 1已发表 2已删除
|
||||
* 根据分页信息获取疯言疯语内容
|
||||
* @param page 分页信息
|
||||
* @return 疯言疯语内容列表
|
||||
*/
|
||||
@GetMapping("/status/{status}")
|
||||
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(
|
||||
@PathVariable("status") Integer status) {
|
||||
logger.info("请求获取状态为{}的疯言疯语内容", status);
|
||||
return nonsenseService.getNonsenseByStatus(status);
|
||||
@GetMapping("/page")
|
||||
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(NonsensePageDto page) {
|
||||
logger.info("请求获取状态为{}的疯言疯语内容, 分页信息: {}", page.getStatus(), page);
|
||||
return nonsenseService.getNonsenseByStatus(page);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,11 +79,11 @@ public class NonsenseController {
|
||||
* @param nonsenseDto 疯言疯语内容数据
|
||||
* @return 更新结果
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
@PutMapping()
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public ResponseMessage<Nonsense> updateNonsense(@PathVariable("id") Integer id, @Valid @RequestBody NonsenseDto nonsenseDto) {
|
||||
logger.info("请求更新ID为{}的疯言疯语内容", id);
|
||||
return nonsenseService.updateNonsense(id, nonsenseDto);
|
||||
public ResponseMessage<Nonsense> updateNonsense(@RequestBody NonsenseDto nonsenseDto) {
|
||||
logger.info("请求更新ID为{}的疯言疯语内容", nonsenseDto.getId());
|
||||
return nonsenseService.updateNonsense(nonsenseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,6 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(value=Exception.class)
|
||||
public ResponseMessage<String> handleException(Exception e, HttpServletRequest request) {
|
||||
logger.error("请求路径:{},异常消息:{}",request.getRequestURI(),e.getMessage());
|
||||
return new ResponseMessage<>(500,"服务器异常",e.getMessage());
|
||||
return new ResponseMessage<String>(500,"服务器异常",e.getMessage(),false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public class ResponseMessage<T> {
|
||||
private boolean success;
|
||||
// 响应数据,泛型类型,支持不同类型的数据
|
||||
private T data;
|
||||
// 分页总页数,仅在分页查询时使用
|
||||
private Integer totalPages;
|
||||
|
||||
/**
|
||||
* 构造方法,用于创建响应消息对象
|
||||
@@ -25,11 +27,13 @@ public class ResponseMessage<T> {
|
||||
* @param code 状态码
|
||||
* @param message 响应消息
|
||||
* @param data 响应数据
|
||||
* @param totalPages 分页总页数
|
||||
*/
|
||||
public ResponseMessage(Integer code, String message, T data) {
|
||||
public ResponseMessage(Integer code, String message, T data, Integer totalPages) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.totalPages = totalPages;
|
||||
// 自动根据状态码判断是否成功
|
||||
this.success = code >= 200 && code < 300;
|
||||
}
|
||||
@@ -41,6 +45,22 @@ public class ResponseMessage<T> {
|
||||
* @param data 响应数据
|
||||
* @param success 是否成功
|
||||
*/
|
||||
public ResponseMessage(Integer code, String message, T data, boolean success, Integer totalPages) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.success = success;
|
||||
this.totalPages = totalPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整参数的构造方法
|
||||
* @param code 状态码
|
||||
* @param message 响应消息
|
||||
* @param data 响应数据
|
||||
* @param success 是否成功
|
||||
* @param totalPages 分页总页数
|
||||
*/
|
||||
public ResponseMessage(Integer code, String message, T data, boolean success) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
@@ -48,6 +68,7 @@ public class ResponseMessage<T> {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------- 成功响应方法 -----------------------------------
|
||||
|
||||
/**
|
||||
@@ -218,8 +239,8 @@ public class ResponseMessage<T> {
|
||||
* @param <T> 数据类型
|
||||
* @return 分页响应对象
|
||||
*/
|
||||
public static <T> ResponseMessage<T> page(T data, String message) {
|
||||
return new ResponseMessage<>(HttpStatus.OK.value(), message, data, true);
|
||||
public static <T> ResponseMessage<T> page(T data, String message, Integer totalPages) {
|
||||
return new ResponseMessage<>(HttpStatus.OK.value(), message, data, true, totalPages);
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
|
||||
112
src/main/java/com/qf/myafterprojecy/pojo/dto/ArticleTreeDto.java
Normal file
112
src/main/java/com/qf/myafterprojecy/pojo/dto/ArticleTreeDto.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class ArticleTreeDto {
|
||||
private Integer articleid;
|
||||
private String title;
|
||||
private String content;
|
||||
private String img;
|
||||
private Integer viewcount;
|
||||
private Integer likes; // 点赞数
|
||||
private Integer status;
|
||||
private String markdownscontent;
|
||||
private Integer attributeid;
|
||||
private String attributename;
|
||||
private Integer userid;
|
||||
private String username;
|
||||
private Integer commentcount; // 评论数
|
||||
private LocalDateTime createtime;
|
||||
private LocalDateTime updatetime;
|
||||
public Integer getArticleid() {
|
||||
return articleid;
|
||||
}
|
||||
public void setArticleid(Integer articleid) {
|
||||
this.articleid = articleid;
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
public String getImg() {
|
||||
return img;
|
||||
}
|
||||
public void setImg(String img) {
|
||||
this.img = img;
|
||||
}
|
||||
public Integer getViewcount() {
|
||||
return viewcount;
|
||||
}
|
||||
public void setViewcount(Integer viewcount) {
|
||||
this.viewcount = viewcount;
|
||||
}
|
||||
public Integer getLikes() {
|
||||
return likes;
|
||||
}
|
||||
public void setLikes(Integer likes) {
|
||||
this.likes = likes;
|
||||
}
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
public String getMarkdownscontent() {
|
||||
return markdownscontent;
|
||||
}
|
||||
public void setMarkdownscontent(String markdownscontent) {
|
||||
this.markdownscontent = markdownscontent;
|
||||
}
|
||||
public Integer getAttributeid() {
|
||||
return attributeid;
|
||||
}
|
||||
public void setAttributeid(Integer attributeid) {
|
||||
this.attributeid = attributeid;
|
||||
}
|
||||
public String getAttributename() {
|
||||
return attributename;
|
||||
}
|
||||
public void setAttributename(String attributename) {
|
||||
this.attributename = attributename;
|
||||
}
|
||||
public Integer getUserid() {
|
||||
return userid;
|
||||
}
|
||||
public void setUserid(Integer userid) {
|
||||
this.userid = userid;
|
||||
}
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
public LocalDateTime getCreatetime() {
|
||||
return createtime;
|
||||
}
|
||||
public void setCreatetime(LocalDateTime createtime) {
|
||||
this.createtime = createtime;
|
||||
}
|
||||
public LocalDateTime getUpdatetime() {
|
||||
return updatetime;
|
||||
}
|
||||
public void setUpdatetime(LocalDateTime updatetime) {
|
||||
this.updatetime = updatetime;
|
||||
}
|
||||
public Integer getCommentcount() {
|
||||
return commentcount;
|
||||
}
|
||||
public void setCommentcount(Integer commentcount) {
|
||||
this.commentcount = commentcount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||
|
||||
public class CategoryTreeDto {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private List<Categoryattribute> children;
|
||||
|
||||
// 构造方法
|
||||
public CategoryTreeDto() {
|
||||
}
|
||||
// 全参构造方法
|
||||
public CategoryTreeDto(Integer id, String name, List<Categoryattribute> children) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.children = children;
|
||||
}
|
||||
// getter和setter方法
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public List<Categoryattribute> getChildren() {
|
||||
return children;
|
||||
}
|
||||
public void setChildren(List<Categoryattribute> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageTreeDto extends MessageDto {
|
||||
private List<MessageTreeDto> children = new ArrayList<>();
|
||||
private int replyCount = 0;
|
||||
private String replyToNickname; // 被回复者昵称
|
||||
private Integer replyToId; // 被回复消息ID
|
||||
|
||||
public List<MessageTreeDto> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<MessageTreeDto> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public int getReplyCount() {
|
||||
return replyCount;
|
||||
}
|
||||
|
||||
public void setReplyCount(int replyCount) {
|
||||
this.replyCount = replyCount;
|
||||
}
|
||||
|
||||
public String getReplyToNickname() {
|
||||
return replyToNickname;
|
||||
}
|
||||
|
||||
public void setReplyToNickname(String replyToNickname) {
|
||||
this.replyToNickname = replyToNickname;
|
||||
}
|
||||
|
||||
public Integer getReplyToId() {
|
||||
return replyToId;
|
||||
}
|
||||
|
||||
public void setReplyToId(Integer replyToId) {
|
||||
this.replyToId = replyToId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
public class NonsensePageDto {
|
||||
private Integer status;
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
public Integer getPageNum() {
|
||||
return pageNum;
|
||||
}
|
||||
public void setPageNum(Integer pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
public void setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Page [pageNum=" + pageNum + ", pageSize=" + pageSize + "]";
|
||||
}
|
||||
|
||||
public NonsensePageDto(Integer pageNum, Integer pageSize) {
|
||||
super();
|
||||
this.pageNum = pageNum;
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
}
|
||||
@@ -43,4 +43,10 @@ public interface CategoryAttributeRepository extends JpaRepository<Categoryattri
|
||||
* @return 属性对象
|
||||
*/
|
||||
Optional<Categoryattribute> findByCategoryidAndAttributename(Integer categoryid, String attributename);
|
||||
/**
|
||||
* 根据分类ID获取分类属性列表
|
||||
* @param categoryids 分类ID列表
|
||||
* @return 返回包含所有分类属性的列表
|
||||
*/
|
||||
List<Categoryattribute> findByCategoryidIn(List<Integer> categoryids);
|
||||
}
|
||||
@@ -16,17 +16,11 @@ import java.util.List;
|
||||
@Repository
|
||||
public interface MessageRepository extends JpaRepository<Message, Integer> {
|
||||
|
||||
// 根据文章ID查询消息
|
||||
/**
|
||||
* 根据文章ID查询消息
|
||||
* @param articleid 文章ID
|
||||
* @return 文章下的消息列表
|
||||
*/
|
||||
List<Message> findByArticleid(Integer articleid);
|
||||
|
||||
// 查询所有父消息(回复的根消息)
|
||||
/**
|
||||
* 查询所有父消息(回复的根消息)
|
||||
*
|
||||
* @return 根回复消息列表
|
||||
*/
|
||||
List<Message> findByParentidIsNull();
|
||||
@@ -34,6 +28,7 @@ public interface MessageRepository extends JpaRepository<Message, Integer> {
|
||||
// 根据父消息ID查询回复
|
||||
/**
|
||||
* 根据父消息ID查询回复
|
||||
*
|
||||
* @param parentid 父消息ID
|
||||
* @return 回复消息列表
|
||||
*/
|
||||
@@ -42,6 +37,7 @@ public interface MessageRepository extends JpaRepository<Message, Integer> {
|
||||
// 根据昵称模糊查询消息
|
||||
/**
|
||||
* 根据昵称模糊查询消息
|
||||
*
|
||||
* @param nickname 昵称关键词
|
||||
* @return 包含关键词的消息列表
|
||||
*/
|
||||
@@ -49,35 +45,59 @@ public interface MessageRepository extends JpaRepository<Message, Integer> {
|
||||
|
||||
/**
|
||||
* 查询指定文章下的所有父消息(根回复)
|
||||
*
|
||||
* @param articleId 文章ID
|
||||
* @return 根回复消息列表
|
||||
*/
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid = :articleId AND m.parentid IS NULL ORDER BY m.createdAt DESC")
|
||||
List<Message> findRootMessagesByArticleId(@Param("articleId") Integer articleId);
|
||||
|
||||
/**
|
||||
* 点赞数增加
|
||||
*
|
||||
* @param messageId 消息ID
|
||||
*/
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE Message m SET m.likes = COALESCE(m.likes, 0) + 1 WHERE m.messageid = :messageId")
|
||||
void incrementLikes(@Param("messageId") Integer messageId);
|
||||
// 统计指定文章的评论数量
|
||||
|
||||
// 统计指定文章下的主留言数量
|
||||
/**
|
||||
* 根据文章ID分页查询消息
|
||||
* @param articleid 文章ID
|
||||
* @param pageable 分页信息
|
||||
* 根据文章ID分页查询消息(不包括回复)
|
||||
* @param articleid 文章ID (可选)
|
||||
* @param pageable 分页信息
|
||||
* @return 分页消息列表
|
||||
*/
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid = :articleId ORDER BY m.createdAt DESC")
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid = :articleId AND m.parentid IS NULL ORDER BY m.createdAt ASC")
|
||||
Page<Message> findByArticleId(@Param("articleId") Integer articleId, PageRequest pageable);
|
||||
/**
|
||||
* 根据页查询消息
|
||||
/**
|
||||
* 根据父ID列表,查询所有子回复(包括多级嵌套)
|
||||
* 注意:这里不递归查数据库,而是查出所有 parentid 属于某集合的留言,
|
||||
* 然后在 Java 中递归构建树(适用于层级不深的场景,如评论)
|
||||
* @param parentIds 父ID列表
|
||||
* @return 分页回复消息列表
|
||||
*/
|
||||
@Query("SELECT m FROM Message m WHERE m.parentid IN :parentIds")
|
||||
List<Message> findRepliesByParentIds( @Param("parentIds") List<Integer> parentIds);
|
||||
// 根据分页查询消息(不包括回复)
|
||||
/**
|
||||
* 根据分页查询消息(不包括回复)
|
||||
* 不包含文章ID的消息
|
||||
* @param pageable 分页信息
|
||||
* @return 分页消息列表
|
||||
*/
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid IS NULL ORDER BY m.createdAt DESC")
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid IS NULL AND m.parentid IS NULL ORDER BY m.createdAt ASC")
|
||||
Page<Message> findAllMessages(PageRequest pageable);
|
||||
|
||||
/**
|
||||
* 根据articleId查询所有回复消息
|
||||
* @param articleId 文章ID
|
||||
* @return 回复消息列表
|
||||
*/
|
||||
@Query("SELECT m FROM Message m WHERE m.articleid = :articleId AND m.parentid IS NOT NULL ORDER BY m.createdAt ASC")
|
||||
List<Message> findAllRepliesByArticleId(@Param("articleId") Integer articleId);
|
||||
|
||||
/**
|
||||
* 统计指定文章下的回复消息数量
|
||||
* @param articleId 文章ID
|
||||
@@ -87,8 +107,8 @@ public interface MessageRepository extends JpaRepository<Message, Integer> {
|
||||
Integer countReplyByArticleId(@Param("articleId") Integer articleId);
|
||||
|
||||
/**
|
||||
* 统计指定文章id parentid为空的回复消息数量
|
||||
* @param articleId 文章ID
|
||||
* 统计所有回复消息数量
|
||||
* 不包含文章ID的消息
|
||||
* @return 回复消息数量
|
||||
*/
|
||||
@Query("SELECT COUNT(m) FROM Message m WHERE m.articleid IS NULL AND m.parentid IS NULL")
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.qf.myafterprojecy.pojo.Nonsense;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@@ -18,4 +20,13 @@ public interface NonsenseRepository extends JpaRepository<Nonsense, Integer> {
|
||||
*/
|
||||
@Query("SELECT n FROM Nonsense n WHERE n.status = :status")
|
||||
List<Nonsense> findByStatus(@Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 根据状态分页获取文章列表
|
||||
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||
* @param pageable 分页信息
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@Query("SELECT n FROM Nonsense n WHERE n.status = :status")
|
||||
Page<Nonsense> findPageByStatus(@Param("status") Integer status, PageRequest pageable);
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleTreeDto;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import java.util.List;
|
||||
@@ -19,13 +21,13 @@ public interface IArticleService {
|
||||
* @param title 文章标题的一部分,用于模糊查询
|
||||
* @return 返回符合查询条件的文章列表
|
||||
*/
|
||||
ResponseMessage<List<Article>> getArticlesByTitle(String title);
|
||||
ResponseMessage<List<ArticleTreeDto>> getArticlesByTitle(String title);
|
||||
/**
|
||||
* 根据状态获取文章列表
|
||||
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
ResponseMessage<List<Article>> getArticlesByStatus(Integer status);
|
||||
ResponseMessage<List<ArticleTreeDto>> getArticlesByStatus(Integer status);
|
||||
/**
|
||||
* 获取文章数量
|
||||
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||
@@ -104,5 +106,5 @@ public interface IArticleService {
|
||||
* @param size 每页大小
|
||||
* @return 返回包含分页文章列表的ResponseMessage对象
|
||||
*/
|
||||
ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto);
|
||||
ResponseMessage<List<ArticleTreeDto>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.qf.myafterprojecy.service;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryTreeDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -19,7 +20,11 @@ public interface ICategoryService {
|
||||
* @return 返回分类列表
|
||||
*/
|
||||
ResponseMessage<List<Category>> getAllCategories();
|
||||
|
||||
/**
|
||||
* 获取分类树
|
||||
* @return 返回分类树
|
||||
*/
|
||||
ResponseMessage<List<CategoryTreeDto>> getCategoryTree();
|
||||
/**
|
||||
* 保存新分类
|
||||
* @param categoryDto 分类数据传输对象
|
||||
|
||||
@@ -4,8 +4,7 @@ import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||
|
||||
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageTreeDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,7 +21,7 @@ public interface IMessageService {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto);
|
||||
ResponseMessage<List<MessageTreeDto>> getMessagesByPage(MessagePageDto messagePageDto);
|
||||
/**
|
||||
* 获取回复消息条数 如果id为空获取文章id为空的消息条数
|
||||
* @param articleId 文章id
|
||||
@@ -68,7 +67,7 @@ public interface IMessageService {
|
||||
* @param articleId 文章ID
|
||||
* @return 消息列表
|
||||
*/
|
||||
ResponseMessage<List<Message>> getMessagesByArticleId(Integer articleId);
|
||||
// ResponseMessage<List<Message>> getMessagesByArticleId(Integer articleId);
|
||||
|
||||
/**
|
||||
* 查询所有父消息(根回复)
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.qf.myafterprojecy.service;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsensePageDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,7 +26,7 @@ public interface INonsenseService {
|
||||
* @param status 状态:0未发表 1已发表 2已删除
|
||||
* @return 疯言疯语内容列表
|
||||
*/
|
||||
ResponseMessage<List<Nonsense>> getNonsenseByStatus(Integer status);
|
||||
ResponseMessage<List<Nonsense>> getNonsenseByStatus(NonsensePageDto page);
|
||||
|
||||
/**
|
||||
* 更新疯言疯语内容状态
|
||||
@@ -48,7 +49,7 @@ public interface INonsenseService {
|
||||
* @param nonsenseDto 疯言疯语内容数据传输对象
|
||||
* @return 更新结果
|
||||
*/
|
||||
ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto);
|
||||
ResponseMessage<Nonsense> updateNonsense(NonsenseDto nonsenseDto);
|
||||
|
||||
/**
|
||||
* 删除疯言疯语内容
|
||||
|
||||
@@ -5,8 +5,10 @@ import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleTreeDto;
|
||||
import com.qf.myafterprojecy.repository.ArticleRepository;
|
||||
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
||||
import com.qf.myafterprojecy.repository.MessageRepository;
|
||||
import com.qf.myafterprojecy.service.IArticleService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -34,6 +36,9 @@ public class ArticleService implements IArticleService {
|
||||
@Autowired
|
||||
private CategoryAttributeRepository categoryAttributeRepository;
|
||||
|
||||
@Autowired
|
||||
private MessageRepository messageRepository;
|
||||
|
||||
/**
|
||||
* 根据文章ID获取文章详情
|
||||
* @param id 文章ID
|
||||
@@ -95,7 +100,7 @@ public class ArticleService implements IArticleService {
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getArticlesByStatus(Integer status) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByStatus(Integer status) {
|
||||
try {
|
||||
if (status == null) {
|
||||
return ResponseMessage.badRequest("文章状态不能为空");
|
||||
@@ -104,7 +109,8 @@ public class ArticleService implements IArticleService {
|
||||
return ResponseMessage.badRequest("文章状态值必须在0到2之间");
|
||||
}
|
||||
List<Article> articles = articleRepository.findByStatus(status);
|
||||
return ResponseMessage.success(articles, "根据状态查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articles);
|
||||
return ResponseMessage.success(articleTreeDtos, "根据状态查询文章成功");
|
||||
} catch (Exception e) {
|
||||
log.error("根据状态查询文章列表失败: {}", e.getMessage());
|
||||
return ResponseMessage.error("根据状态查询文章列表失败");
|
||||
@@ -128,7 +134,7 @@ public class ArticleService implements IArticleService {
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto) {
|
||||
if (arriclePageDto.getPagenum() == null || arriclePageDto.getPagenum() < 0) {
|
||||
arriclePageDto.setPagenum(0); // 默认第一页
|
||||
}
|
||||
@@ -136,12 +142,7 @@ public class ArticleService implements IArticleService {
|
||||
arriclePageDto.setPagesize(10); // 默认每页10条,最大100条
|
||||
}
|
||||
try {
|
||||
// 如果文章状态值是否在0到2之间则根据文章状态查询文章列表
|
||||
if (arriclePageDto.getStatus() < 0 || arriclePageDto.getStatus() > 2) {
|
||||
return ResponseMessage.badRequest("文章状态值必须在0到2之间");
|
||||
}
|
||||
PageRequest pageRequest = PageRequest.of(arriclePageDto.getPagenum(), arriclePageDto.getPagesize());
|
||||
// 如果文章分类ID不为空则根据文章分类ID查询文章列表
|
||||
if (arriclePageDto.getCategoryid() != null && arriclePageDto.getCategoryid() > 0) {
|
||||
// 如果文章分类ID不为空则根据文章分类ID查询文章列表
|
||||
List<Categoryattribute> categoryAttribute = categoryAttributeRepository.findByCategoryId(arriclePageDto.getCategoryid());
|
||||
@@ -152,20 +153,25 @@ public class ArticleService implements IArticleService {
|
||||
List<Integer> attributeids = categoryAttribute.stream().map(Categoryattribute::getAttributeid).collect(Collectors.toList());
|
||||
// 根据分类ID对应的属性ID数组分页查询文章列表
|
||||
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), attributeids, pageRequest);
|
||||
return ResponseMessage.success(articlePage, "根据分类ID分页查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articlePage.getContent());
|
||||
return ResponseMessage.page( articleTreeDtos, "根据分类ID分页查询文章成功", articlePage.getTotalPages());
|
||||
}
|
||||
// 如果文章属性ID不为空则根据文章属性ID查询文章列表
|
||||
if (arriclePageDto.getAttributeid() != null && arriclePageDto.getAttributeid() > 0) {
|
||||
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), arriclePageDto.getAttributeid(), pageRequest);
|
||||
return ResponseMessage.success(articlePage, "根据属性ID分页查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articlePage.getContent());
|
||||
return ResponseMessage.page( articleTreeDtos, "根据属性ID分页查询文章成功", articlePage.getTotalPages());
|
||||
}
|
||||
// 如果文章标题不为空则根据文章标题查询文章列表
|
||||
if (arriclePageDto.getTitle() != null && !arriclePageDto.getTitle().isEmpty()) {
|
||||
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), arriclePageDto.getTitle(), pageRequest);
|
||||
return ResponseMessage.success(articlePage, "根据标题分页查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articlePage.getContent());
|
||||
return ResponseMessage.page( articleTreeDtos, "根据标题分页查询文章成功", articlePage.getTotalPages());
|
||||
}
|
||||
|
||||
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), pageRequest);
|
||||
return ResponseMessage.success(articlePage, "根据状态分页查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articlePage.getContent());
|
||||
return ResponseMessage.page( articleTreeDtos, "根据状态分页查询文章成功", articlePage.getTotalPages());
|
||||
} catch (Exception e) {
|
||||
log.error("根据状态分页查询文章列表失败: {}", e.getMessage());
|
||||
return ResponseMessage.error("根据状态分页查询文章列表失败");
|
||||
@@ -173,13 +179,14 @@ public class ArticleService implements IArticleService {
|
||||
}
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getArticlesByTitle(String title) {
|
||||
public ResponseMessage<List<ArticleTreeDto>> getArticlesByTitle(String title) {
|
||||
try {
|
||||
if (title == null || title.isEmpty()) {
|
||||
return ResponseMessage.badRequest("文章标题不能为空");
|
||||
}
|
||||
List<Article> articles = articleRepository.findByTitle(title);
|
||||
return ResponseMessage.success(articles, "根据标题查询文章成功");
|
||||
List<ArticleTreeDto> articleTreeDtos = getArticleTree(articles);
|
||||
return ResponseMessage.success(articleTreeDtos, "根据标题查询文章成功");
|
||||
} catch (Exception e) {
|
||||
log.error("根据标题查询文章列表失败: {}", e.getMessage());
|
||||
return ResponseMessage.error("根据标题查询文章列表失败");
|
||||
@@ -208,7 +215,6 @@ public class ArticleService implements IArticleService {
|
||||
article.setUpdatedAt(LocalDateTime.now());
|
||||
article.setImg(articleDto.getImg() != null ? articleDto.getImg() : "");
|
||||
article.setStatus(articleDto.getStatus() != null ? articleDto.getStatus() : 0);
|
||||
|
||||
Article savedArticle = articleRepository.save(article);
|
||||
return ResponseMessage.save(true, savedArticle);
|
||||
} catch (DataAccessException e) {
|
||||
@@ -225,6 +231,10 @@ public class ArticleService implements IArticleService {
|
||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||
|
||||
BeanUtils.copyProperties(articleDto, article);
|
||||
|
||||
|
||||
|
||||
|
||||
article.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
Article updatedArticle = articleRepository.save(article);
|
||||
@@ -359,4 +369,41 @@ public class ArticleService implements IArticleService {
|
||||
return ResponseMessage.error("获取热门文章失败");
|
||||
}
|
||||
}
|
||||
// =========补全文章树信息
|
||||
public List<ArticleTreeDto> getArticleTree( List<Article> articlePage) {
|
||||
try {
|
||||
List<ArticleTreeDto> articleTreeDtos = articlePage.stream()
|
||||
.map(article -> {
|
||||
ArticleTreeDto dto = new ArticleTreeDto();
|
||||
dto.setArticleid(article.getArticleid());
|
||||
dto.setTitle(article.getTitle());
|
||||
dto.setContent(article.getContent());
|
||||
dto.setImg(article.getImg());
|
||||
dto.setViewcount(article.getViewCount());
|
||||
dto.setLikes(article.getLikes());
|
||||
dto.setStatus(article.getStatus());
|
||||
dto.setAttributeid(article.getAttributeid());
|
||||
// 获取属性名称
|
||||
Categoryattribute categoryAttribute = categoryAttributeRepository.findById(article.getAttributeid()).orElse(null);
|
||||
if (categoryAttribute != null) {
|
||||
dto.setAttributename(categoryAttribute.getAttributename());
|
||||
}
|
||||
dto.setMarkdownscontent(article.getMarkdownscontent());
|
||||
// 设置用户信息(Article实体中没有这些字段,暂时设置为null)
|
||||
dto.setUserid(null);
|
||||
dto.setUsername(null);
|
||||
// 获取评论数
|
||||
Integer commentcount = messageRepository.countReplyByArticleId(article.getArticleid());
|
||||
dto.setCommentcount(commentcount);
|
||||
dto.setCreatetime(article.getCreatedAt());
|
||||
dto.setUpdatetime(article.getUpdatedAt());
|
||||
return dto;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return articleTreeDtos;
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取文章树失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.qf.myafterprojecy.service.impl;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryTreeDto;
|
||||
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
||||
import com.qf.myafterprojecy.repository.CategoryRepository;
|
||||
import com.qf.myafterprojecy.service.ICategoryService;
|
||||
|
||||
@@ -15,7 +17,9 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CategoryService implements ICategoryService {
|
||||
@@ -24,6 +28,8 @@ public class CategoryService implements ICategoryService {
|
||||
|
||||
@Autowired
|
||||
private CategoryRepository categoryRepository;
|
||||
@Autowired
|
||||
private CategoryAttributeRepository categoryAttributeRepository;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
@@ -152,4 +158,35 @@ public class CategoryService implements ICategoryService {
|
||||
return ResponseMessage.error("搜索分类失败");
|
||||
}
|
||||
}
|
||||
// 获取分类树
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<CategoryTreeDto>> getCategoryTree() {
|
||||
try {
|
||||
List<Category> categories = categoryRepository.findAll();
|
||||
// System.out.println(categories);
|
||||
List<CategoryTreeDto> tree = buildCategoryTree(categories);
|
||||
return ResponseMessage.success(tree, "获取分类树成功");
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取分类树失败: {}", e.getMessage());
|
||||
return ResponseMessage.error("获取分类树失败");
|
||||
}
|
||||
}
|
||||
// 递归构建分类树
|
||||
private List<CategoryTreeDto> buildCategoryTree(List<Category> categories) {
|
||||
List<CategoryTreeDto> tree = new ArrayList<>();
|
||||
for (Category category : categories) {
|
||||
tree.add(buildCategoryTreeNode(category));
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
// 构建分类树节点
|
||||
private CategoryTreeDto buildCategoryTreeNode(Category category) {
|
||||
CategoryTreeDto node = new CategoryTreeDto();
|
||||
node.setId(category.getCategoryid());
|
||||
node.setName(category.getTypename());
|
||||
|
||||
node.setChildren(categoryAttributeRepository.findByCategoryId(category.getCategoryid()));
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageTreeDto;
|
||||
import com.qf.myafterprojecy.repository.MessageRepository;
|
||||
import com.qf.myafterprojecy.service.IMessageService;
|
||||
|
||||
@@ -11,16 +12,20 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties.Pageable;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -140,22 +145,23 @@ public class MessageService implements IMessageService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<List<Message>> getMessagesByArticleId(Integer articleId) {
|
||||
if (articleId == null || articleId <= 0) {
|
||||
logger.warn("根据文章ID查询消息时ID无效: {}", articleId);
|
||||
return ResponseMessage.badRequest("文章ID无效");
|
||||
}
|
||||
// @Override
|
||||
// public ResponseMessage<List<Message>> getMessagesByArticleId(Integer
|
||||
// articleId) {
|
||||
// if (articleId == null || articleId <= 0) {
|
||||
// logger.warn("根据文章ID查询消息时ID无效: {}", articleId);
|
||||
// return ResponseMessage.badRequest("文章ID无效");
|
||||
// }
|
||||
|
||||
try {
|
||||
logger.info("根据文章ID查询消息: {}", articleId);
|
||||
List<Message> messages = messageRepository.findByArticleid(articleId);
|
||||
return ResponseMessage.success(messages, "查询成功");
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("根据文章ID查询消息失败: {}", articleId, e);
|
||||
return ResponseMessage.error("查询消息失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
// try {
|
||||
// logger.info("根据文章ID查询消息: {}", articleId);
|
||||
// List<Message> messages = messageRepository.findByArticleid(articleId);
|
||||
// return ResponseMessage.success(messages, "查询成功");
|
||||
// } catch (DataAccessException e) {
|
||||
// logger.error("根据文章ID查询消息失败: {}", articleId, e);
|
||||
// return ResponseMessage.error("查询消息失败:" + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public ResponseMessage<List<Message>> getRootMessages() {
|
||||
@@ -235,9 +241,8 @@ public class MessageService implements IMessageService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||
public ResponseMessage<List<MessageTreeDto>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||
if (messagePageDto == null) {
|
||||
logger.warn("分页查询消息时参数为空");
|
||||
return ResponseMessage.badRequest("分页参数不能为空");
|
||||
@@ -251,21 +256,16 @@ public class MessageService implements IMessageService {
|
||||
return ResponseMessage.badRequest("每页数量无效");
|
||||
}
|
||||
try {
|
||||
// 如何文章id为空,默认根据分页基础信息查询消息
|
||||
// // 如何文章id为空,默认根据分页基础信息查询消息
|
||||
PageRequest pageable = PageRequest.of(messagePageDto.getPageNum(), messagePageDto.getPageSize());
|
||||
if (messagePageDto.getArticleid() != null && messagePageDto.getArticleid() > 0) {
|
||||
// 如果文章ID存在,根据文章ID查询消息
|
||||
Page<Message> messagePage = messageRepository.findByArticleId(messagePageDto.getArticleid(), pageable);
|
||||
return ResponseMessage.success(messagePage.getContent(), "查询成功");
|
||||
}
|
||||
// 如果文章ID不存在,根据分页基础信息查询所有消息
|
||||
Page<Message> messagePage = messageRepository.findAllMessages(pageable);
|
||||
return ResponseMessage.success(messagePage.getContent(), "查询成功");
|
||||
logger.info("根据分页基础信息查询所有消息: {}", messagePageDto);
|
||||
return buildMessageTreeDto(messagePageDto.getArticleid(), pageable);
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("分页查询消息失败: {}", messagePageDto, e);
|
||||
return ResponseMessage.error("查询消息失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取回复消息条数 如果id为空获取文章id为空的消息条数
|
||||
@Override
|
||||
public ResponseMessage<Integer> getMessageCountByArticleId(Integer articleId) {
|
||||
@@ -283,4 +283,145 @@ public class MessageService implements IMessageService {
|
||||
return ResponseMessage.error("查询回复数量失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建消息树DTO
|
||||
*
|
||||
* @param articleId 文章ID (可选)
|
||||
* @param pageable 分页信息
|
||||
* @return 消息树DTO列表
|
||||
*/
|
||||
public ResponseMessage<List<MessageTreeDto>> buildMessageTreeDto(Integer articleId, PageRequest pageable) {
|
||||
// 1. 获取主留言(分页)
|
||||
Page<Message> messagePage = null;
|
||||
if (articleId == null || articleId <= 0) {
|
||||
// 如果文章ID不存在,根据分页基础信息查询所有消息
|
||||
logger.info("根据分页基础信息查询所有消息: {}", pageable);
|
||||
messagePage = messageRepository.findAllMessages(pageable);
|
||||
logger.info("根据分页基础信息查询所有消息: {}", messagePage);
|
||||
} else {
|
||||
messagePage = messageRepository.findByArticleId(articleId, pageable);
|
||||
logger.info("根据文章ID分页查询消息: {}", messagePage);
|
||||
}
|
||||
List<Message> mainMessages = messagePage.getContent();
|
||||
int totalPages = messagePage.getTotalPages();
|
||||
// 如果没有消息,直接返回空列表
|
||||
if (mainMessages.isEmpty()) {
|
||||
logger.info("文章ID {} 下没有消息", articleId);
|
||||
return ResponseMessage.success(null);
|
||||
}
|
||||
|
||||
// 2. 获取所有子回复(一次性查询,减少数据库访问)
|
||||
// 注意:这里不递归查数据库,而是查出所有 parentid 属于某集合的留言,
|
||||
// 然后在 Java 中递归构建树(适用于层级不深的场景,如评论)、
|
||||
List<Message> allReplies = new ArrayList<>();
|
||||
if (articleId == null || articleId <= 0) {
|
||||
// 如果文章ID不存在,根据分页基础信息查询所有消息
|
||||
// 从主留言中提取所有父ID
|
||||
List<Integer> parentIds = mainMessages.stream().map(Message::getMessageid).collect(Collectors.toList());
|
||||
logger.info("根据父ID列表查询所有子回复: {}", parentIds);
|
||||
allReplies = messageRepository.findRepliesByParentIds(parentIds);
|
||||
} else {
|
||||
allReplies = messageRepository.findAllRepliesByArticleId(articleId);
|
||||
logger.info("根据文章ID查询所有子回复: {}", articleId);
|
||||
}
|
||||
|
||||
// 3. 合并所有消息(主留言 + 子回复)
|
||||
List<Message> allMessages = new ArrayList<>(mainMessages);
|
||||
allMessages.addAll(allReplies);
|
||||
|
||||
// 4. 构建消息ID到消息对象的映射
|
||||
Map<Integer, Message> messageMap = new HashMap<>();
|
||||
for (Message msg : allMessages) {
|
||||
messageMap.put(msg.getMessageid(), msg);
|
||||
}
|
||||
|
||||
// 5. 构建消息树
|
||||
Map<Integer, MessageTreeDto> treeNodeMap = new HashMap<>();
|
||||
List<MessageTreeDto> roots = new ArrayList<>();
|
||||
|
||||
// 5.1 先构建所有节点
|
||||
for (Message msg : allMessages) {
|
||||
MessageTreeDto node = convertToTreeDto(msg);
|
||||
treeNodeMap.put(msg.getMessageid(), node);
|
||||
}
|
||||
|
||||
// 5.2 构建父子关系
|
||||
for (Message msg : allMessages) {
|
||||
MessageTreeDto currentNode = treeNodeMap.get(msg.getMessageid());
|
||||
Integer parentId = msg.getParentid();
|
||||
// 处理回复信息
|
||||
Integer replyId = msg.getReplyid();
|
||||
// 如果是回复消息,获取被回复者的昵称
|
||||
if (replyId != null && replyId > 0) {
|
||||
Message replyMsg = messageMap.get(replyId);
|
||||
if (replyMsg != null) {
|
||||
// 建议:在MessageTreeDto中添加replyToNickname字段
|
||||
currentNode.setReplyToNickname(replyMsg.getNickname());
|
||||
// 而不是修改发送者昵称:currentNode.setNickname("@" + replyMsg.getNickname());
|
||||
}
|
||||
}
|
||||
if (parentId == null || parentId <= 0) {
|
||||
// 主留言,直接添加到根列表
|
||||
roots.add(currentNode);
|
||||
} else {
|
||||
// 子回复,添加到父节点的children列表
|
||||
MessageTreeDto parentNode = treeNodeMap.get(parentId);
|
||||
if (parentNode != null) {
|
||||
parentNode.getChildren().add(currentNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 6. 计算每个节点的回复数
|
||||
for (MessageTreeDto node : treeNodeMap.values()) {
|
||||
int replyCount = calculateReplyCount(node);
|
||||
node.setReplyCount(replyCount);
|
||||
}
|
||||
|
||||
// 7. 排序:根节点按时间倒序(最新的在前面)
|
||||
roots.sort(Comparator.comparing(MessageTreeDto::getCreatedAt).reversed());
|
||||
|
||||
// 8. 对每个根节点的子节点按时间排序
|
||||
for (MessageTreeDto root : roots) {
|
||||
sortChildrenByTime(root);
|
||||
}
|
||||
|
||||
return ResponseMessage.page(roots, "查询成功", totalPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Message转换为MessageTreeDto
|
||||
*/
|
||||
private MessageTreeDto convertToTreeDto(Message msg) {
|
||||
MessageTreeDto dto = new MessageTreeDto();
|
||||
// 使用Spring的BeanUtils进行属性复制
|
||||
BeanUtils.copyProperties(msg, dto);
|
||||
// 初始化children列表
|
||||
dto.setChildren(new ArrayList<>());
|
||||
dto.setReplyCount(0);
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算节点的回复总数(包括所有子回复)
|
||||
*/
|
||||
private int calculateReplyCount(MessageTreeDto node) {
|
||||
int count = node.getChildren().size();
|
||||
for (MessageTreeDto child : node.getChildren()) {
|
||||
count += calculateReplyCount(child);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归按时间排序子节点
|
||||
*/
|
||||
private void sortChildrenByTime(MessageTreeDto node) {
|
||||
node.getChildren().sort(Comparator.comparing(MessageTreeDto::getCreatedAt));
|
||||
for (MessageTreeDto child : node.getChildren()) {
|
||||
sortChildrenByTime(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.qf.myafterprojecy.service.impl;
|
||||
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||
import com.qf.myafterprojecy.pojo.dto.NonsensePageDto;
|
||||
import com.qf.myafterprojecy.repository.NonsenseRepository;
|
||||
import com.qf.myafterprojecy.service.INonsenseService;
|
||||
|
||||
@@ -10,7 +11,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties.Pageable;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -48,38 +52,43 @@ public class NonsenseService implements INonsenseService {
|
||||
if (nonsenseOptional.isPresent()) {
|
||||
Nonsense nonsense = nonsenseOptional.get();
|
||||
logger.info("获取ID为{}的疯言疯语内容成功,状态: {}", id, nonsense.getStatus());
|
||||
return new ResponseMessage<>(200, "获取成功", nonsense, true);
|
||||
return ResponseMessage.success(nonsense, "获取成功");
|
||||
} else {
|
||||
logger.warn("未找到ID为{}的疯言疯语内容", id);
|
||||
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||
return ResponseMessage.error(404, "未找到指定疯言疯语内容");
|
||||
}
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("根据ID查询疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "数据库查询异常", null, false);
|
||||
return ResponseMessage.error(500, "数据库查询异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("根据ID查询疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(Integer status) {
|
||||
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(NonsensePageDto page) {
|
||||
try {
|
||||
// 验证状态值是否有效
|
||||
if (status < 0 || status > 2) {
|
||||
logger.warn("无效的状态值: {}", status);
|
||||
return new ResponseMessage<>(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)", null, false);
|
||||
if (page.getStatus() < 0 || page.getStatus() > 2) {
|
||||
logger.warn("无效的状态值: {}", page.getStatus());
|
||||
return ResponseMessage.error(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)");
|
||||
}
|
||||
// 分页查询
|
||||
PageRequest pageable = PageRequest.of(page.getPageNum(), page.getPageSize());
|
||||
|
||||
List<Nonsense> nonsenseList = nonsenseRepository.findByStatus(status);
|
||||
// 根据状态过滤
|
||||
return new ResponseMessage<>(200, "获取成功", nonsenseList, true);
|
||||
Page<Nonsense> pageResult = nonsenseRepository.findPageByStatus(page.getStatus(), pageable);
|
||||
|
||||
// 根据状态过滤已发表(1)的内容
|
||||
List<Nonsense> filteredNonsense = pageResult.getContent();
|
||||
|
||||
return ResponseMessage.page(filteredNonsense, "获取成功", pageResult.getTotalPages());
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("根据状态获取疯言疯语内容失败,状态: {}", status, e);
|
||||
return new ResponseMessage<>(500, "数据库查询异常", null, false);
|
||||
logger.error("根据状态获取疯言疯语内容失败,状态: {}", page.getStatus(), e);
|
||||
return ResponseMessage.error(500, "数据库查询异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("根据状态获取疯言疯语内容失败,状态: {}", status, e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||
logger.error("根据状态获取疯言疯语内容失败,状态: {}", page.getStatus(), e);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +99,7 @@ public class NonsenseService implements INonsenseService {
|
||||
// 验证状态值是否有效
|
||||
if (status < 0 || status > 2) {
|
||||
logger.warn("无效的状态值: {} 用于ID为{}的疯言疯语内容", status, id);
|
||||
return new ResponseMessage<>(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)", null, false);
|
||||
return ResponseMessage.error(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)");
|
||||
}
|
||||
|
||||
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
|
||||
@@ -101,17 +110,17 @@ public class NonsenseService implements INonsenseService {
|
||||
|
||||
Nonsense updatedNonsense = nonsenseRepository.save(nonsense);
|
||||
logger.info("更新疯言疯语内容状态成功,ID: {}, 旧状态: {}, 新状态: {}", id, oldStatus, status);
|
||||
return new ResponseMessage<>(200, "状态更新成功", updatedNonsense, true);
|
||||
return ResponseMessage.success(updatedNonsense, "状态更新成功");
|
||||
} else {
|
||||
logger.warn("更新状态失败,未找到ID为{}的疯言疯语内容", id);
|
||||
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||
return ResponseMessage.error(404, "未找到指定疯言疯语内容");
|
||||
}
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("更新疯言疯语内容状态失败,ID: {}, 状态: {}", id, status, e);
|
||||
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||
return ResponseMessage.error(500, "数据库操作异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("更新疯言疯语内容状态失败,ID: {}, 状态: {}", id, status, e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,42 +143,42 @@ public class NonsenseService implements INonsenseService {
|
||||
|
||||
Nonsense savedNonsense = nonsenseRepository.save(nonsense);
|
||||
logger.info("保存疯言疯语内容成功,ID: {}, 状态: {}", savedNonsense.getId(), savedNonsense.getStatus());
|
||||
return new ResponseMessage<>(200, "保存成功", savedNonsense, true);
|
||||
return ResponseMessage.success(savedNonsense, "保存成功");
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("保存疯言疯语内容失败", e);
|
||||
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||
return ResponseMessage.error(500, "数据库操作异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("保存疯言疯语内容失败", e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto) {
|
||||
public ResponseMessage<Nonsense> updateNonsense(NonsenseDto nonsenseDto) {
|
||||
try {
|
||||
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
|
||||
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(nonsenseDto.getId());
|
||||
if (nonsenseOptional.isPresent()) {
|
||||
Nonsense nonsense = nonsenseOptional.get();
|
||||
// 只有当DTO中提供了status值时才更新
|
||||
if (nonsenseDto.getStatus() != null) {
|
||||
logger.info("更新疯言疯语内容状态,ID: {}, 新状态: {}", id, nonsenseDto.getStatus());
|
||||
logger.info("更新疯言疯语内容状态,ID: {}, 新状态: {}", nonsenseDto.getId(), nonsenseDto.getStatus());
|
||||
}
|
||||
BeanUtils.copyProperties(nonsenseDto, nonsense, "id");
|
||||
|
||||
Nonsense updatedNonsense = nonsenseRepository.save(nonsense);
|
||||
logger.info("更新疯言疯语内容成功,ID: {}, 当前状态: {}", id, updatedNonsense.getStatus());
|
||||
return new ResponseMessage<>(200, "更新成功", updatedNonsense, true);
|
||||
logger.info("更新疯言疯语内容成功,ID: {}, 当前状态: {}", nonsenseDto.getId(), updatedNonsense.getStatus());
|
||||
return ResponseMessage.success(updatedNonsense, "更新成功");
|
||||
} else {
|
||||
logger.warn("更新失败,未找到ID为{}的疯言疯语内容", id);
|
||||
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||
logger.warn("更新失败,未找到ID为{}的疯言疯语内容", nonsenseDto.getId());
|
||||
return ResponseMessage.error(404, "未找到指定疯言疯语内容");
|
||||
}
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("更新疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||
logger.error("更新疯言疯语内容失败,ID: {}", nonsenseDto.getId(), e);
|
||||
return ResponseMessage.error(500, "数据库操作异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("更新疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||
logger.error("更新疯言疯语内容失败,ID: {}", nonsenseDto.getId(), e);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,17 +195,17 @@ public class NonsenseService implements INonsenseService {
|
||||
// 物理删除
|
||||
// nonsenseRepository.deleteById(id);
|
||||
logger.info("删除疯言疯语内容成功,ID: {}", id);
|
||||
return new ResponseMessage<>(200, "删除成功", true, true);
|
||||
return ResponseMessage.success(true, "删除成功");
|
||||
} else {
|
||||
logger.warn("删除失败,未找到ID为{}的疯言疯语内容", id);
|
||||
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", false, false);
|
||||
return ResponseMessage.error(404, "未找到指定疯言疯语内容");
|
||||
}
|
||||
} catch (DataAccessException e) {
|
||||
logger.error("删除疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "数据库操作异常", false, false);
|
||||
return ResponseMessage.error(500, "数据库操作异常");
|
||||
} catch (Exception e) {
|
||||
logger.error("删除疯言疯语内容失败,ID: {}", id, e);
|
||||
return new ResponseMessage<>(500, "服务器内部错误", false, false);
|
||||
return ResponseMessage.error(500, "服务器内部错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,13 @@ import java.util.function.Function;
|
||||
@Component
|
||||
public class JwtUtils {
|
||||
|
||||
@Value("${jwt.secret:default_secret_key_for_development}")
|
||||
@Value("${jwt.secret}")
|
||||
private String secret;
|
||||
|
||||
@Value("${jwt.expiration:86400000}")
|
||||
@Value("${jwt.expiration}")
|
||||
private long expiration;
|
||||
|
||||
@Value("${jwt.token-prefix:Bearer}")
|
||||
@Value("${jwt.token-prefix}")
|
||||
private String tokenPrefix;
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,11 +9,14 @@ server.port=7070
|
||||
# ====================================================================
|
||||
# 数据库与JPA配置 - 生产用
|
||||
# ====================================================================
|
||||
spring.datasource.url=${DB_URL:jdbc:mysql://mysql:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai}
|
||||
spring.datasource.username=${DB_USERNAME:root}
|
||||
spring.datasource.password=${DB_PASSWORD:root}
|
||||
# spring.datasource.url=${DB_URL:jdbc:mysql://mysql:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai}
|
||||
# spring.datasource.username=${DB_USERNAME:root}
|
||||
# spring.datasource.password=${DB_PASSWORD:root}
|
||||
# spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=123456
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
|
||||
# 数据库连接池配置(生产环境优化版)
|
||||
spring.datasource.hikari.maximum-pool-size=20
|
||||
spring.datasource.hikari.minimum-idle=5
|
||||
@@ -24,13 +27,13 @@ spring.datasource.hikari.connection-test-query=SELECT 1
|
||||
spring.datasource.hikari.pool-name=WebProjectHikariCP
|
||||
|
||||
# JPA配置(生产环境禁用自动DDL,避免意外修改表结构)
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.properties.hibernate.format_sql=false
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
|
||||
spring.jpa.open-in-view=false
|
||||
|
||||
# JPA性能优化配置
|
||||
# JPA性能优化配置(生产环境开启批量处理)
|
||||
spring.jpa.properties.hibernate.jdbc.batch_size=30
|
||||
spring.jpa.properties.hibernate.order_inserts=true
|
||||
spring.jpa.properties.hibernate.order_updates=true
|
||||
@@ -38,8 +41,8 @@ spring.jpa.properties.hibernate.order_updates=true
|
||||
# ====================================================================
|
||||
# JWT 配置 - 生产用(敏感信息从环境变量读取)
|
||||
# ====================================================================
|
||||
jwt.secret=${JWT_SECRET:}
|
||||
jwt.expiration=${JWT_EXPIRATION:86400000}
|
||||
jwt.secret=${JWT_SECRET:6a1f4832-29bf-4ac5-9408-a8813b6f2dfe}
|
||||
jwt.expiration=${JWT_EXPIRATION:3600000}
|
||||
jwt.header=Authorization
|
||||
jwt.token-prefix=Bearer
|
||||
|
||||
@@ -47,7 +50,8 @@ jwt.token-prefix=Bearer
|
||||
# 安全与CORS配置 - 生产用
|
||||
# ====================================================================
|
||||
# CORS配置(生产环境限制为具体域名)
|
||||
cors.allowed-origins=http://qf1121.top,https://qf1121.top,http://www.qf1121.top,https://www.qf1121.top
|
||||
# cors.allowed-origins=http://qf1121.top,https://qf1121.top,http://www.qf1121.top,https://www.qf1121.top
|
||||
cors.allowed-origins=http://localhost:3000,http://localhost:8080,http://localhost:5173
|
||||
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
||||
cors.allowed-headers=*
|
||||
cors.allow-credentials=true
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
# ====================================================================
|
||||
# 环境激活配置
|
||||
# 说明:默认激活开发环境,生产环境部署时应通过命令行参数或环境变量覆盖
|
||||
spring.profiles.active=dev
|
||||
server.port=7070
|
||||
spring.profiles.active=prod
|
||||
# 应用名称(通用配置)
|
||||
spring.application.name=web_project
|
||||
|
||||
|
||||
Reference in New Issue
Block a user