add:新增知识库功能

This commit is contained in:
zhangzq
2026-01-28 15:19:33 +08:00
parent d75da90e63
commit 42dd6d29f0
28 changed files with 4513 additions and 161 deletions

View File

@@ -0,0 +1,118 @@
-- =============================================
-- 知识库模块数据库表结构
-- 数据库: MySQL 8.0+
-- 字符集: utf8mb4
-- 创建时间: 2026-01-28
-- =============================================
-- 1. 评论表
CREATE TABLE IF NOT EXISTS `comment` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '评论ID',
`knowledge_id` BIGINT NOT NULL COMMENT '知识ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`parent_id` BIGINT DEFAULT 0 COMMENT '父评论ID',
`content` TEXT NOT NULL COMMENT '评论内容',
`like_count` INT DEFAULT 0 COMMENT '点赞数',
`status` TINYINT DEFAULT 1 COMMENT '状态: 0-删除, 1-正常',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_knowledge_id` (`knowledge_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_parent_id` (`parent_id`),
KEY `idx_knowledge_status` (`knowledge_id`, `status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';
-- 2. 知识文档表
CREATE TABLE IF NOT EXISTS `knowledge` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '知识ID',
`title` VARCHAR(255) NOT NULL COMMENT '标题',
`subtitle` VARCHAR(500) COMMENT '副标题',
`content` LONGTEXT NOT NULL COMMENT '内容(HTML格式)',
`plain_content` LONGTEXT COMMENT '纯文本内容(用于搜索)',
`summary` TEXT COMMENT '摘要',
`category_id` BIGINT NOT NULL COMMENT '分类ID',
`author_id` BIGINT NOT NULL COMMENT '作者ID',
`cover_image` VARCHAR(255) COMMENT '封面图',
`view_count` INT DEFAULT 0 COMMENT '浏览量',
`like_count` INT DEFAULT 0 COMMENT '点赞数',
`collect_count` INT DEFAULT 0 COMMENT '收藏数',
`version` INT DEFAULT 1 COMMENT '版本号',
`status` ENUM('DRAFT', 'PUBLISHED', 'REVIEWING', 'ARCHIVED') DEFAULT 'DRAFT' COMMENT '状态',
`publish_time` DATETIME COMMENT '发布时间',
`expire_time` DATETIME COMMENT '过期时间',
`is_top` TINYINT DEFAULT 0 COMMENT '是否置顶',
`tags` VARCHAR(500) COMMENT '标签(逗号分隔)',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_author_id` (`author_id`),
KEY `idx_status` (`status`),
KEY `idx_publish_time` (`publish_time`),
KEY `idx_title` (`title`(191)),
KEY `idx_status_publish_time` (`status`, `publish_time`),
KEY `idx_category_status` (`category_id`, `status`),
FULLTEXT KEY `ft_content` (`plain_content`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识文档表';
-- 3. 用户点赞记录表(可选,用于防止重复点赞)
CREATE TABLE IF NOT EXISTS `knowledge_like_record` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '记录ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`knowledge_id` BIGINT NOT NULL COMMENT '知识ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '点赞时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_knowledge` (`user_id`, `knowledge_id`),
KEY `idx_knowledge_id` (`knowledge_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识点赞记录表';
-- 4. 评论点赞记录表(可选,用于防止重复点赞)
CREATE TABLE IF NOT EXISTS `comment_like_record` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '记录ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`comment_id` BIGINT NOT NULL COMMENT '评论ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '点赞时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_comment` (`user_id`, `comment_id`),
KEY `idx_comment_id` (`comment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论点赞记录表';
-- 5. 知识分类表(可选)
CREATE TABLE IF NOT EXISTS `knowledge_category` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '分类ID',
`parent_id` BIGINT DEFAULT 0 COMMENT '父分类ID',
`name` VARCHAR(100) NOT NULL COMMENT '分类名称',
`description` VARCHAR(500) COMMENT '分类描述',
`sort` INT DEFAULT 0 COMMENT '排序',
`status` TINYINT DEFAULT 1 COMMENT '状态: 0-禁用, 1-启用',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识分类表';
-- 插入测试数据(可选)
-- 知识分类测试数据
INSERT INTO `knowledge_category` (`id`, `parent_id`, `name`, `description`, `sort`, `status`) VALUES
(1, 0, '技术文档', '技术相关文档', 1, 1),
(2, 0, '产品手册', '产品使用手册', 2, 1),
(3, 0, '常见问题', '常见问题解答', 3, 1),
(4, 1, 'Java开发', 'Java开发相关', 1, 1),
(5, 1, '前端开发', '前端开发相关', 2, 1);
-- 知识文档测试数据(需要先有用户数据)
-- INSERT INTO `knowledge` (`title`, `subtitle`, `content`, `plain_content`, `summary`, `category_id`, `author_id`, `status`) VALUES
-- ('Spring Boot入门教程', '快速上手Spring Boot', '<h1>Spring Boot入门</h1><p>这是一篇Spring Boot入门教程...</p>', 'Spring Boot入门 这是一篇Spring Boot入门教程...', '本文介绍Spring Boot的基本使用', 4, 1, 'PUBLISHED');
-- 查询语句示例
-- 查询已发布的知识文档
-- SELECT * FROM knowledge WHERE status = 'PUBLISHED' ORDER BY publish_time DESC LIMIT 10;
-- 查询某个知识的所有评论
-- SELECT c.*, u.username FROM comment c LEFT JOIN sys_user u ON c.user_id = u.user_id WHERE c.knowledge_id = 1 AND c.status = 1 ORDER BY c.create_time DESC;
-- 查询热门知识(按点赞数排序)
-- SELECT * FROM knowledge WHERE status = 'PUBLISHED' ORDER BY like_count DESC LIMIT 10;
-- 查询最新知识
-- SELECT * FROM knowledge WHERE status = 'PUBLISHED' ORDER BY publish_time DESC LIMIT 10;

View File

@@ -0,0 +1,258 @@
# 知识库模块 API 文档
## 模块说明
本模块实现了知识库管理功能,包括知识文档的增删改查、点赞、评论等功能。
## 数据库表结构
### 1. knowledge知识文档表
- 存储知识文档的详细信息
- 支持草稿、已发布、审核中、已归档等状态
- 支持标签、分类、置顶等功能
### 2. comment评论表
- 存储用户对知识文档的评论
- 支持多级评论通过parent_id实现
- 支持评论点赞
## 项目结构
```
com.boge.modules.knowledge/
├── controller/
│ ├── KnowledgeController.java # 知识文档控制器
│ └── CommentController.java # 评论控制器
├── service/
│ ├── KnowledgeService.java # 知识文档服务接口
│ ├── CommentService.java # 评论服务接口
│ └── impl/
│ ├── KnowledgeServiceImpl.java # 知识文档服务实现
│ └── CommentServiceImpl.java # 评论服务实现
├── dao/
│ ├── KnowledgeMapper.java # 知识文档Mapper
│ └── CommentMapper.java # 评论Mapper
├── entity/
│ ├── KnowledgeEntity.java # 知识文档实体
│ └── CommentEntity.java # 评论实体
└── dto/
├── KnowledgeDTO.java # 知识文档请求DTO
├── KnowledgeVO.java # 知识文档响应VO
├── KnowledgeQueryDTO.java # 知识文档查询DTO
├── CommentDTO.java # 评论请求DTO
└── CommentVO.java # 评论响应VO
```
## API 接口说明
### 知识文档接口
#### 1. 分页查询知识文档列表
- **接口地址**: `POST /knowledge/list`
- **请求参数**:
```json
{
"page": 1,
"limit": 10,
"title": "关键字",
"categoryId": 1,
"authorId": 1,
"status": "PUBLISHED",
"tag": "标签",
"isTop": 0,
"orderBy": "create_time",
"order": "desc"
}
```
- **响应示例**:
```json
{
"code": 200,
"msg": "success",
"page": {
"totalCount": 100,
"pageSize": 10,
"totalPage": 10,
"currPage": 1,
"list": [...]
}
}
```
#### 2. 查询知识文档详情
- **接口地址**: `GET /knowledge/info/{id}`
- **说明**: 查询时会自动增加浏览量
#### 3. 保存知识文档
- **接口地址**: `POST /knowledge/save`
- **请求参数**:
```json
{
"title": "标题",
"subtitle": "副标题",
"content": "HTML内容",
"plainContent": "纯文本内容",
"summary": "摘要",
"categoryId": 1,
"coverImage": "封面图URL",
"status": "DRAFT",
"tags": "标签1,标签2"
}
```
#### 4. 更新知识文档
- **接口地址**: `PUT /knowledge/update`
- **说明**: 只有作者本人可以更新
#### 5. 删除知识文档
- **接口地址**: `DELETE /knowledge/delete/{id}`
- **说明**: 软删除将状态改为ARCHIVED
#### 6. 点赞知识文档
- **接口地址**: `POST /knowledge/like/{id}`
#### 7. 取消点赞知识文档
- **接口地址**: `POST /knowledge/unlike/{id}`
#### 8. 发布知识文档
- **接口地址**: `POST /knowledge/publish/{id}`
- **说明**: 将草稿状态改为已发布
### 评论接口
#### 1. 分页查询评论列表
- **接口地址**: `GET /knowledge/comment/list`
- **请求参数**:
- knowledgeId: 知识ID
- parentId: 父评论ID可选
- page: 页码
- limit: 每页条数
#### 2. 根据知识ID查询评论列表
- **接口地址**: `GET /knowledge/comment/listByKnowledge/{knowledgeId}`
- **请求参数**:
- page: 页码默认1
- limit: 每页条数默认10
#### 3. 添加评论
- **接口地址**: `POST /knowledge/comment/add`
- **请求参数**:
```json
{
"knowledgeId": 1,
"parentId": 0,
"content": "评论内容"
}
```
#### 4. 删除评论
- **接口地址**: `DELETE /knowledge/comment/delete/{id}`
- **说明**: 只有评论作者可以删除
#### 5. 点赞评论
- **接口地址**: `POST /knowledge/comment/like/{id}`
#### 6. 取消点赞评论
- **接口地址**: `POST /knowledge/comment/unlike/{id}`
#### 7. 查询评论详情
- **接口地址**: `GET /knowledge/comment/info/{id}`
## 功能特性
### 已实现功能
1. ✅ 知识库列表查询(支持多条件筛选、排序)
2. ✅ 文档详情查询(自动增加浏览量)
3. ✅ 文档点赞/取消点赞
4. ✅ 文档评论功能
5. ✅ 评论点赞/取消点赞
6. ✅ 多级评论支持
7. ✅ 权限控制(只有作者可以修改/删除自己的内容)
### 待扩展功能
1. 🔲 用户点赞记录表(防止重复点赞)
2. 🔲 文档收藏功能
3. 🔲 全文搜索功能基于plain_content字段
4. 🔲 文档版本管理
5. 🔲 评论审核功能
6. 🔲 文档分类管理
## 注意事项
1. **权限控制**: 所有接口都需要用户登录通过Shiro获取当前用户信息
2. **软删除**: 删除操作采用软删除方式,不会真正删除数据
3. **点赞功能**: 当前实现较简单,建议后续添加用户点赞记录表防止重复点赞
4. **事务管理**: 所有写操作都添加了事务注解,确保数据一致性
5. **浏览量**: 每次查询详情会自动增加浏览量如需防止刷量可添加IP限制
## 使用示例
### 前端调用示例Vue.js
```javascript
// 查询知识列表
this.$http({
url: '/knowledge/list',
method: 'post',
data: {
page: 1,
limit: 10,
status: 'PUBLISHED'
}
}).then(({data}) => {
if(data && data.code === 200){
this.dataList = data.page.list
this.totalPage = data.page.totalCount
}
})
// 点赞文档
this.$http({
url: `/knowledge/like/${id}`,
method: 'post'
}).then(({data}) => {
if(data && data.code === 200){
this.$message.success('点赞成功')
}
})
// 添加评论
this.$http({
url: '/knowledge/comment/add',
method: 'post',
data: {
knowledgeId: this.knowledgeId,
parentId: 0,
content: this.commentContent
}
}).then(({data}) => {
if(data && data.code === 200){
this.$message.success('评论成功')
this.getComments()
}
})
```
## 数据库索引优化建议
已在表结构中添加的索引:
- knowledge表: category_id, author_id, status, publish_time, title
- comment表: knowledge_id, user_id, parent_id
建议添加的复合索引:
```sql
-- 知识表复合索引
ALTER TABLE knowledge ADD INDEX idx_status_publish_time (status, publish_time);
ALTER TABLE knowledge ADD INDEX idx_category_status (category_id, status);
-- 评论表复合索引
ALTER TABLE comment ADD INDEX idx_knowledge_status (knowledge_id, status);
```
## 版本历史
- v1.0.0 (2026-01-28)
- 初始版本
- 实现知识文档基本CRUD
- 实现评论功能
- 实现点赞功能

View File

@@ -0,0 +1,105 @@
package com.boge.modules.knowledge.controller;
import com.boge.common.utils.PageUtils;
import com.boge.common.utils.R;
import com.boge.modules.knowledge.service.dto.CommentDTO;
import com.boge.modules.knowledge.service.CommentService;
import com.boge.modules.sys.controller.AbstractController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Map;
/**
* 评论Controller
*
* @author boge
*/
@RestController
@RequestMapping("/knowledge/comment")
@Api(tags = "知识库-评论管理")
public class CommentController extends AbstractController {
@Autowired
private CommentService commentService;
/**
* 分页查询评论列表
*/
@GetMapping("/list")
@ApiOperation("分页查询评论列表")
public R list(@RequestParam Map<String, Object> params) {
PageUtils page = commentService.queryPage(params);
return R.ok().put("page", page);
}
/**
* 根据知识ID查询评论列表
*/
@GetMapping("/listByKnowledge/{knowledgeId}")
@ApiOperation("根据知识ID查询评论列表")
public R listByKnowledge(
@ApiParam("知识ID") @PathVariable("knowledgeId") Long knowledgeId,
@ApiParam("页码") @RequestParam(value = "page", defaultValue = "1") Integer page,
@ApiParam("每页条数") @RequestParam(value = "limit", defaultValue = "10") Integer limit) {
PageUtils pageResult = commentService.getCommentsByKnowledgeId(knowledgeId, page, limit);
return R.ok().put("page", pageResult);
}
/**
* 添加评论
*/
@PostMapping("/add")
@ApiOperation("添加评论")
public R add(@Valid @RequestBody CommentDTO commentDTO) {
Long userId = getUserId();
Long commentId = commentService.addComment(commentDTO, userId);
return R.ok().put("commentId", commentId);
}
/**
* 删除评论
*/
@DeleteMapping("/delete/{id}")
@ApiOperation("删除评论")
public R delete(@ApiParam("评论ID") @PathVariable("id") Long id) {
Long userId = getUserId();
commentService.deleteComment(id, userId);
return R.ok();
}
/**
* 点赞评论
*/
@PostMapping("/like/{id}")
@ApiOperation("点赞评论")
public R like(@ApiParam("评论ID") @PathVariable("id") Long id) {
Long userId = getUserId();
commentService.likeComment(id, userId);
return R.ok();
}
/**
* 取消点赞评论
*/
@PostMapping("/unlike/{id}")
@ApiOperation("取消点赞评论")
public R unlike(@ApiParam("评论ID") @PathVariable("id") Long id) {
Long userId = getUserId();
commentService.unlikeComment(id, userId);
return R.ok();
}
/**
* 查询评论详情
*/
@GetMapping("/info/{id}")
@ApiOperation("查询评论详情")
public R info(@ApiParam("评论ID") @PathVariable("id") Long id) {
return R.ok().put("comment", commentService.getById(id));
}
}

View File

@@ -0,0 +1,127 @@
package com.boge.modules.knowledge.controller;
import com.boge.common.utils.PageUtils;
import com.boge.common.utils.R;
import com.boge.modules.knowledge.service.dto.KnowledgeDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeQueryDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeVO;
import com.boge.modules.knowledge.service.KnowledgeService;
import com.boge.modules.sys.controller.AbstractController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 知识文档Controller
*
* @author boge
*/
@RestController
@RequestMapping("/knowledge")
@Api(tags = "知识库-文档管理")
public class KnowledgeController extends AbstractController {
@Autowired
private KnowledgeService knowledgeService;
/**
* 分页查询知识文档列表
*/
@PostMapping("/list")
@ApiOperation("分页查询知识文档列表")
public R list(@RequestBody KnowledgeQueryDTO query) {
PageUtils page = knowledgeService.queryPage(query);
return R.ok().put("page", page);
}
/**
* 查询知识文档详情
*/
@GetMapping("/info/{id}")
@ApiOperation("查询知识文档详情")
public R info(@ApiParam("知识ID") @PathVariable("id") Long id) {
KnowledgeVO knowledge = knowledgeService.getKnowledgeDetail(id);
return R.ok().put("knowledge", knowledge);
}
/**
* 保存知识文档
*/
@PostMapping("/save")
@ApiOperation("保存知识文档")
public R save(@Valid @RequestBody KnowledgeDTO knowledgeDTO) {
Long userId = getUserId();
Long knowledgeId = knowledgeService.saveKnowledge(knowledgeDTO, userId);
return R.ok().put("knowledgeId", knowledgeId);
}
/**
* 更新知识文档
*/
@PutMapping("/update")
@ApiOperation("更新知识文档")
public R update(@Valid @RequestBody KnowledgeDTO knowledgeDTO) {
Long userId = getUserId();
knowledgeService.updateKnowledge(knowledgeDTO, userId);
return R.ok();
}
/**
* 删除知识文档
*/
@DeleteMapping("/delete/{id}")
@ApiOperation("删除知识文档")
public R delete(@ApiParam("知识ID") @PathVariable("id") Long id) {
Long userId = getUserId();
knowledgeService.deleteKnowledge(id, userId);
return R.ok();
}
/**
* 点赞知识文档
*/
@PostMapping("/like/{id}")
@ApiOperation("点赞知识文档")
public R like(@ApiParam("知识ID") @PathVariable("id") Long id) {
Long userId = getUserId();
knowledgeService.likeKnowledge(id, userId);
return R.ok();
}
/**
* 取消点赞知识文档
*/
@PostMapping("/unlike/{id}")
@ApiOperation("取消点赞知识文档")
public R unlike(@ApiParam("知识ID") @PathVariable("id") Long id) {
Long userId = getUserId();
knowledgeService.unlikeKnowledge(id, userId);
return R.ok();
}
/**
* 发布知识文档
*/
@PostMapping("/publish/{id}")
@ApiOperation("发布知识文档")
public R publish(@ApiParam("知识ID") @PathVariable("id") Long id) {
Long userId = getUserId();
knowledgeService.publishKnowledge(id, userId);
return R.ok();
}
/**
* 下架知识文档
*/
@PostMapping("/unpublish/{id}")
@ApiOperation("下架知识文档")
public R unpublish(@ApiParam("知识ID") @PathVariable("id") Long id) {
Long userId = getUserId();
knowledgeService.unpublishKnowledge(id, userId);
return R.ok();
}
}

View File

@@ -0,0 +1,67 @@
package com.boge.modules.knowledge.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.boge.common.utils.PageUtils;
import com.boge.modules.knowledge.service.dto.CommentDTO;
import com.boge.modules.knowledge.service.entity.CommentEntity;
import java.util.Map;
/**
* 评论Service
*
* @author boge
*/
public interface CommentService extends IService<CommentEntity> {
/**
* 分页查询评论列表
*
* @param params 查询参数
* @return 分页结果
*/
PageUtils queryPage(Map<String, Object> params);
/**
* 添加评论
*
* @param commentDTO 评论信息
* @param userId 用户ID
* @return 评论ID
*/
Long addComment(CommentDTO commentDTO, Long userId);
/**
* 删除评论
*
* @param id 评论ID
* @param userId 用户ID
*/
void deleteComment(Long id, Long userId);
/**
* 点赞评论
*
* @param id 评论ID
* @param userId 用户ID
*/
void likeComment(Long id, Long userId);
/**
* 取消点赞评论
*
* @param id 评论ID
* @param userId 用户ID
*/
void unlikeComment(Long id, Long userId);
/**
* 根据知识ID查询评论列表
*
* @param knowledgeId 知识ID
* @param page 页码
* @param limit 每页条数
* @return 评论列表
*/
PageUtils getCommentsByKnowledgeId(Long knowledgeId, Integer page, Integer limit);
}

View File

@@ -0,0 +1,89 @@
package com.boge.modules.knowledge.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.boge.common.utils.PageUtils;
import com.boge.modules.knowledge.service.dto.KnowledgeDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeQueryDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeVO;
import com.boge.modules.knowledge.service.entity.KnowledgeEntity;
/**
* 知识文档Service
*
* @author boge
*/
public interface KnowledgeService extends IService<KnowledgeEntity> {
/**
* 分页查询知识文档列表
*
* @param query 查询参数
* @return 分页结果
*/
PageUtils queryPage(KnowledgeQueryDTO query);
/**
* 根据ID查询知识文档详情
*
* @param id 知识ID
* @return 知识文档详情
*/
KnowledgeVO getKnowledgeDetail(Long id);
/**
* 保存知识文档
*
* @param knowledgeDTO 知识文档信息
* @param userId 用户ID
* @return 知识ID
*/
Long saveKnowledge(KnowledgeDTO knowledgeDTO, Long userId);
/**
* 更新知识文档
*
* @param knowledgeDTO 知识文档信息
* @param userId 用户ID
*/
void updateKnowledge(KnowledgeDTO knowledgeDTO, Long userId);
/**
* 删除知识文档
*
* @param id 知识ID
* @param userId 用户ID
*/
void deleteKnowledge(Long id, Long userId);
/**
* 点赞知识文档
*
* @param id 知识ID
* @param userId 用户ID
*/
void likeKnowledge(Long id, Long userId);
/**
* 取消点赞知识文档
*
* @param id 知识ID
* @param userId 用户ID
*/
void unlikeKnowledge(Long id, Long userId);
/**
* 发布知识文档
*
* @param id 知识ID
* @param userId 用户ID
*/
void publishKnowledge(Long id, Long userId);
/**
* 下架知识文档
*
* @param id 知识ID
* @param userId 用户ID
*/
void unpublishKnowledge(Long id, Long userId);
}

View File

@@ -0,0 +1,44 @@
package com.boge.modules.knowledge.service.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boge.modules.knowledge.service.dto.CommentVO;
import com.boge.modules.knowledge.service.entity.CommentEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 评论Mapper
*
* @author boge
*/
@Mapper
public interface CommentMapper extends BaseMapper<CommentEntity> {
/**
* 分页查询评论列表
*
* @param page 分页对象
* @param knowledgeId 知识ID
* @param parentId 父评论ID
* @return 评论列表
*/
IPage<CommentVO> queryPage(Page<CommentVO> page,
@Param("knowledgeId") Long knowledgeId,
@Param("parentId") Long parentId);
/**
* 增加评论点赞数
*
* @param id 评论ID
*/
void increaseLikeCount(@Param("id") Long id);
/**
* 减少评论点赞数
*
* @param id 评论ID
*/
void decreaseLikeCount(@Param("id") Long id);
}

View File

@@ -0,0 +1,57 @@
package com.boge.modules.knowledge.service.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boge.modules.knowledge.service.dto.KnowledgeQueryDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeVO;
import com.boge.modules.knowledge.service.entity.KnowledgeEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 知识文档Mapper
*
* @author boge
*/
@Mapper
public interface KnowledgeMapper extends BaseMapper<KnowledgeEntity> {
/**
* 分页查询知识文档列表
*
* @param page 分页对象
* @param query 查询参数
* @return 知识文档列表
*/
IPage<KnowledgeVO> queryPage(Page<KnowledgeVO> page, @Param("query") KnowledgeQueryDTO query);
/**
* 根据ID查询知识文档详情
*
* @param id 知识ID
* @return 知识文档详情
*/
KnowledgeVO getKnowledgeDetail(@Param("id") Long id);
/**
* 增加浏览量
*
* @param id 知识ID
*/
void increaseViewCount(@Param("id") Long id);
/**
* 增加点赞数
*
* @param id 知识ID
*/
void increaseLikeCount(@Param("id") Long id);
/**
* 减少点赞数
*
* @param id 知识ID
*/
void decreaseLikeCount(@Param("id") Long id);
}

View File

@@ -0,0 +1,39 @@
package com.boge.modules.knowledge.service.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 评论请求DTO
*
* @author boge
*/
@Data
public class CommentDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 评论ID
*/
private Long id;
/**
* 知识ID
*/
@NotNull(message = "知识ID不能为空")
private Long knowledgeId;
/**
* 父评论ID (0表示顶级评论)
*/
private Long parentId;
/**
* 评论内容
*/
@NotBlank(message = "评论内容不能为空")
private String content;
}

View File

@@ -0,0 +1,73 @@
package com.boge.modules.knowledge.service.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 评论响应VO
*
* @author boge
*/
@Data
public class CommentVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 评论ID
*/
private Long id;
/**
* 知识ID
*/
private Long knowledgeId;
/**
* 用户ID
*/
private Long userId;
/**
* 用户名
*/
private String username;
/**
* 用户昵称
*/
private String nickname;
/**
* 用户头像
*/
private String userAvatar;
/**
* 父评论ID
*/
private Long parentId;
/**
* 评论内容
*/
private String content;
/**
* 点赞数
*/
private Integer likeCount;
/**
* 状态: 0-删除, 1-正常
*/
private Integer status;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}

View File

@@ -0,0 +1,85 @@
package com.boge.modules.knowledge.service.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
/**
* 知识文档请求DTO
*
* @author boge
*/
@Data
public class KnowledgeDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 知识ID
*/
private Long id;
/**
* 标题
*/
@NotBlank(message = "标题不能为空")
private String title;
/**
* 副标题
*/
private String subtitle;
/**
* 内容(HTML格式)
*/
@NotBlank(message = "内容不能为空")
private String content;
/**
* 纯文本内容(用于搜索)
*/
private String plainContent;
/**
* 摘要
*/
private String summary;
/**
* 分类ID
*/
private Long categoryId;
/**
* 封面图
*/
private String coverImage;
/**
* 状态: DRAFT-草稿, PUBLISHED-已发布, REVIEWING-审核中, ARCHIVED-已归档
*/
private String status;
/**
* 发布时间
*/
private Date publishTime;
/**
* 过期时间
*/
private Date expireTime;
/**
* 是否置顶: 0-否, 1-是
*/
private Integer isTop;
/**
* 标签(逗号分隔)
*/
private String tags;
}

View File

@@ -0,0 +1,65 @@
package com.boge.modules.knowledge.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 知识文档查询参数
*
* @author boge
*/
@Data
public class KnowledgeQueryDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 当前页码
*/
private Integer page = 1;
/**
* 每页条数
*/
private Integer limit = 10;
/**
* 标题关键字
*/
private String title;
/**
* 分类ID
*/
private Long categoryId;
/**
* 作者ID
*/
private Long authorId;
/**
* 状态
*/
private String status;
/**
* 标签
*/
private String tag;
/**
* 是否置顶
*/
private Integer isTop;
/**
* 排序字段 (view_count, like_count, create_time, publish_time)
*/
private String orderBy = "create_time";
/**
* 排序方式 (asc, desc)
*/
private String order = "desc";
}

View File

@@ -0,0 +1,121 @@
package com.boge.modules.knowledge.service.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 知识文档响应VO
*
* @author boge
*/
@Data
public class KnowledgeVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 知识ID
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 副标题
*/
private String subtitle;
/**
* 内容(HTML格式)
*/
private String content;
/**
* 摘要
*/
private String summary;
/**
* 分类ID
*/
private Long categoryId;
/**
* 作者ID
*/
private Long authorId;
/**
* 作者名称
*/
private String authorName;
/**
* 封面图
*/
private String coverImage;
/**
* 浏览量
*/
private Integer viewCount;
/**
* 点赞数
*/
private Integer likeCount;
/**
* 收藏数
*/
private Integer collectCount;
/**
* 版本号
*/
private Integer version;
/**
* 状态: DRAFT-草稿, PUBLISHED-已发布, REVIEWING-审核中, ARCHIVED-已归档
*/
private String status;
/**
* 发布时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date publishTime;
/**
* 过期时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date expireTime;
/**
* 是否置顶: 0-否, 1-是
*/
private Integer isTop;
/**
* 标签(逗号分隔)
*/
private String tags;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@@ -0,0 +1,63 @@
package com.boge.modules.knowledge.service.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 评论实体类
*
* @author boge
*/
@Data
@TableName("comment")
public class CommentEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 评论ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 知识ID
*/
private Long knowledgeId;
/**
* 用户ID
*/
private Long userId;
/**
* 父评论ID
*/
private Long parentId;
/**
* 评论内容
*/
private String content;
/**
* 点赞数
*/
private Integer likeCount;
/**
* 状态: 0-删除, 1-正常
*/
private Integer status;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}

View File

@@ -0,0 +1,126 @@
package com.boge.modules.knowledge.service.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 知识文档实体类
*
* @author boge
*/
@Data
@TableName("knowledge")
public class KnowledgeEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 知识ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 标题
*/
private String title;
/**
* 副标题
*/
private String subtitle;
/**
* 内容(HTML格式)
*/
private String content;
/**
* 纯文本内容(用于搜索)
*/
private String plainContent;
/**
* 摘要
*/
private String summary;
/**
* 分类ID
*/
private Long categoryId;
/**
* 作者ID
*/
private Long authorId;
/**
* 封面图
*/
private String coverImage;
/**
* 浏览量
*/
private Integer viewCount;
/**
* 点赞数
*/
private Integer likeCount;
/**
* 收藏数
*/
private Integer collectCount;
/**
* 版本号
*/
private Integer version;
/**
* 状态: DRAFT-草稿, PUBLISHED-已发布, REVIEWING-审核中, ARCHIVED-已归档
*/
private String status;
/**
* 发布时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date publishTime;
/**
* 过期时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date expireTime;
/**
* 是否置顶: 0-否, 1-是
*/
private Integer isTop;
/**
* 标签(逗号分隔)
*/
private String tags;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@@ -0,0 +1,108 @@
package com.boge.modules.knowledge.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.boge.common.exception.RRException;
import com.boge.common.utils.PageUtils;
import com.boge.modules.knowledge.service.dao.CommentMapper;
import com.boge.modules.knowledge.service.dto.CommentDTO;
import com.boge.modules.knowledge.service.dto.CommentVO;
import com.boge.modules.knowledge.service.entity.CommentEntity;
import com.boge.modules.knowledge.service.CommentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.Map;
/**
* 评论Service实现类
*
* @author boge
*/
@Service("commentService")
public class CommentServiceImpl extends ServiceImpl<CommentMapper, CommentEntity> implements CommentService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
Long knowledgeId = params.get("knowledgeId") != null ? Long.parseLong(params.get("knowledgeId").toString()) : null;
Long parentId = params.get("parentId") != null ? Long.parseLong(params.get("parentId").toString()) : 0L;
Integer page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
Integer limit = params.get("limit") != null ? Integer.parseInt(params.get("limit").toString()) : 10;
Page<CommentVO> pageParam = new Page<>(page, limit);
IPage<CommentVO> pageResult = baseMapper.queryPage(pageParam, knowledgeId, parentId);
return new PageUtils(pageResult);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long addComment(CommentDTO commentDTO, Long userId) {
CommentEntity comment = new CommentEntity();
comment.setKnowledgeId(commentDTO.getKnowledgeId());
comment.setUserId(userId);
comment.setParentId(commentDTO.getParentId() != null ? commentDTO.getParentId() : 0L);
comment.setContent(commentDTO.getContent());
comment.setLikeCount(0);
comment.setStatus(1);
comment.setCreateTime(new Date());
this.save(comment);
return comment.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteComment(Long id, Long userId) {
CommentEntity comment = this.getById(id);
if (comment == null) {
throw new RRException("评论不存在");
}
// 只有评论作者才能删除
if (!comment.getUserId().equals(userId)) {
throw new RRException("无权删除该评论");
}
// 软删除
comment.setStatus(0);
this.updateById(comment);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void likeComment(Long id, Long userId) {
CommentEntity comment = this.getById(id);
if (comment == null) {
throw new RRException("评论不存在");
}
// TODO: 可以添加用户点赞记录表,防止重复点赞
baseMapper.increaseLikeCount(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void unlikeComment(Long id, Long userId) {
CommentEntity comment = this.getById(id);
if (comment == null) {
throw new RRException("评论不存在");
}
// TODO: 可以添加用户点赞记录表,防止重复取消点赞
baseMapper.decreaseLikeCount(id);
}
@Override
public PageUtils getCommentsByKnowledgeId(Long knowledgeId, Integer page, Integer limit) {
page = page != null ? page : 1;
limit = limit != null ? limit : 10;
Page<CommentVO> pageParam = new Page<>(page, limit);
IPage<CommentVO> pageResult = baseMapper.queryPage(pageParam, knowledgeId, 0L);
return new PageUtils(pageResult);
}
}

View File

@@ -0,0 +1,166 @@
package com.boge.modules.knowledge.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.boge.common.exception.RRException;
import com.boge.common.utils.PageUtils;
import com.boge.modules.knowledge.service.dao.KnowledgeMapper;
import com.boge.modules.knowledge.service.dto.KnowledgeDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeQueryDTO;
import com.boge.modules.knowledge.service.dto.KnowledgeVO;
import com.boge.modules.knowledge.service.entity.KnowledgeEntity;
import com.boge.modules.knowledge.service.KnowledgeService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
* 知识文档Service实现类
*
* @author boge
*/
@Service("knowledgeService")
public class KnowledgeServiceImpl extends ServiceImpl<KnowledgeMapper, KnowledgeEntity> implements KnowledgeService {
@Override
public PageUtils queryPage(KnowledgeQueryDTO query) {
Page<KnowledgeVO> page = new Page<>(query.getPage(), query.getLimit());
IPage<KnowledgeVO> pageResult = baseMapper.queryPage(page, query);
return new PageUtils(pageResult);
}
@Override
public KnowledgeVO getKnowledgeDetail(Long id) {
// 增加浏览量
baseMapper.increaseViewCount(id);
// 查询详情
return baseMapper.getKnowledgeDetail(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long saveKnowledge(KnowledgeDTO knowledgeDTO, Long userId) {
KnowledgeEntity knowledge = new KnowledgeEntity();
BeanUtils.copyProperties(knowledgeDTO, knowledge);
knowledge.setAuthorId(userId);
knowledge.setViewCount(0);
knowledge.setLikeCount(0);
knowledge.setCollectCount(0);
knowledge.setVersion(1);
knowledge.setIsTop(0);
knowledge.setCreateTime(new Date());
knowledge.setUpdateTime(new Date());
// 如果状态为空,默认为草稿
if (knowledge.getStatus() == null || knowledge.getStatus().isEmpty()) {
knowledge.setStatus("DRAFT");
}
this.save(knowledge);
return knowledge.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateKnowledge(KnowledgeDTO knowledgeDTO, Long userId) {
KnowledgeEntity knowledge = this.getById(knowledgeDTO.getId());
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// 只有作者才能修改
if (!knowledge.getAuthorId().equals(userId)) {
throw new RRException("无权修改该知识文档");
}
BeanUtils.copyProperties(knowledgeDTO, knowledge, "id", "authorId", "viewCount",
"likeCount", "collectCount", "version", "createTime");
knowledge.setUpdateTime(new Date());
this.updateById(knowledge);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteKnowledge(Long id, Long userId) {
KnowledgeEntity knowledge = this.getById(id);
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// 只有作者才能删除
if (!knowledge.getAuthorId().equals(userId)) {
throw new RRException("无权删除该知识文档");
}
// 归档而不是物理删除
knowledge.setStatus("ARCHIVED");
knowledge.setUpdateTime(new Date());
this.updateById(knowledge);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void likeKnowledge(Long id, Long userId) {
KnowledgeEntity knowledge = this.getById(id);
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// TODO: 可以添加用户点赞记录表,防止重复点赞
baseMapper.increaseLikeCount(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void unlikeKnowledge(Long id, Long userId) {
KnowledgeEntity knowledge = this.getById(id);
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// TODO: 可以添加用户点赞记录表,防止重复取消点赞
baseMapper.decreaseLikeCount(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void publishKnowledge(Long id, Long userId) {
KnowledgeEntity knowledge = this.getById(id);
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// 只有作者才能发布
if (!knowledge.getAuthorId().equals(userId)) {
throw new RRException("无权发布该知识文档");
}
knowledge.setStatus("PUBLISHED");
knowledge.setPublishTime(new Date());
knowledge.setUpdateTime(new Date());
this.updateById(knowledge);
}
@Override
public void unpublishKnowledge(Long id, Long userId) {
KnowledgeEntity knowledge = this.getById(id);
if (knowledge == null) {
throw new RRException("知识文档不存在");
}
// 只有作者才能发布
if (!knowledge.getAuthorId().equals(userId)) {
throw new RRException("无权发布该知识文档");
}
knowledge.setStatus("DRAFT");
knowledge.setUpdateTime(new Date());
this.updateById(knowledge);
}
}

View File

@@ -0,0 +1,82 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.boge.modules.sys;
import com.boge.common.exception.RRException;
import com.boge.common.utils.FileUtil;
import com.boge.modules.tickets.entity.LocalStorage;
import com.boge.modules.tickets.service.LocalStorageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RestController
@Api(
tags = {"工具:本地存储管理"}
)
@RequestMapping({"/api/localStorage"})
public class LocalStorageController {
private final LocalStorageService localStorageService;
@ApiOperation("查询文件")
@GetMapping
public ResponseEntity<Object> query(@RequestParam String annex) {
List<LocalStorage> list = new ArrayList<>();
if (StringUtils.isNotEmpty(annex)){
String[] split = annex.split(",");
list = localStorageService.listByIds(Arrays.asList(split));
}
return new ResponseEntity(list, HttpStatus.OK);
}
@ApiOperation("导出数据")
@GetMapping({"/download"})
public void download(@RequestParam Long storageId , HttpServletResponse response, HttpServletRequest request) throws IOException {
this.localStorageService.downloadFile(this.localStorageService.getById(storageId),request, response);
}
@ApiOperation("上传文件")
@PostMapping
public ResponseEntity<Object> create(@RequestParam String name, @RequestParam("file") MultipartFile file) {
LocalStorage localStorage = this.localStorageService.create(name, file);
return new ResponseEntity(localStorage, HttpStatus.CREATED);
}
@PostMapping({"/pictures"})
@ApiOperation("上传图片")
public ResponseEntity<Object> upload(@RequestParam MultipartFile file) {
String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
if (!"图片".equals(FileUtil.getFileType(suffix))) {
throw new RRException("只能上传图片");
} else {
LocalStorage localStorage = this.localStorageService.create((String)null, file);
return new ResponseEntity(localStorage, HttpStatus.OK);
}
}
@DeleteMapping
@ApiOperation("多选删除")
public ResponseEntity<Object> delete(@RequestBody Long[] ids) {
localStorageService.removeByIds(Arrays.asList(ids));
return new ResponseEntity(HttpStatus.OK);
}
public LocalStorageController(final LocalStorageService localStorageService) {
this.localStorageService = localStorageService;
}
}

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.boge.modules.knowledge.service.dao.CommentMapper">
<!-- 评论VO结果映射 -->
<resultMap id="commentVOMap" type="com.boge.modules.knowledge.service.dto.CommentVO">
<id column="id" property="id"/>
<result column="knowledge_id" property="knowledgeId"/>
<result column="user_id" property="userId"/>
<result column="username" property="username"/>
<result column="nickname" property="nickname"/>
<result column="user_avatar" property="userAvatar"/>
<result column="parent_id" property="parentId"/>
<result column="content" property="content"/>
<result column="like_count" property="likeCount"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 分页查询评论列表 -->
<select id="queryPage" resultMap="commentVOMap">
SELECT
c.id,
c.knowledge_id,
c.user_id,
u.username,
u.nickname,
u.img AS user_avatar,
c.parent_id,
c.content,
c.like_count,
c.status,
c.create_time
FROM comment c
LEFT JOIN sys_user u ON c.user_id = u.user_id
<where>
c.status = 1
<if test="knowledgeId != null">
AND c.knowledge_id = #{knowledgeId}
</if>
<if test="parentId != null">
AND c.parent_id = #{parentId}
</if>
</where>
ORDER BY c.create_time DESC
</select>
<!-- 增加评论点赞数 -->
<update id="increaseLikeCount">
UPDATE comment
SET like_count = like_count + 1
WHERE id = #{id}
</update>
<!-- 减少评论点赞数 -->
<update id="decreaseLikeCount">
UPDATE comment
SET like_count = CASE WHEN like_count > 0 THEN like_count - 1 ELSE 0 END
WHERE id = #{id}
</update>
</mapper>

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.boge.modules.knowledge.service.dao.KnowledgeMapper">
<!-- 知识文档VO结果映射 -->
<resultMap id="knowledgeVOMap" type="com.boge.modules.knowledge.service.dto.KnowledgeVO">
<id column="id" property="id"/>
<result column="title" property="title"/>
<result column="subtitle" property="subtitle"/>
<result column="content" property="content"/>
<result column="summary" property="summary"/>
<result column="category_id" property="categoryId"/>
<result column="author_id" property="authorId"/>
<result column="author_name" property="authorName"/>
<result column="cover_image" property="coverImage"/>
<result column="view_count" property="viewCount"/>
<result column="like_count" property="likeCount"/>
<result column="collect_count" property="collectCount"/>
<result column="version" property="version"/>
<result column="status" property="status"/>
<result column="publish_time" property="publishTime"/>
<result column="expire_time" property="expireTime"/>
<result column="is_top" property="isTop"/>
<result column="tags" property="tags"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 分页查询知识文档列表 -->
<select id="queryPage" resultMap="knowledgeVOMap">
SELECT
k.id,
k.title,
k.subtitle,
k.summary,
k.category_id,
k.author_id,
u.username AS author_name,
k.cover_image,
k.view_count,
k.like_count,
k.collect_count,
k.version,
k.status,
k.publish_time,
k.expire_time,
k.is_top,
k.tags,
k.create_time,
k.update_time
FROM knowledge k
LEFT JOIN sys_user u ON k.author_id = u.user_id
<where>
<if test="query.title != null and query.title != ''">
AND k.title LIKE CONCAT('%', #{query.title}, '%')
</if>
<if test="query.categoryId != null">
AND k.category_id = #{query.categoryId}
</if>
<if test="query.authorId != null">
AND k.author_id = #{query.authorId}
</if>
<if test="query.status != null and query.status != ''">
AND k.status = #{query.status}
</if>
<if test="query.tag != null and query.tag != ''">
AND FIND_IN_SET(#{query.tag}, k.tags)
</if>
<if test="query.isTop != null">
AND k.is_top = #{query.isTop}
</if>
</where>
ORDER BY
<choose>
<when test="query.orderBy == 'view_count'">
k.view_count
</when>
<when test="query.orderBy == 'like_count'">
k.like_count
</when>
<when test="query.orderBy == 'publish_time'">
k.publish_time
</when>
<otherwise>
k.create_time
</otherwise>
</choose>
<choose>
<when test="query.order == 'asc'">
ASC
</when>
<otherwise>
DESC
</otherwise>
</choose>
</select>
<!-- 根据ID查询知识文档详情 -->
<select id="getKnowledgeDetail" resultMap="knowledgeVOMap">
SELECT
k.id,
k.title,
k.subtitle,
k.content,
k.plain_content,
k.summary,
k.category_id,
k.author_id,
u.username AS author_name,
k.cover_image,
k.view_count,
k.like_count,
k.collect_count,
k.version,
k.status,
k.publish_time,
k.expire_time,
k.is_top,
k.tags,
k.create_time,
k.update_time
FROM knowledge k
LEFT JOIN sys_user u ON k.author_id = u.user_id
WHERE k.id = #{id}
</select>
<!-- 增加浏览量 -->
<update id="increaseViewCount">
UPDATE knowledge
SET view_count = view_count + 1
WHERE id = #{id}
</update>
<!-- 增加点赞数 -->
<update id="increaseLikeCount">
UPDATE knowledge
SET like_count = like_count + 1
WHERE id = #{id}
</update>
<!-- 减少点赞数 -->
<update id="decreaseLikeCount">
UPDATE knowledge
SET like_count = CASE WHEN like_count > 0 THEN like_count - 1 ELSE 0 END
WHERE id = #{id}
</update>
</mapper>