feat(web): 新增博客首页文章、分类、标签及博客设置相关接口
- 新增ArticleController提供首页文章分页查询接口 - 实现ArticleService及其实现类,支持分页查询文章及其分类标签关联信息 - 扩展ArticleCategoryRelRepository和ArticleTagRelRepository,支持批量查询文章关联分类和标签 - 新增CategoryController及CategoryService,实现前台分类列表查询接口 - 新增TagController及TagService,实现前台标签列表查询接口 - 新增BlogSettingsController及BlogSettingsService,支持博客配置信息查询 - 添加相应的请求响应VO,包含文章、分类、标签及博客设置数据结构 - 移除无用的User模型代码,简化项目结构
This commit is contained in:
1
.idea/ApifoxUploaderProjectSetting.xml
generated
1
.idea/ApifoxUploaderProjectSetting.xml
generated
@@ -5,6 +5,7 @@
|
|||||||
<option name="apiProjectIds">
|
<option name="apiProjectIds">
|
||||||
<array>
|
<array>
|
||||||
<option value="<byte-array>rO0ABXNyADZjb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50LlByb2plY3RBbmRNb2R1bGUAAAAAAAAAAQIAFVoABmVuYWJsZUwACG1vZHVsZUlkdAASTGphdmEvbGFuZy9TdHJpbmc7TAAGb3RoZXIxcQB+AAFMAAdvdGhlcjEwcQB+AAFMAAdvdGhlcjExcQB+AAFMAAdvdGhlcjEycQB+AAFMAAZvdGhlcjJxAH4AAUwABm90aGVyM3EAfgABTAAGb3RoZXI0cQB+AAFMAAZvdGhlcjVxAH4AAUwABm90aGVyNnEAfgABTAAGb3RoZXI3cQB+AAFMAAZvdGhlcjhxAH4AAUwABm90aGVyOXEAfgABTAAKcGF0aEJlZm9yZXEAfgABTAANcHJvamVjdEZvbGRlcnEAfgABTAAPcHJvamVjdEZvbGRlcklkcQB+AAFMAAlwcm9qZWN0SWRxAH4AAUwAC3Byb2plY3ROYW1lcQB+AAFMAAxzY2hlbWFGb2xkZXJxAH4AAUwACHNjaGVtYUlkcQB+AAF4cAF0ACp3ZWJsb2ctc3ByaW5nYm9vdC53ZWJsb2ctbW9kdWxlLWFkbWluLm1haW50AAc3MjIwMjQ1cHBwdAAHNjY1NzM5NHQAC2JyYW5jaC1tYWludAAM6buY6K6k5qih5Z2XcHBwcHB0AAB0AAnmoLnnm67lvZV0AAEwdAAHNzQ4NDkxM3QABVdCbG9ncQB+AAlxAH4ACg==</byte-array>" />
|
<option value="<byte-array>rO0ABXNyADZjb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50LlByb2plY3RBbmRNb2R1bGUAAAAAAAAAAQIAFVoABmVuYWJsZUwACG1vZHVsZUlkdAASTGphdmEvbGFuZy9TdHJpbmc7TAAGb3RoZXIxcQB+AAFMAAdvdGhlcjEwcQB+AAFMAAdvdGhlcjExcQB+AAFMAAdvdGhlcjEycQB+AAFMAAZvdGhlcjJxAH4AAUwABm90aGVyM3EAfgABTAAGb3RoZXI0cQB+AAFMAAZvdGhlcjVxAH4AAUwABm90aGVyNnEAfgABTAAGb3RoZXI3cQB+AAFMAAZvdGhlcjhxAH4AAUwABm90aGVyOXEAfgABTAAKcGF0aEJlZm9yZXEAfgABTAANcHJvamVjdEZvbGRlcnEAfgABTAAPcHJvamVjdEZvbGRlcklkcQB+AAFMAAlwcm9qZWN0SWRxAH4AAUwAC3Byb2plY3ROYW1lcQB+AAFMAAxzY2hlbWFGb2xkZXJxAH4AAUwACHNjaGVtYUlkcQB+AAF4cAF0ACp3ZWJsb2ctc3ByaW5nYm9vdC53ZWJsb2ctbW9kdWxlLWFkbWluLm1haW50AAc3MjIwMjQ1cHBwdAAHNjY1NzM5NHQAC2JyYW5jaC1tYWludAAM6buY6K6k5qih5Z2XcHBwcHB0AAB0AAnmoLnnm67lvZV0AAEwdAAHNzQ4NDkxM3QABVdCbG9ncQB+AAlxAH4ACg==</byte-array>" />
|
||||||
|
<option value="<byte-array>rO0ABXNyADZjb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50LlByb2plY3RBbmRNb2R1bGUAAAAAAAAAAQIAFVoABmVuYWJsZUwACG1vZHVsZUlkdAASTGphdmEvbGFuZy9TdHJpbmc7TAAGb3RoZXIxcQB+AAFMAAdvdGhlcjEwcQB+AAFMAAdvdGhlcjExcQB+AAFMAAdvdGhlcjEycQB+AAFMAAZvdGhlcjJxAH4AAUwABm90aGVyM3EAfgABTAAGb3RoZXI0cQB+AAFMAAZvdGhlcjVxAH4AAUwABm90aGVyNnEAfgABTAAGb3RoZXI3cQB+AAFMAAZvdGhlcjhxAH4AAUwABm90aGVyOXEAfgABTAAKcGF0aEJlZm9yZXEAfgABTAANcHJvamVjdEZvbGRlcnEAfgABTAAPcHJvamVjdEZvbGRlcklkcQB+AAFMAAlwcm9qZWN0SWRxAH4AAUwAC3Byb2plY3ROYW1lcQB+AAFMAAxzY2hlbWFGb2xkZXJxAH4AAUwACHNjaGVtYUlkcQB+AAF4cAF0ACF3ZWJsb2ctc3ByaW5nYm9vdC53ZWJsb2ctd2ViLm1haW50AAc3MjIwMjQ1cHBwdAAHNjY1NzM5NHQAC2JyYW5jaC1tYWludAAM6buY6K6k5qih5Z2XcHBwcHB0AAB0AAnmoLnnm67lvZV0AAEwdAAHNzQ4NDkxM3QABVdCbG9ncQB+AAlxAH4ACg==</byte-array>" />
|
||||||
</array>
|
</array>
|
||||||
</option>
|
</option>
|
||||||
<option name="treeNodes" value="<byte-array>rO0ABXNyABdqYXZhLnV0aWwuTGlua2VkSGFzaE1hcDTATlwQbMD7AgABWgALYWNjZXNzT3JkZXJ4cgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAnQABzM0MjU5MzBzcgAuY29tLml0YW5nY2VudC5pZGVhLnBsdWdpbi5hcGkuYWNjb3VudC5UcmVlTm9kZQAAAAAAAAABAgAQTAAHYWxsUGF0aHQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAFGJyYW5jaEFuZFZlcnNpb25JdGVtdABLW0xjb20vaXRhbmdjZW50L2lkZWEvcGx1Z2luL2RpYWxvZy9jb21wb25lbnQvYWNjb3VudC9BY2NvdW50UmlnaHRQYW5lbEl0ZW07TAAUYnJhbmNoSWRBbmRWZXJzaW9uSWRxAH4ABUwACGNoaWxkcmVudAAPTGphdmEvdXRpbC9NYXA7TAAKZm9sZGVyVHlwZXEAfgAFTAAIZnVsbFBhdGhxAH4ABUwAA2tleXEAfgAFWwAJbW9kZWxJdGVtcQB+AAZMAAhtb2R1bGVJZHEAfgAFTAAEbmFtZXEAfgAFTAAIcGFyZW50SWRxAH4ABUwACXByb2plY3RJZHEAfgAFTAALcHJvamVjdE5hbWVxAH4ABUwABnRlYW1JZHEAfgAFTAAIdGVhbU5hbWVxAH4ABUwABHR5cGV0ADBMY29tL2l0YW5nY2VudC9pZGVhL3BsdWdpbi9hcGkvYWNjb3VudC9Ob2RlVHlwZTt4cHQADOS4quS6uuWboumYn3Bwc3EAfgAAP0AAAAAAAAx3CAAAABAAAAABdAAHNzQ4NDkxM3NxAH4ABHQAEuS4quS6uuWboumYny9XQmxvZ3Bwc3EAfgAAP0AAAAAAAAB3CAAAABAAAAAAeABwcHEAfgAMcHB0AA9XQmxvZyAoNzQ4NDkxMyl0AAczNDI1OTMwcQB+AAx0AAVXQmxvZ3EAfgARcH5yAC5jb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50Lk5vZGVUeXBlAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAHUFJPSkVDVHgAcHBxAH4AA3BwcQB+AApwcHBxAH4AA3EAfgAKfnEAfgATdAAEVEVBTXQABzM5NjY0MDlzcQB+AAR0AAlIYW5zZXJEZXZwcHNxAH4AAD9AAAAAAAAMdwgAAAAQAAAAAXQABzc0NjI0NzJzcQB+AAR0ABlIYW5zZXJEZXYvSU4tQUktaW50ZXJ2aWV3cHBzcQB+AAA/QAAAAAAAAHcIAAAAEAAAAAB4AHBwcQB+AB1wcHQAGUlOLUFJLWludGVydmlldyAoNzQ2MjQ3Mil0AAczOTY2NDA5cQB+AB10AA9JTi1BSS1pbnRlcnZpZXdxAH4AInBxAH4AFXgAcHBxAH4AGXBwcQB+ABtwcHBxAH4AGXEAfgAbcQB+ABd4AA==</byte-array>" />
|
<option name="treeNodes" value="<byte-array>rO0ABXNyABdqYXZhLnV0aWwuTGlua2VkSGFzaE1hcDTATlwQbMD7AgABWgALYWNjZXNzT3JkZXJ4cgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAnQABzM0MjU5MzBzcgAuY29tLml0YW5nY2VudC5pZGVhLnBsdWdpbi5hcGkuYWNjb3VudC5UcmVlTm9kZQAAAAAAAAABAgAQTAAHYWxsUGF0aHQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAFGJyYW5jaEFuZFZlcnNpb25JdGVtdABLW0xjb20vaXRhbmdjZW50L2lkZWEvcGx1Z2luL2RpYWxvZy9jb21wb25lbnQvYWNjb3VudC9BY2NvdW50UmlnaHRQYW5lbEl0ZW07TAAUYnJhbmNoSWRBbmRWZXJzaW9uSWRxAH4ABUwACGNoaWxkcmVudAAPTGphdmEvdXRpbC9NYXA7TAAKZm9sZGVyVHlwZXEAfgAFTAAIZnVsbFBhdGhxAH4ABUwAA2tleXEAfgAFWwAJbW9kZWxJdGVtcQB+AAZMAAhtb2R1bGVJZHEAfgAFTAAEbmFtZXEAfgAFTAAIcGFyZW50SWRxAH4ABUwACXByb2plY3RJZHEAfgAFTAALcHJvamVjdE5hbWVxAH4ABUwABnRlYW1JZHEAfgAFTAAIdGVhbU5hbWVxAH4ABUwABHR5cGV0ADBMY29tL2l0YW5nY2VudC9pZGVhL3BsdWdpbi9hcGkvYWNjb3VudC9Ob2RlVHlwZTt4cHQADOS4quS6uuWboumYn3Bwc3EAfgAAP0AAAAAAAAx3CAAAABAAAAABdAAHNzQ4NDkxM3NxAH4ABHQAEuS4quS6uuWboumYny9XQmxvZ3Bwc3EAfgAAP0AAAAAAAAB3CAAAABAAAAAAeABwcHEAfgAMcHB0AA9XQmxvZyAoNzQ4NDkxMyl0AAczNDI1OTMwcQB+AAx0AAVXQmxvZ3EAfgARcH5yAC5jb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50Lk5vZGVUeXBlAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAHUFJPSkVDVHgAcHBxAH4AA3BwcQB+AApwcHBxAH4AA3EAfgAKfnEAfgATdAAEVEVBTXQABzM5NjY0MDlzcQB+AAR0AAlIYW5zZXJEZXZwcHNxAH4AAD9AAAAAAAAMdwgAAAAQAAAAAXQABzc0NjI0NzJzcQB+AAR0ABlIYW5zZXJEZXYvSU4tQUktaW50ZXJ2aWV3cHBzcQB+AAA/QAAAAAAAAHcIAAAAEAAAAAB4AHBwcQB+AB1wcHQAGUlOLUFJLWludGVydmlldyAoNzQ2MjQ3Mil0AAczOTY2NDA5cQB+AB10AA9JTi1BSS1pbnRlcnZpZXdxAH4AInBxAH4AFXgAcHBxAH4AGXBwcQB+ABtwcHBxAH4AGXEAfgAbcQB+ABd4AA==</byte-array>" />
|
||||||
|
|||||||
@@ -17,4 +17,6 @@ public interface ArticleCategoryRelRepository extends JpaRepository<ArticleCateg
|
|||||||
ArticleCategoryRel findByArticleId(Long articleId);
|
ArticleCategoryRel findByArticleId(Long articleId);
|
||||||
|
|
||||||
List<ArticleCategoryRel> findByCategoryId(Long categoryId);
|
List<ArticleCategoryRel> findByCategoryId(Long categoryId);
|
||||||
|
|
||||||
|
List<ArticleCategoryRel> findByArticleIdIn(List<Long> articleIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Modifying;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ArticleTagRelRepository extends JpaRepository<ArticleTagRel, Long> {
|
public interface ArticleTagRelRepository extends JpaRepository<ArticleTagRel, Long> {
|
||||||
@@ -16,4 +17,6 @@ public interface ArticleTagRelRepository extends JpaRepository<ArticleTagRel, Lo
|
|||||||
List<ArticleTagRel> findByArticleId(Long articleId);
|
List<ArticleTagRel> findByArticleId(Long articleId);
|
||||||
|
|
||||||
List<ArticleTagRel> findByTagId(Long tagId);
|
List<ArticleTagRel> findByTagId(Long tagId);
|
||||||
|
|
||||||
|
List<ArticleTagRel> findByArticleIdIn(Collection<Long> articleIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ import org.springframework.data.jpa.domain.Specification;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface CategoryRepository extends JpaRepository<Category, Long>, JpaSpecificationExecutor<Category> {
|
public interface CategoryRepository extends JpaRepository<Category, Long>, JpaSpecificationExecutor<Category> {
|
||||||
boolean existsCategoryByName(String name);
|
boolean existsCategoryByName(String name);
|
||||||
|
|
||||||
Page<Category> findAll(Specification<Category> specification, Pageable pageable);
|
Page<Category> findAll(Specification<Category> specification, Pageable pageable);
|
||||||
|
|
||||||
|
List<Category> findAllByIdIn(Collection<Long> ids);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.hanserwei.web.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.common.aspect.ApiOperationLog;
|
||||||
|
import com.hanserwei.common.utils.PageResponse;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListReqVO;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListRspVO;
|
||||||
|
import com.hanserwei.web.service.ArticleService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章控制器
|
||||||
|
*
|
||||||
|
* @author hanserwei
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class ArticleController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ArticleService articleService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取首页文章分页数据
|
||||||
|
*/
|
||||||
|
@PostMapping("/article/list")
|
||||||
|
@ApiOperationLog(description = "获取首页文章分页数据")
|
||||||
|
public PageResponse<FindIndexArticlePageListRspVO> findArticlePageList(@RequestBody FindIndexArticlePageListReqVO findIndexArticlePageListReqVO) {
|
||||||
|
return articleService.findArticlePageList(findIndexArticlePageListReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.hanserwei.web.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.common.aspect.ApiOperationLog;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.blogsetting.FindBlogSettingsDetailRspVO;
|
||||||
|
import com.hanserwei.web.service.BlogSettingsService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 博客设置控制器
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/blog/settings")
|
||||||
|
public class BlogSettingsController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BlogSettingsService blogSettingsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取博客设置详情
|
||||||
|
*/
|
||||||
|
@PostMapping("/detail")
|
||||||
|
@ApiOperationLog(description = "前台获取博客详情")
|
||||||
|
public Response<FindBlogSettingsDetailRspVO> findDetail() {
|
||||||
|
return blogSettingsService.findDetail();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.hanserwei.web.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.common.aspect.ApiOperationLog;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.category.FindCategoryListRspVO;
|
||||||
|
import com.hanserwei.web.service.CategoryService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类控制器
|
||||||
|
*
|
||||||
|
* @author hanserwei
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/category")
|
||||||
|
public class CategoryController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CategoryService categoryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台获取分类列表
|
||||||
|
*/
|
||||||
|
@PostMapping("/list")
|
||||||
|
@ApiOperationLog(description = "前台获取分类列表")
|
||||||
|
public Response<List<FindCategoryListRspVO>> findCategoryList() {
|
||||||
|
return categoryService.findCategoryList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.hanserwei.web.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.common.aspect.ApiOperationLog;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.tag.FindTagListRspVO;
|
||||||
|
import com.hanserwei.web.service.TagService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签控制器
|
||||||
|
*
|
||||||
|
* @author hanserwei
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/tag")
|
||||||
|
public class TagController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TagService tagService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取标签列表
|
||||||
|
*/
|
||||||
|
@PostMapping("/list")
|
||||||
|
@ApiOperationLog(description = "前台获取标签列表")
|
||||||
|
public Response<List<FindTagListRspVO>> findTagList() {
|
||||||
|
return tagService.findTagList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package com.hanserwei.web.model;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.*;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class User {
|
|
||||||
// 用户名
|
|
||||||
@NotBlank(message = "用户名不能为空") // 注解确保用户名不为空
|
|
||||||
private String username;
|
|
||||||
// 性别
|
|
||||||
@NotNull(message = "性别不能为空") // 注解确保性别不为空
|
|
||||||
private Integer sex;
|
|
||||||
|
|
||||||
// 年龄
|
|
||||||
@NotNull(message = "年龄不能为空")
|
|
||||||
@Min(value = 18, message = "年龄必须大于或等于 18") // 注解确保年龄大于等于 18
|
|
||||||
@Max(value = 100, message = "年龄必须小于或等于 100") // 注解确保年龄小于等于 100
|
|
||||||
private Integer age;
|
|
||||||
|
|
||||||
// 邮箱
|
|
||||||
@NotBlank(message = "邮箱不能为空")
|
|
||||||
@Email(message = "邮箱格式不正确") // 注解确保邮箱格式正确
|
|
||||||
private String email;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.hanserwei.web.model.vo.article;
|
||||||
|
|
||||||
|
import com.hanserwei.common.model.BasePageQuery;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class FindIndexArticlePageListReqVO extends BasePageQuery {
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.hanserwei.web.model.vo.article;
|
||||||
|
|
||||||
|
import com.hanserwei.web.model.vo.category.FindCategoryListRspVO;
|
||||||
|
import com.hanserwei.web.model.vo.tag.FindTagListRspVO;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindIndexArticlePageListRspVO {
|
||||||
|
/**
|
||||||
|
* 文章id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 封面url
|
||||||
|
*/
|
||||||
|
private String cover;
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
/**
|
||||||
|
* 摘要
|
||||||
|
*/
|
||||||
|
private String summary;
|
||||||
|
/**
|
||||||
|
* 文章分类
|
||||||
|
*/
|
||||||
|
private FindCategoryListRspVO category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章标签
|
||||||
|
*/
|
||||||
|
private List<FindTagListRspVO> tags;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.hanserwei.web.model.vo.blogsetting;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 博客设置详情响应VO
|
||||||
|
*/
|
||||||
|
public class FindBlogSettingsDetailRspVO {
|
||||||
|
/**
|
||||||
|
* 博客Logo
|
||||||
|
*/
|
||||||
|
private String logo;
|
||||||
|
/**
|
||||||
|
* 博客名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 作者名称
|
||||||
|
*/
|
||||||
|
private String author;
|
||||||
|
/**
|
||||||
|
* 博客介绍
|
||||||
|
*/
|
||||||
|
private String introduction;
|
||||||
|
/**
|
||||||
|
* 作者头像
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
/**
|
||||||
|
* GitHub主页
|
||||||
|
*/
|
||||||
|
private String githubHomepage;
|
||||||
|
/**
|
||||||
|
* CSDN主页
|
||||||
|
*/
|
||||||
|
private String csdnHomepage;
|
||||||
|
/**
|
||||||
|
* Gitee主页
|
||||||
|
*/
|
||||||
|
private String giteeHomepage;
|
||||||
|
/**
|
||||||
|
* 知乎主页
|
||||||
|
*/
|
||||||
|
private String zhihuHomepage;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.hanserwei.web.model.vo.category;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindCategoryListRspVO {
|
||||||
|
/**
|
||||||
|
* 分类id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.hanserwei.web.model.vo.tag;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindTagListRspVO {
|
||||||
|
/**
|
||||||
|
* 标签id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 标签名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.hanserwei.web.service;
|
||||||
|
|
||||||
|
import com.hanserwei.common.utils.PageResponse;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListReqVO;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListRspVO;
|
||||||
|
|
||||||
|
public interface ArticleService {
|
||||||
|
/**
|
||||||
|
* 获取首页文章分页数据
|
||||||
|
*
|
||||||
|
* @param findIndexArticlePageListReqVO 获取首页文章分页数据请求参数
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
PageResponse<FindIndexArticlePageListRspVO> findArticlePageList(FindIndexArticlePageListReqVO findIndexArticlePageListReqVO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.hanserwei.web.service;
|
||||||
|
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.blogsetting.FindBlogSettingsDetailRspVO;
|
||||||
|
|
||||||
|
public interface BlogSettingsService {
|
||||||
|
/**
|
||||||
|
* 获取博客设置信息
|
||||||
|
*
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
Response<FindBlogSettingsDetailRspVO> findDetail();
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.hanserwei.web.service;
|
||||||
|
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.category.FindCategoryListRspVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface CategoryService {
|
||||||
|
/**
|
||||||
|
* 获取分类列表
|
||||||
|
*
|
||||||
|
* @return 分类列表
|
||||||
|
*/
|
||||||
|
Response<List<FindCategoryListRspVO>> findCategoryList();
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.hanserwei.web.service;
|
||||||
|
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.tag.FindTagListRspVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface TagService {
|
||||||
|
/**
|
||||||
|
* 获取标签列表
|
||||||
|
*
|
||||||
|
* @return 标签列表
|
||||||
|
*/
|
||||||
|
Response<List<FindTagListRspVO>> findTagList();
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.hanserwei.web.service.impl;
|
||||||
|
|
||||||
|
import com.hanserwei.common.domain.dataobject.*;
|
||||||
|
import com.hanserwei.common.domain.repository.*;
|
||||||
|
import com.hanserwei.common.utils.PageHelper;
|
||||||
|
import com.hanserwei.common.utils.PageResponse;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListReqVO;
|
||||||
|
import com.hanserwei.web.model.vo.article.FindIndexArticlePageListRspVO;
|
||||||
|
import com.hanserwei.web.model.vo.category.FindCategoryListRspVO;
|
||||||
|
import com.hanserwei.web.model.vo.tag.FindTagListRspVO;
|
||||||
|
import com.hanserwei.web.service.ArticleService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ArticleServiceImpl implements ArticleService {
|
||||||
|
@Resource
|
||||||
|
private ArticleRepository articleRepository;
|
||||||
|
@Resource
|
||||||
|
private CategoryRepository categoryRepository;
|
||||||
|
@Resource
|
||||||
|
private ArticleContentRepository articleContentRepository;
|
||||||
|
@Resource
|
||||||
|
private ArticleCategoryRelRepository articleCategoryRelRepository;
|
||||||
|
@Resource
|
||||||
|
private TagRepository tagRepository;
|
||||||
|
@Resource
|
||||||
|
private ArticleTagRelRepository articleTagRelRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResponse<FindIndexArticlePageListRspVO> findArticlePageList(FindIndexArticlePageListReqVO findIndexArticlePageListReqVO) {
|
||||||
|
// 查询文章主体数据
|
||||||
|
PageResponse<Article> articlePageResponse = PageHelper.findPageList(articleRepository,
|
||||||
|
findIndexArticlePageListReqVO,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
e -> e);
|
||||||
|
List<Article> articleList = articlePageResponse.getData();
|
||||||
|
List<FindIndexArticlePageListRspVO> vos = null;
|
||||||
|
if (!CollectionUtils.isEmpty(articleList)) {
|
||||||
|
vos = articleList.stream().map(e -> {
|
||||||
|
FindIndexArticlePageListRspVO vo = new FindIndexArticlePageListRspVO();
|
||||||
|
BeanUtils.copyProperties(e, vo);
|
||||||
|
// 手动设置 createTime,因为 Instant 无法自动转换为 LocalDateTime
|
||||||
|
if (e.getCreateTime() != null) {
|
||||||
|
vo.setCreateTime(java.time.LocalDateTime.ofInstant(e.getCreateTime(), java.time.ZoneId.systemDefault()));
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}).toList();
|
||||||
|
// 拿到所有文章的 ID 集合
|
||||||
|
List<Long> articleIds = articleList.stream().map(Article::getId).toList();
|
||||||
|
|
||||||
|
// 第二步:设置文章所属分类
|
||||||
|
// 根据文章 ID 批量查询所有关联记录
|
||||||
|
List<ArticleCategoryRel> articleCategoryRelList = articleCategoryRelRepository.findByArticleIdIn(articleIds);
|
||||||
|
// 获取所有分类ID
|
||||||
|
List<Long> categoryIds = articleCategoryRelList.stream()
|
||||||
|
.map(ArticleCategoryRel::getCategoryId)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
// 查询所有分类
|
||||||
|
List<Category> categories = categoryRepository.findAllByIdIn(categoryIds);
|
||||||
|
// 转 Map, 方便后续根据分类 ID 拿到对应的分类名称
|
||||||
|
Map<Long, String> categoryIdNameMap = categories.stream().collect(Collectors.toMap(Category::getId, Category::getName));
|
||||||
|
|
||||||
|
vos.forEach(vo -> {
|
||||||
|
Long currentArticleId = vo.getId();
|
||||||
|
// 过滤出当前文章对应的关联数据
|
||||||
|
Optional<ArticleCategoryRel> optional = articleCategoryRelList.stream()
|
||||||
|
.filter(e -> Objects.equals(e.getArticleId(), currentArticleId))
|
||||||
|
.findAny();
|
||||||
|
// 如果不为空
|
||||||
|
if (optional.isPresent()) {
|
||||||
|
ArticleCategoryRel articleCategoryRel = optional.get();
|
||||||
|
Long categoryId = articleCategoryRel.getCategoryId();
|
||||||
|
// 通过分类 ID 从 map 中拿到对应的分类名称
|
||||||
|
String categoryName = categoryIdNameMap.get(categoryId);
|
||||||
|
FindCategoryListRspVO findCategoryListRspVO = FindCategoryListRspVO.builder()
|
||||||
|
.id(categoryId)
|
||||||
|
.name(categoryName)
|
||||||
|
.build();
|
||||||
|
// 设置到当前 vo 类中
|
||||||
|
vo.setCategory(findCategoryListRspVO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 第三步:设置文章标签
|
||||||
|
// 查询所有标签
|
||||||
|
List<Tag> allTagList = tagRepository.findAll();
|
||||||
|
// 转 Map, 方便后续根据标签 ID 拿到对应的标签名称
|
||||||
|
Map<Long, String> tagIdNameMap = allTagList.stream().collect(Collectors.toMap(Tag::getId, Tag::getName));
|
||||||
|
// 拿到所有文章的标签关联记录
|
||||||
|
List<ArticleTagRel> articleTagRelList = articleTagRelRepository.findByArticleIdIn(articleIds);
|
||||||
|
vos.forEach(vo -> {
|
||||||
|
Long currentArticleId = vo.getId();
|
||||||
|
// 过滤出当前文章对应的关联标签数据
|
||||||
|
List<ArticleTagRel> currentArticleTagRelList = articleTagRelList.stream()
|
||||||
|
.filter(e -> Objects.equals(e.getArticleId(), currentArticleId))
|
||||||
|
.toList();
|
||||||
|
List<FindTagListRspVO> findTagListRspVOS = new ArrayList<>();
|
||||||
|
// 将关联记录 DO 转 VO, 并设置对应的标签名称
|
||||||
|
currentArticleTagRelList.forEach(e -> {
|
||||||
|
Long tagId = e.getTagId();
|
||||||
|
String tagName = tagIdNameMap.get(tagId);
|
||||||
|
FindTagListRspVO findTagListRspVO = FindTagListRspVO.builder()
|
||||||
|
.id(tagId)
|
||||||
|
.name(tagName)
|
||||||
|
.build();
|
||||||
|
findTagListRspVOS.add(findTagListRspVO);
|
||||||
|
});
|
||||||
|
// 设置转换后的标签数据
|
||||||
|
vo.setTags(findTagListRspVOS);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PageResponse<FindIndexArticlePageListRspVO> findIndexArticlePageListRspVOPageResponse = new PageResponse<>();
|
||||||
|
BeanUtils.copyProperties(articlePageResponse, findIndexArticlePageListRspVOPageResponse);
|
||||||
|
findIndexArticlePageListRspVOPageResponse.setData(vos);
|
||||||
|
return findIndexArticlePageListRspVOPageResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArticleContentRepository getArticleContentRepository() {
|
||||||
|
return articleContentRepository;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.hanserwei.web.service.impl;
|
||||||
|
|
||||||
|
import com.hanserwei.common.domain.repository.BlogSettingsRepository;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.blogsetting.FindBlogSettingsDetailRspVO;
|
||||||
|
import com.hanserwei.web.service.BlogSettingsService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class BlogSettingsServiceImpl implements BlogSettingsService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BlogSettingsRepository blogSettingsRepository;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<FindBlogSettingsDetailRspVO> findDetail() {
|
||||||
|
return blogSettingsRepository.findById(1L)
|
||||||
|
.map(e -> {
|
||||||
|
FindBlogSettingsDetailRspVO vo = FindBlogSettingsDetailRspVO.builder()
|
||||||
|
.author(e.getAuthor())
|
||||||
|
.logo(e.getLogo())
|
||||||
|
.name(e.getName())
|
||||||
|
.introduction(e.getIntroduction())
|
||||||
|
.avatar(e.getAvatar())
|
||||||
|
.githubHomepage(e.getGithubHomepage())
|
||||||
|
.csdnHomepage(e.getCsdnHomepage())
|
||||||
|
.giteeHomepage(e.getGiteeHomepage())
|
||||||
|
.zhihuHomepage(e.getZhihuHomepage())
|
||||||
|
.build();
|
||||||
|
return Response.success(vo);
|
||||||
|
})
|
||||||
|
.orElse(Response.success(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.hanserwei.web.service.impl;
|
||||||
|
|
||||||
|
import com.hanserwei.common.domain.dataobject.Category;
|
||||||
|
import com.hanserwei.common.domain.repository.CategoryRepository;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.category.FindCategoryListRspVO;
|
||||||
|
import com.hanserwei.web.service.CategoryService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CategoryServiceImpl implements CategoryService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CategoryRepository categoryRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<List<FindCategoryListRspVO>> findCategoryList() {
|
||||||
|
List<Category> categoryList = categoryRepository.findAll();
|
||||||
|
List<FindCategoryListRspVO> vos = null;
|
||||||
|
if (!CollectionUtils.isEmpty(categoryList)) {
|
||||||
|
vos = categoryList.stream().map(category -> {
|
||||||
|
FindCategoryListRspVO vo = new FindCategoryListRspVO();
|
||||||
|
vo.setId(category.getId());
|
||||||
|
vo.setName(category.getName());
|
||||||
|
return vo;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
return Response.success(vos);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.hanserwei.web.service.impl;
|
||||||
|
|
||||||
|
import com.hanserwei.common.domain.dataobject.Tag;
|
||||||
|
import com.hanserwei.common.domain.repository.TagRepository;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import com.hanserwei.web.model.vo.tag.FindTagListRspVO;
|
||||||
|
import com.hanserwei.web.service.TagService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TagServiceImpl implements TagService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TagRepository tagRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<List<FindTagListRspVO>> findTagList() {
|
||||||
|
List<Tag> tagList = tagRepository.findAll();
|
||||||
|
List<FindTagListRspVO> tagListVO = null;
|
||||||
|
if (!CollectionUtils.isEmpty(tagList)) {
|
||||||
|
tagListVO = tagList.stream().map(tag -> FindTagListRspVO.builder()
|
||||||
|
.id(tag.getId())
|
||||||
|
.name(tag.getName())
|
||||||
|
.build()).toList();
|
||||||
|
}
|
||||||
|
return Response.success(tagListVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user