238 lines
7.2 KiB
Go
238 lines
7.2 KiB
Go
package api
|
|
|
|
import (
|
|
"bbs-go/internal/models/constants"
|
|
"bbs-go/internal/pkg/bbsurls"
|
|
"bbs-go/internal/pkg/errs"
|
|
"bbs-go/internal/spam"
|
|
"log/slog"
|
|
"strconv"
|
|
|
|
"github.com/kataras/iris/v12"
|
|
"github.com/mlogclub/simple/common/jsons"
|
|
"github.com/mlogclub/simple/sqls"
|
|
"github.com/mlogclub/simple/web"
|
|
"github.com/mlogclub/simple/web/params"
|
|
"github.com/panjf2000/ants/v2"
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"bbs-go/internal/controllers/render"
|
|
"bbs-go/internal/models"
|
|
"bbs-go/internal/services"
|
|
)
|
|
|
|
type ArticleController struct {
|
|
Ctx iris.Context
|
|
}
|
|
|
|
func (c *ArticleController) GetClean() *web.JsonResult {
|
|
go func() {
|
|
p, _ := ants.NewPool(10)
|
|
services.ArticleService.ScanDesc(func(articles []models.Article) {
|
|
var ids []int64
|
|
for _, article := range articles {
|
|
if article.ContentType == constants.ContentTypeHtml {
|
|
ids = append(ids, article.Id)
|
|
}
|
|
}
|
|
if len(ids) > 0 {
|
|
p.Submit(func() {
|
|
sqls.DB().Delete(&models.Article{}, "id in ?", ids)
|
|
logrus.Info("清理文章:", ids)
|
|
})
|
|
}
|
|
})
|
|
}()
|
|
return web.JsonSuccess()
|
|
}
|
|
|
|
// 文章详情
|
|
func (c *ArticleController) GetBy(articleId int64) *web.JsonResult {
|
|
article := services.ArticleService.Get(articleId)
|
|
if article == nil || article.Status == constants.StatusDeleted {
|
|
return web.JsonErrorCode(404, "文章不存在")
|
|
}
|
|
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
|
|
// 审核中文章控制展示
|
|
if article.Status == constants.StatusReview {
|
|
if user != nil {
|
|
if article.UserId != user.Id && !user.IsOwnerOrAdmin() {
|
|
return web.JsonErrorCode(403, "文章审核中")
|
|
}
|
|
} else {
|
|
return web.JsonErrorCode(403, "文章审核中")
|
|
}
|
|
}
|
|
|
|
services.ArticleService.IncrViewCount(articleId) // 增加浏览量
|
|
return web.JsonData(render.BuildArticle(article, user))
|
|
}
|
|
|
|
// PostCreate 发表文章
|
|
func (c *ArticleController) PostCreate() *web.JsonResult {
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
if err := services.UserService.CheckPostStatus(user); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
form := models.GetCreateArticleForm(c.Ctx)
|
|
|
|
if err := spam.CheckArticle(user, form); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
|
|
article, err := services.ArticleService.Publish(user.Id, form)
|
|
if err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
return web.JsonData(render.BuildArticle(article, user))
|
|
}
|
|
|
|
// 编辑时获取详情
|
|
func (c *ArticleController) GetEditBy(articleId int64) *web.JsonResult {
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
if err := services.UserService.CheckPostStatus(user); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
|
|
article := services.ArticleService.Get(articleId)
|
|
if article == nil || article.Status == constants.StatusDeleted {
|
|
return web.JsonErrorMsg("话题不存在或已被删除")
|
|
}
|
|
|
|
// 非作者、且非管理员
|
|
if article.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
|
return web.JsonErrorMsg("无权限")
|
|
}
|
|
|
|
tags := services.ArticleService.GetArticleTags(articleId)
|
|
var tagNames []string
|
|
if len(tags) > 0 {
|
|
for _, tag := range tags {
|
|
tagNames = append(tagNames, tag.Name)
|
|
}
|
|
}
|
|
|
|
var cover *models.ImageDTO
|
|
if err := jsons.Parse(article.Cover, &cover); err != nil {
|
|
slog.Error(err.Error(), slog.Any("err", err))
|
|
}
|
|
|
|
return web.NewEmptyRspBuilder().
|
|
Put("id", article.Id).
|
|
Put("articleId", article.Id).
|
|
Put("title", article.Title).
|
|
Put("content", article.Content).
|
|
Put("tags", tagNames).
|
|
Put("cover", cover).
|
|
JsonResult()
|
|
}
|
|
|
|
// 编辑文章
|
|
func (c *ArticleController) PostEditBy(articleId int64) *web.JsonResult {
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
if err := services.UserService.CheckPostStatus(user); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
|
|
var (
|
|
tags = params.FormValueStringArray(c.Ctx, "tags")
|
|
title = c.Ctx.PostValue("title")
|
|
content = c.Ctx.PostValue("content")
|
|
cover = models.GetImageDTO(c.Ctx, "cover")
|
|
)
|
|
|
|
article := services.ArticleService.Get(articleId)
|
|
if article == nil || article.Status == constants.StatusDeleted {
|
|
return web.JsonErrorMsg("文章不存在")
|
|
}
|
|
|
|
// 非作者、且非管理员
|
|
if article.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
|
return web.JsonErrorMsg("无权限")
|
|
}
|
|
|
|
if err := services.ArticleService.Edit(articleId, tags, title, content, cover); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
// 操作日志
|
|
services.OperateLogService.AddOperateLog(user.Id, constants.OpTypeUpdate, constants.EntityArticle, articleId,
|
|
"", c.Ctx.Request())
|
|
return web.NewEmptyRspBuilder().Put("articleId", article.Id).JsonResult()
|
|
}
|
|
|
|
// 删除文章
|
|
func (c *ArticleController) PostDeleteBy(articleId int64) *web.JsonResult {
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
if err := services.UserService.CheckPostStatus(user); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
|
|
article := services.ArticleService.Get(articleId)
|
|
if article == nil || article.Status == constants.StatusDeleted {
|
|
return web.JsonErrorMsg("文章不存在")
|
|
}
|
|
|
|
// 非作者、且非管理员
|
|
if article.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
|
return web.JsonErrorMsg("无权限")
|
|
}
|
|
|
|
if err := services.ArticleService.Delete(articleId); err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
// 操作日志
|
|
services.OperateLogService.AddOperateLog(user.Id, constants.OpTypeDelete, constants.EntityArticle, articleId,
|
|
"", c.Ctx.Request())
|
|
return web.JsonSuccess()
|
|
}
|
|
|
|
// 收藏文章
|
|
func (c *ArticleController) PostFavoriteBy(articleId int64) *web.JsonResult {
|
|
user := services.UserTokenService.GetCurrent(c.Ctx)
|
|
if user == nil {
|
|
return web.JsonError(errs.NotLogin)
|
|
}
|
|
err := services.FavoriteService.AddArticleFavorite(user.Id, articleId)
|
|
if err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
return web.JsonSuccess()
|
|
}
|
|
|
|
// 文章跳转链接
|
|
func (c *ArticleController) GetRedirectBy(articleId int64) *web.JsonResult {
|
|
article := services.ArticleService.Get(articleId)
|
|
if article == nil || article.Status != constants.StatusOk {
|
|
return web.JsonErrorMsg("文章不存在")
|
|
}
|
|
return web.NewEmptyRspBuilder().Put("url", bbsurls.ArticleUrl(articleId)).JsonResult()
|
|
}
|
|
|
|
// 用户文章列表
|
|
func (c *ArticleController) GetUserArticles() *web.JsonResult {
|
|
userId, err := params.FormValueInt64(c.Ctx, "userId")
|
|
if err != nil {
|
|
return web.JsonError(err)
|
|
}
|
|
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
|
articles, cursor, hasMore := services.ArticleService.GetUserArticles(userId, cursor)
|
|
return web.JsonCursorData(render.BuildSimpleArticles(articles), strconv.FormatInt(cursor, 10), hasMore)
|
|
}
|
|
|
|
// 文章列表
|
|
func (c *ArticleController) GetArticles() *web.JsonResult {
|
|
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
|
articles, cursor, hasMore := services.ArticleService.GetArticles(cursor)
|
|
return web.JsonCursorData(render.BuildSimpleArticles(articles), strconv.FormatInt(cursor, 10), hasMore)
|
|
}
|
|
|
|
// 标签文章列表
|
|
func (c *ArticleController) GetTagArticles() *web.JsonResult {
|
|
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
|
tagId := params.FormValueInt64Default(c.Ctx, "tagId", 0)
|
|
articles, cursor, hasMore := services.ArticleService.GetTagArticles(tagId, cursor)
|
|
return web.JsonCursorData(render.BuildSimpleArticles(articles), strconv.FormatInt(cursor, 10), hasMore)
|
|
}
|