Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
920 changes: 920 additions & 0 deletions mianshiya-next-backend/sql/article_sample_data.sql

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions mianshiya-next-backend/sql/article_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use mianshiya;
-- 文章表
create table if not exists article
(
id bigint auto_increment comment 'id' primary key,
title varchar(512) not null comment '文章标题',
content longtext not null comment '文章内容',
summary text null comment '文章摘要',
cover varchar(1024) null comment '封面图片',
tags varchar(1024) null comment '标签列表(json 数组)',
category varchar(256) null comment '文章分类',
status int default 0 not null comment '状态(0-草稿、1-已发布、2-已下线)',
viewNum int default 0 not null comment '浏览数',
thumbNum int default 0 not null comment '点赞数',
favourNum int default 0 not null comment '收藏数',
userId bigint not null comment '创建用户 id',
editTime datetime default CURRENT_TIMESTAMP not null comment '编辑时间',
createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
isDelete tinyint default 0 not null comment '是否删除',
index idx_title (title),
index idx_category (category),
index idx_status (status),
index idx_userId (userId),
index idx_createTime (createTime)
) comment '文章' collate = utf8mb4_unicode_ci;

-- 文章点赞表
create table if not exists article_thumb
(
id bigint auto_increment comment 'id' primary key,
articleId bigint not null comment '文章 id',
userId bigint not null comment '用户 id',
createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
index idx_articleId (articleId),
index idx_userId (userId)
) comment '文章点赞';

-- 文章收藏表
create table if not exists article_favour
(
id bigint auto_increment comment 'id' primary key,
articleId bigint not null comment '文章 id',
userId bigint not null comment '用户 id',
createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
index idx_articleId (articleId),
index idx_userId (userId)
) comment '文章收藏';
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
package com.yupi.mianshiya.controller;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.mianshiya.annotation.AuthCheck;
import com.yupi.mianshiya.common.BaseResponse;
import com.yupi.mianshiya.common.DeleteRequest;
import com.yupi.mianshiya.common.ErrorCode;
import com.yupi.mianshiya.common.ResultUtils;
import com.yupi.mianshiya.constant.UserConstant;
import com.yupi.mianshiya.exception.BusinessException;
import com.yupi.mianshiya.exception.ThrowUtils;
import com.yupi.mianshiya.model.dto.article.ArticleAddRequest;
import com.yupi.mianshiya.model.dto.article.ArticleEditRequest;
import com.yupi.mianshiya.model.dto.article.ArticleQueryRequest;
import com.yupi.mianshiya.model.dto.article.ArticleUpdateRequest;
import com.yupi.mianshiya.model.entity.Article;
import com.yupi.mianshiya.model.entity.User;
import com.yupi.mianshiya.model.vo.ArticleVO;
import com.yupi.mianshiya.service.ArticleService;
import com.yupi.mianshiya.service.UserService;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 文章接口
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@RestController
@RequestMapping("/article")
@Slf4j
public class ArticleController {

@Resource
private ArticleService articleService;

@Resource
private UserService userService;

// region 增删改查

/**
* 创建
*
* @param articleAddRequest
* @param request
* @return
*/
@PostMapping("/add")
public BaseResponse<Long> addArticle(@RequestBody ArticleAddRequest articleAddRequest, HttpServletRequest request) {
if (articleAddRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Article article = new Article();
BeanUtils.copyProperties(articleAddRequest, article);
List<String> tags = articleAddRequest.getTags();
if (tags != null) {
article.setTags(JSONUtil.toJsonStr(tags));
}
articleService.validArticle(article, true);
User loginUser = userService.getLoginUser(request);
article.setUserId(loginUser.getId());
article.setFavourNum(0);
article.setThumbNum(0);
article.setViewNum(0);
boolean result = articleService.save(article);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
long newArticleId = article.getId();
return ResultUtils.success(newArticleId);
}

/**
* 删除
*
* @param deleteRequest
* @param request
* @return
*/
@PostMapping("/delete")
public BaseResponse<Boolean> deleteArticle(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
if (deleteRequest == null || deleteRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = userService.getLoginUser(request);
long id = deleteRequest.getId();
// 判断是否存在
Article oldArticle = articleService.getById(id);
ThrowUtils.throwIf(oldArticle == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可删除
if (!oldArticle.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
boolean b = articleService.removeById(id);
return ResultUtils.success(b);
}

/**
* 更新(仅管理员)
*
* @param articleUpdateRequest
* @return
*/
@PostMapping("/update")
@SaCheckRole(UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> updateArticle(@RequestBody ArticleUpdateRequest articleUpdateRequest) {
if (articleUpdateRequest == null || articleUpdateRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Article article = new Article();
BeanUtils.copyProperties(articleUpdateRequest, article);
List<String> tags = articleUpdateRequest.getTags();
if (tags != null) {
article.setTags(JSONUtil.toJsonStr(tags));
}
// 参数校验
articleService.validArticle(article, false);
long id = articleUpdateRequest.getId();
// 判断是否存在
Article oldArticle = articleService.getById(id);
ThrowUtils.throwIf(oldArticle == null, ErrorCode.NOT_FOUND_ERROR);
boolean result = articleService.updateById(article);
return ResultUtils.success(result);
}

/**
* 根据 id 获取
*
* @param id
* @return
*/
@GetMapping("/get/vo")
public BaseResponse<ArticleVO> getArticleVOById(long id, HttpServletRequest request) {
if (id <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Article article = articleService.getById(id);
if (article == null) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
}
// 增加浏览数
articleService.addViewNum(id);
return ResultUtils.success(articleService.getArticleVO(article, request));
}

/**
* 分页获取列表(仅管理员)
*
* @param articleQueryRequest
* @return
*/
@PostMapping("/list/page")
@SaCheckRole(UserConstant.ADMIN_ROLE)
public BaseResponse<Page<Article>> listArticleByPage(@RequestBody ArticleQueryRequest articleQueryRequest) {
long current = articleQueryRequest.getCurrent();
long size = articleQueryRequest.getPageSize();
Page<Article> articlePage = articleService.page(new Page<>(current, size),
articleService.getQueryWrapper(articleQueryRequest));
return ResultUtils.success(articlePage);
}

/**
* 分页获取列表(封装类)
*
* @param articleQueryRequest
* @param request
* @return
*/
@PostMapping("/list/page/vo")
public BaseResponse<Page<ArticleVO>> listArticleVOByPage(@RequestBody ArticleQueryRequest articleQueryRequest,
HttpServletRequest request) {
long current = articleQueryRequest.getCurrent();
long size = articleQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
Page<Article> articlePage = articleService.page(new Page<>(current, size),
articleService.getQueryWrapper(articleQueryRequest));
return ResultUtils.success(articleService.getArticleVOPage(articlePage, request));
}

/**
* 分页获取当前用户创建的资源列表
*
* @param articleQueryRequest
* @param request
* @return
*/
@PostMapping("/my/list/page/vo")
public BaseResponse<Page<ArticleVO>> listMyArticleVOByPage(@RequestBody ArticleQueryRequest articleQueryRequest,
HttpServletRequest request) {
if (articleQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User loginUser = userService.getLoginUser(request);
articleQueryRequest.setUserId(loginUser.getId());
articleQueryRequest.setNotPublic(true); // 可以查看自己的非公开文章
long current = articleQueryRequest.getCurrent();
long size = articleQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
Page<Article> articlePage = articleService.page(new Page<>(current, size),
articleService.getQueryWrapper(articleQueryRequest));
return ResultUtils.success(articleService.getArticleVOPage(articlePage, request));
}

// endregion

/**
* 编辑(用户)
*
* @param articleEditRequest
* @param request
* @return
*/
@PostMapping("/edit")
public BaseResponse<Boolean> editArticle(@RequestBody ArticleEditRequest articleEditRequest, HttpServletRequest request) {
if (articleEditRequest == null || articleEditRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Article article = new Article();
BeanUtils.copyProperties(articleEditRequest, article);
List<String> tags = articleEditRequest.getTags();
if (tags != null) {
article.setTags(JSONUtil.toJsonStr(tags));
}
// 参数校验
articleService.validArticle(article, false);
User loginUser = userService.getLoginUser(request);
long id = articleEditRequest.getId();
// 判断是否存在
Article oldArticle = articleService.getById(id);
ThrowUtils.throwIf(oldArticle == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可编辑
if (!oldArticle.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
boolean result = articleService.updateById(article);
return ResultUtils.success(result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.yupi.mianshiya.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.mianshiya.common.BaseResponse;
import com.yupi.mianshiya.common.ErrorCode;
import com.yupi.mianshiya.common.ResultUtils;
import com.yupi.mianshiya.exception.BusinessException;
import com.yupi.mianshiya.exception.ThrowUtils;
import com.yupi.mianshiya.model.dto.article.ArticleFavourAddRequest;
import com.yupi.mianshiya.model.dto.article.ArticleQueryRequest;
import com.yupi.mianshiya.model.entity.Article;
import com.yupi.mianshiya.model.entity.User;
import com.yupi.mianshiya.model.vo.ArticleVO;
import com.yupi.mianshiya.service.ArticleFavourService;
import com.yupi.mianshiya.service.ArticleService;
import com.yupi.mianshiya.service.UserService;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 文章收藏接口
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@RestController
@RequestMapping("/article_favour")
@Slf4j
public class ArticleFavourController {

@Resource
private ArticleFavourService articleFavourService;

@Resource
private ArticleService articleService;

@Resource
private UserService userService;

/**
* 收藏 / 取消收藏
*
* @param articleFavourAddRequest
* @param request
* @return resultNum 收藏变化数
*/
@PostMapping("/")
public BaseResponse<Integer> doArticleFavour(@RequestBody ArticleFavourAddRequest articleFavourAddRequest,
HttpServletRequest request) {
if (articleFavourAddRequest == null || articleFavourAddRequest.getArticleId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// 登录才能操作
final User loginUser = userService.getLoginUser(request);
long articleId = articleFavourAddRequest.getArticleId();
int result = articleFavourService.doArticleFavour(articleId, loginUser);
return ResultUtils.success(result);
}

/**
* 获取我收藏的文章列表
*
* @param articleQueryRequest
* @param request
* @return
*/
@PostMapping("/my/list/page/vo")
public BaseResponse<Page<ArticleVO>> listMyFavourArticleByPage(@RequestBody ArticleQueryRequest articleQueryRequest,
HttpServletRequest request) {
if (articleQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User loginUser = userService.getLoginUser(request);
long current = articleQueryRequest.getCurrent();
long size = articleQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
Page<Article> articlePage = articleFavourService.listFavourArticleByPage(new Page<>(current, size),
articleService.getQueryWrapper(articleQueryRequest), loginUser.getId());
return ResultUtils.success(articleService.getArticleVOPage(articlePage, request));
}

}
Loading