20251209
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/pkg/bbsurls"
|
||||
"log/slog"
|
||||
|
||||
"github.com/dchest/captcha"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
type CaptchaController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *CaptchaController) GetRequest() *web.JsonResult {
|
||||
captchaId := c.Ctx.FormValue("captchaId")
|
||||
if strs.IsNotBlank(captchaId) { // reload
|
||||
if !captcha.Reload(captchaId) {
|
||||
// reload 失败,重新加载验证码
|
||||
captchaId = captcha.NewLen(4)
|
||||
}
|
||||
} else {
|
||||
captchaId = captcha.NewLen(4)
|
||||
}
|
||||
captchaUrl := bbsurls.AbsUrl("/api/captcha/show?captchaId=" + captchaId + "&r=" + strs.UUID())
|
||||
return web.NewEmptyRspBuilder().
|
||||
Put("captchaId", captchaId).
|
||||
Put("captchaUrl", captchaUrl).
|
||||
JsonResult()
|
||||
}
|
||||
|
||||
func (c *CaptchaController) GetShow() {
|
||||
captchaId := c.Ctx.URLParam("captchaId")
|
||||
|
||||
if captchaId == "" {
|
||||
c.Ctx.StatusCode(404)
|
||||
return
|
||||
}
|
||||
|
||||
if !captcha.Reload(captchaId) {
|
||||
c.Ctx.StatusCode(404)
|
||||
return
|
||||
}
|
||||
|
||||
c.Ctx.Header("Content-Type", "image/png")
|
||||
if err := captcha.WriteImage(c.Ctx.ResponseWriter(), captchaId, captcha.StdWidth, captcha.StdHeight); err != nil {
|
||||
slog.Error(err.Error(), slog.Any("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CaptchaController) GetVerify() *web.JsonResult {
|
||||
captchaId := c.Ctx.URLParam("captchaId")
|
||||
captchaCode := c.Ctx.URLParam("captchaCode")
|
||||
success := captcha.VerifyString(captchaId, captchaCode)
|
||||
return web.NewEmptyRspBuilder().Put("success", success).JsonResult()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/cache"
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/services"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/dates"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
type CheckinController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
// PostCheckin 签到
|
||||
func (c *CheckinController) PostCheckin() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
err := services.CheckInService.CheckIn(user.Id)
|
||||
if err == nil {
|
||||
return web.JsonSuccess()
|
||||
} else {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetCheckin 获取签到信息
|
||||
func (c *CheckinController) GetCheckin() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
checkIn := services.CheckInService.GetByUserId(user.Id)
|
||||
if checkIn != nil {
|
||||
today := dates.GetDay(time.Now())
|
||||
return web.NewRspBuilder(checkIn).
|
||||
Put("checkIn", checkIn.LatestDayName == today). // 今日是否已签到
|
||||
JsonResult()
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// GetRank 获取当天签到排行榜(最早签到的排在最前面)
|
||||
func (c *CheckinController) GetRank() *web.JsonResult {
|
||||
list := cache.UserCache.GetCheckInRank()
|
||||
var itemList []map[string]interface{}
|
||||
for _, checkIn := range list {
|
||||
itemList = append(itemList, web.NewRspBuilder(checkIn).
|
||||
Put("user", render.BuildUserInfoDefaultIfNull(checkIn.UserId)).
|
||||
Build())
|
||||
}
|
||||
return web.JsonData(itemList)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/spam"
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"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/services"
|
||||
)
|
||||
|
||||
type CommentController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *CommentController) GetClean() *web.JsonResult {
|
||||
go func() {
|
||||
p, _ := ants.NewPool(10)
|
||||
services.CommentService.Scan(func(comments []models.Comment) {
|
||||
var ids []int64
|
||||
for _, comment := range comments {
|
||||
if comment.ContentType == constants.ContentTypeHtml {
|
||||
ids = append(ids, comment.Id)
|
||||
}
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
p.Submit(func() {
|
||||
sqls.DB().Delete(&models.Comment{}, "id in ?", ids)
|
||||
logrus.Info("清理评论:", ids)
|
||||
})
|
||||
}
|
||||
})
|
||||
}()
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *CommentController) GetComments() *web.JsonResult {
|
||||
var (
|
||||
err error
|
||||
cursor int64
|
||||
entityType string
|
||||
entityId int64
|
||||
)
|
||||
cursor = params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
|
||||
if entityType, err = params.FormValueRequired(c.Ctx, "entityType"); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
if entityId, err = params.FormValueInt64(c.Ctx, "entityId"); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
currentUser := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
comments, cursor, hasMore := services.CommentService.GetComments(entityType, entityId, cursor)
|
||||
return web.JsonCursorData(render.BuildComments(comments, currentUser, true, false), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
func (c *CommentController) GetReplies() *web.JsonResult {
|
||||
var (
|
||||
cursor = params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
commentId = params.FormValueInt64Default(c.Ctx, "commentId", 0)
|
||||
)
|
||||
currentUser := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
comments, cursor, hasMore := services.CommentService.GetReplies(commentId, cursor, 10)
|
||||
return web.JsonCursorData(render.BuildComments(comments, currentUser, false, true), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
func (c *CommentController) PostCreate() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
form := models.GetCreateCommentForm(c.Ctx)
|
||||
if err := spam.CheckComment(user, form); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
comment, err := services.CommentService.Publish(user.Id, form)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
return web.JsonData(render.BuildComment(comment))
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type ConfigController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *ConfigController) GetConfigs() *web.JsonResult {
|
||||
config := services.SysConfigService.GetConfig()
|
||||
return web.JsonData(config)
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/services"
|
||||
"strconv"
|
||||
|
||||
"github.com/emirpasic/gods/sets/hashset"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
)
|
||||
|
||||
type FansController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *FansController) PostFollow() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
|
||||
otherId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
if otherId <= 0 {
|
||||
return web.JsonErrorMsg("param: userId required")
|
||||
}
|
||||
|
||||
err := services.UserFollowService.Follow(user.Id, otherId)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *FansController) PostUnfollow() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
|
||||
otherId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
if otherId <= 0 {
|
||||
return web.JsonErrorMsg("param: userId required")
|
||||
}
|
||||
|
||||
err := services.UserFollowService.UnFollow(user.Id, otherId)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *FansController) GetIsfollowed() *web.JsonResult {
|
||||
userId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
current := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var followed = false
|
||||
if current != nil && current.Id != userId {
|
||||
followed = services.UserFollowService.IsFollowed(current.Id, userId)
|
||||
}
|
||||
return web.JsonData(followed)
|
||||
}
|
||||
|
||||
func (c *FansController) GetFans() *web.JsonResult {
|
||||
userId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
userIds, cursor, hasMore := services.UserFollowService.GetFans(userId, cursor, 10)
|
||||
|
||||
current := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var followedSet hashset.Set
|
||||
if current != nil {
|
||||
followedSet = services.UserFollowService.IsFollowedUsers(current.Id, userIds...)
|
||||
}
|
||||
|
||||
var itemList []*models.UserInfo
|
||||
for _, id := range userIds {
|
||||
item := render.BuildUserInfoDefaultIfNull(id)
|
||||
item.Followed = followedSet.Contains(id)
|
||||
itemList = append(itemList, item)
|
||||
}
|
||||
return web.JsonCursorData(itemList, strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
func (c *FansController) GetFollowed() *web.JsonResult {
|
||||
userId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
userIds, cursor, hasMore := services.UserFollowService.GetFollows(userId, cursor, 10)
|
||||
|
||||
current := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var followedSet hashset.Set
|
||||
if current != nil {
|
||||
if current.Id == userId {
|
||||
followedSet = *hashset.New()
|
||||
for _, id := range userIds {
|
||||
followedSet.Add(id)
|
||||
}
|
||||
} else {
|
||||
followedSet = services.UserFollowService.IsFollowedUsers(current.Id, userIds...)
|
||||
}
|
||||
}
|
||||
|
||||
var itemList []*models.UserInfo
|
||||
for _, id := range userIds {
|
||||
item := render.BuildUserInfoDefaultIfNull(id)
|
||||
item.Followed = followedSet.Contains(id)
|
||||
itemList = append(itemList, item)
|
||||
}
|
||||
return web.JsonCursorData(itemList, strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
func (c *FansController) GetRecentFans() *web.JsonResult {
|
||||
userId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
userIds, cursor, hasMore := services.UserFollowService.GetFans(userId, 0, 10)
|
||||
|
||||
current := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var followedSet hashset.Set
|
||||
if current != nil {
|
||||
followedSet = services.UserFollowService.IsFollowedUsers(current.Id, userIds...)
|
||||
}
|
||||
|
||||
var itemList []*models.UserInfo
|
||||
for _, id := range userIds {
|
||||
item := render.BuildUserInfoDefaultIfNull(id)
|
||||
item.Followed = followedSet.Contains(id)
|
||||
itemList = append(itemList, item)
|
||||
}
|
||||
return web.JsonCursorData(itemList, strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
func (c *FansController) GetRecentFollow() *web.JsonResult {
|
||||
userId := params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
userIds, cursor, hasMore := services.UserFollowService.GetFollows(userId, 0, 10)
|
||||
|
||||
current := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var followedSet hashset.Set
|
||||
if current != nil {
|
||||
if current.Id == userId {
|
||||
followedSet = *hashset.New()
|
||||
for _, id := range userIds {
|
||||
followedSet.Add(id)
|
||||
}
|
||||
} else {
|
||||
followedSet = services.UserFollowService.IsFollowedUsers(current.Id, userIds...)
|
||||
}
|
||||
}
|
||||
|
||||
var itemList []*models.UserInfo
|
||||
for _, id := range userIds {
|
||||
item := render.BuildUserInfoDefaultIfNull(id)
|
||||
item.Followed = followedSet.Contains(id)
|
||||
itemList = append(itemList, item)
|
||||
}
|
||||
return web.JsonCursorData(itemList, strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type FavoriteController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *FavoriteController) PostAdd() *web.JsonResult {
|
||||
var (
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityId = params.FormValueInt64Default(c.Ctx, "entityId", 0)
|
||||
)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
var err error
|
||||
if entityType == constants.EntityTopic {
|
||||
err = services.FavoriteService.AddTopicFavorite(user.Id, entityId)
|
||||
} else if entityType == constants.EntityArticle {
|
||||
err = services.FavoriteService.AddArticleFavorite(user.Id, entityId)
|
||||
} else {
|
||||
err = errors.New("unsupproted")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 取消收藏
|
||||
func (c *FavoriteController) PostDelete() *web.JsonResult {
|
||||
var (
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityId = params.FormValueInt64Default(c.Ctx, "entityId", 0)
|
||||
)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
tmp := services.FavoriteService.GetBy(user.Id, entityType, entityId)
|
||||
if tmp != nil {
|
||||
services.FavoriteService.Delete(tmp.Id)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/services"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
)
|
||||
|
||||
type LikeController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *LikeController) PostLike() *web.JsonResult {
|
||||
var (
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityId = params.FormValueInt64Default(c.Ctx, "entityId", 0)
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
err error
|
||||
)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if entityType == constants.EntityTopic {
|
||||
err = services.UserLikeService.TopicLike(user.Id, entityId)
|
||||
} else if entityType == constants.EntityArticle {
|
||||
err = services.UserLikeService.ArticleLike(user.Id, entityId)
|
||||
} else if entityType == constants.EntityComment {
|
||||
err = services.UserLikeService.CommentLike(user.Id, entityId)
|
||||
}
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *LikeController) PostUnlike() *web.JsonResult {
|
||||
var (
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityId = params.FormValueInt64Default(c.Ctx, "entityId", 0)
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
err error
|
||||
)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if entityType == constants.EntityTopic {
|
||||
err = services.UserLikeService.TopicUnLike(user.Id, entityId)
|
||||
} else if entityType == constants.EntityArticle {
|
||||
err = services.UserLikeService.ArticleUnLike(user.Id, entityId)
|
||||
} else if entityType == constants.EntityComment {
|
||||
err = services.UserLikeService.CommentUnLike(user.Id, entityId)
|
||||
}
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *LikeController) GetLiked_ids() *web.JsonResult {
|
||||
var (
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityIds = params.FormValueInt64Array(c.Ctx, "entityIds")
|
||||
likedEntityIds []int64
|
||||
)
|
||||
if user != nil {
|
||||
likedEntityIds = services.UserLikeService.IsLiked(user.Id, entityType, entityIds)
|
||||
}
|
||||
return web.JsonData(likedEntityIds)
|
||||
}
|
||||
|
||||
func (c *LikeController) GetLiked() *web.JsonResult {
|
||||
var (
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
entityType = params.FormValue(c.Ctx, "entityType")
|
||||
entityId = params.FormValueInt64Default(c.Ctx, "entityId", 0)
|
||||
)
|
||||
if user == nil || strs.IsBlank(entityType) || entityId <= 0 {
|
||||
return web.JsonData(false)
|
||||
} else {
|
||||
liked := services.UserLikeService.Exists(user.Id, entityType, entityId)
|
||||
return web.JsonData(liked)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type LinkController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *LinkController) GetBy(id int64) *web.JsonResult {
|
||||
link := services.LinkService.Get(id)
|
||||
if link == nil || link.Status == constants.StatusDeleted {
|
||||
return web.JsonErrorMsg("数据不存在")
|
||||
}
|
||||
return web.JsonData(c.buildLink(*link))
|
||||
}
|
||||
|
||||
// 列表
|
||||
func (c *LinkController) GetList() *web.JsonResult {
|
||||
links := services.LinkService.Find(sqls.NewCnd().
|
||||
Eq("status", constants.StatusOk).Asc("id"))
|
||||
|
||||
var itemList []map[string]interface{}
|
||||
for _, v := range links {
|
||||
itemList = append(itemList, c.buildLink(v))
|
||||
}
|
||||
return web.JsonData(itemList)
|
||||
}
|
||||
|
||||
// 列表
|
||||
func (c *LinkController) GetLinks() *web.JsonResult {
|
||||
page := params.FormValueIntDefault(c.Ctx, "page", 1)
|
||||
|
||||
links, paging := services.LinkService.FindPageByCnd(sqls.NewCnd().
|
||||
Eq("status", constants.StatusOk).Page(page, 20).Asc("id"))
|
||||
|
||||
var itemList []map[string]interface{}
|
||||
for _, v := range links {
|
||||
itemList = append(itemList, c.buildLink(v))
|
||||
}
|
||||
return web.JsonPageData(itemList, paging)
|
||||
}
|
||||
|
||||
// 前10个链接
|
||||
func (c *LinkController) GetToplinks() *web.JsonResult {
|
||||
links := services.LinkService.Find(sqls.NewCnd().
|
||||
Eq("status", constants.StatusOk).Limit(10).Asc("id"))
|
||||
|
||||
var itemList []map[string]interface{}
|
||||
for _, v := range links {
|
||||
itemList = append(itemList, c.buildLink(v))
|
||||
}
|
||||
return web.JsonData(itemList)
|
||||
}
|
||||
|
||||
func (c *LinkController) buildLink(link models.Link) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": link.Id,
|
||||
"linkId": link.Id,
|
||||
"url": link.Url,
|
||||
"title": link.Title,
|
||||
"summary": link.Summary,
|
||||
"logo": link.Logo,
|
||||
"createTime": link.CreateTime,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/controllers/render"
|
||||
|
||||
"github.com/dchest/captcha"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type LoginController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
// 注册
|
||||
func (c *LoginController) PostSignup() *web.JsonResult {
|
||||
var (
|
||||
captchaId = c.Ctx.PostValueTrim("captchaId")
|
||||
captchaCode = c.Ctx.PostValueTrim("captchaCode")
|
||||
email = c.Ctx.PostValueTrim("email")
|
||||
username = c.Ctx.PostValueTrim("username")
|
||||
password = c.Ctx.PostValueTrim("password")
|
||||
rePassword = c.Ctx.PostValueTrim("rePassword")
|
||||
nickname = c.Ctx.PostValueTrim("nickname")
|
||||
redirect = c.Ctx.FormValue("redirect")
|
||||
)
|
||||
loginMethod := services.SysConfigService.GetLoginMethod()
|
||||
if !loginMethod.Password {
|
||||
return web.JsonErrorMsg("账号密码登录/注册已禁用")
|
||||
}
|
||||
if !captcha.VerifyString(captchaId, captchaCode) {
|
||||
return web.JsonError(errs.CaptchaError)
|
||||
}
|
||||
user, err := services.UserService.SignUp(username, email, nickname, password, rePassword)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return render.BuildLoginSuccess(c.Ctx, user, redirect)
|
||||
}
|
||||
|
||||
// 用户名密码登录
|
||||
func (c *LoginController) PostSignin() *web.JsonResult {
|
||||
var (
|
||||
captchaId = c.Ctx.PostValueTrim("captchaId")
|
||||
captchaCode = c.Ctx.PostValueTrim("captchaCode")
|
||||
username = c.Ctx.PostValueTrim("username")
|
||||
password = c.Ctx.PostValueTrim("password")
|
||||
redirect = c.Ctx.FormValue("redirect")
|
||||
)
|
||||
loginMethod := services.SysConfigService.GetLoginMethod()
|
||||
if !loginMethod.Password {
|
||||
return web.JsonErrorMsg("账号密码登录/注册已禁用")
|
||||
}
|
||||
|
||||
if !captcha.VerifyString(captchaId, captchaCode) {
|
||||
return web.JsonError(errs.CaptchaError)
|
||||
}
|
||||
user, err := services.UserService.SignIn(username, password)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return render.BuildLoginSuccess(c.Ctx, user, redirect)
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
func (c *LoginController) GetSignout() *web.JsonResult {
|
||||
err := services.UserTokenService.Signout(c.Ctx)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/search"
|
||||
"bbs-go/internal/services"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type SearchController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *SearchController) AnyReindex() *web.JsonResult {
|
||||
go services.TopicService.ScanDesc(func(topics []models.Topic) {
|
||||
for _, topic := range topics {
|
||||
if topic.Status != constants.StatusDeleted {
|
||||
search.UpdateTopicIndex(&topic)
|
||||
}
|
||||
}
|
||||
})
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *SearchController) GetTopic() *web.JsonResult {
|
||||
var (
|
||||
cursor = params.FormValueIntDefault(c.Ctx, "cursor", 1)
|
||||
keyword = params.FormValue(c.Ctx, "keyword")
|
||||
nodeId = params.FormValueInt64Default(c.Ctx, "nodeId", 0)
|
||||
timeRange = params.FormValueIntDefault(c.Ctx, "timeRange", 0)
|
||||
limit = 20
|
||||
)
|
||||
list, _, err := search.SearchTopic(keyword, nodeId, timeRange, cursor, limit)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonCursorData(render.BuildSearchTopics(list), cast.ToString(cursor+1), len(list) >= limit)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
|
||||
"bbs-go/internal/cache"
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type TagController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
// 标签详情
|
||||
func (c *TagController) GetBy(tagId int64) *web.JsonResult {
|
||||
tag := cache.TagCache.Get(tagId)
|
||||
if tag == nil {
|
||||
return web.JsonErrorMsg("标签不存在")
|
||||
}
|
||||
return web.JsonData(render.BuildTag(tag))
|
||||
}
|
||||
|
||||
// 标签列表
|
||||
func (c *TagController) GetTags() *web.JsonResult {
|
||||
page := params.FormValueIntDefault(c.Ctx, "page", 1)
|
||||
tags, paging := services.TagService.FindPageByCnd(sqls.NewCnd().
|
||||
Eq("status", constants.StatusOk).
|
||||
Page(page, 200).Desc("id"))
|
||||
|
||||
return web.JsonPageData(render.BuildTags(tags), paging)
|
||||
}
|
||||
|
||||
// 标签自动完成
|
||||
func (c *TagController) PostAutocomplete() *web.JsonResult {
|
||||
input := c.Ctx.FormValue("input")
|
||||
tags := services.TagService.Autocomplete(input)
|
||||
return web.JsonData(tags)
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/common"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/pkg/markdown"
|
||||
"bbs-go/internal/spam"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
|
||||
"bbs-go/internal/cache"
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type TopicController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *TopicController) GetNode_navs() *web.JsonResult {
|
||||
nodes := []models.NodeResponse{
|
||||
{
|
||||
Id: 0,
|
||||
Name: "最新",
|
||||
},
|
||||
{
|
||||
Id: -1,
|
||||
Name: "推荐",
|
||||
},
|
||||
{
|
||||
Id: -2,
|
||||
Name: "关注",
|
||||
},
|
||||
}
|
||||
realNodes := render.BuildNodes(services.TopicNodeService.GetNodes())
|
||||
nodes = append(nodes, realNodes...)
|
||||
return web.JsonData(nodes)
|
||||
}
|
||||
|
||||
// 节点
|
||||
func (c *TopicController) GetNodes() *web.JsonResult {
|
||||
nodes := render.BuildNodes(services.TopicNodeService.GetNodes())
|
||||
return web.JsonData(nodes)
|
||||
}
|
||||
|
||||
// 节点信息
|
||||
func (c *TopicController) GetNode() *web.JsonResult {
|
||||
nodeId := params.FormValueInt64Default(c.Ctx, "nodeId", 0)
|
||||
node := services.TopicNodeService.Get(nodeId)
|
||||
return web.JsonData(render.BuildNode(node))
|
||||
}
|
||||
|
||||
// 发表帖子
|
||||
func (c *TopicController) PostCreate() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
form := models.GetCreateTopicForm(c.Ctx)
|
||||
|
||||
if err := spam.CheckTopic(user, form); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
topic, err := services.TopicPublishService.Publish(user.Id, form)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonData(render.BuildSimpleTopic(topic))
|
||||
}
|
||||
|
||||
// 编辑时获取详情
|
||||
func (c *TopicController) GetEditBy(topicId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
topic := services.TopicService.Get(topicId)
|
||||
if topic == nil || topic.Status != constants.StatusOk {
|
||||
return web.JsonErrorMsg("话题不存在或已被删除")
|
||||
}
|
||||
if topic.Type != constants.TopicTypeTopic {
|
||||
return web.JsonErrorMsg("当前类型帖子不支持修改")
|
||||
}
|
||||
|
||||
// 非作者、且非管理员
|
||||
if topic.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
|
||||
tags := services.TopicService.GetTopicTags(topicId)
|
||||
var tagNames []string
|
||||
if len(tags) > 0 {
|
||||
for _, tag := range tags {
|
||||
tagNames = append(tagNames, tag.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return web.NewEmptyRspBuilder().
|
||||
Put("id", topic.Id).
|
||||
Put("nodeId", topic.NodeId).
|
||||
Put("title", topic.Title).
|
||||
Put("content", topic.Content).
|
||||
Put("hideContent", topic.HideContent).
|
||||
Put("tags", tagNames).
|
||||
JsonResult()
|
||||
}
|
||||
|
||||
// 编辑帖子
|
||||
func (c *TopicController) PostEditBy(topicId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
topic := services.TopicService.Get(topicId)
|
||||
if topic == nil || topic.Status != constants.StatusOk {
|
||||
return web.JsonErrorMsg("话题不存在或已被删除")
|
||||
}
|
||||
|
||||
// 非作者、且非管理员
|
||||
if topic.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
|
||||
var (
|
||||
nodeId = params.FormValueInt64Default(c.Ctx, "nodeId", 0)
|
||||
title = strings.TrimSpace(params.FormValue(c.Ctx, "title"))
|
||||
content = strings.TrimSpace(params.FormValue(c.Ctx, "content"))
|
||||
hideContent = strings.TrimSpace(params.FormValue(c.Ctx, "hideContent"))
|
||||
tags = params.FormValueStringArray(c.Ctx, "tags")
|
||||
)
|
||||
|
||||
err := services.TopicService.Edit(topicId, nodeId, tags, title, content, hideContent)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
// 操作日志
|
||||
services.OperateLogService.AddOperateLog(user.Id, constants.OpTypeUpdate, constants.EntityTopic, topicId,
|
||||
"", c.Ctx.Request())
|
||||
return web.JsonData(render.BuildSimpleTopic(topic))
|
||||
}
|
||||
|
||||
// 删除帖子
|
||||
func (c *TopicController) PostDeleteBy(topicId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
topic := services.TopicService.Get(topicId)
|
||||
if topic == nil || topic.Status != constants.StatusOk {
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 非作者、且非管理员
|
||||
if topic.UserId != user.Id && !user.HasAnyRole(constants.RoleAdmin, constants.RoleOwner) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
|
||||
if err := services.TopicService.Delete(topicId, user.Id, c.Ctx.Request()); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// PostRecommendBy 设为推荐
|
||||
func (c *TopicController) PostRecommendBy(topicId int64) *web.JsonResult {
|
||||
recommend, err := params.FormValueBool(c.Ctx, "recommend")
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if !user.HasAnyRole(constants.RoleOwner, constants.RoleAdmin) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
|
||||
err = services.TopicService.SetRecommend(topicId, recommend)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 帖子详情
|
||||
func (c *TopicController) GetBy(topicId int64) *web.JsonResult {
|
||||
topic := services.TopicService.Get(topicId)
|
||||
if topic == nil || topic.Status == constants.StatusDeleted {
|
||||
return web.JsonErrorMsg("帖子不存在")
|
||||
}
|
||||
|
||||
// 审核中文章控制展示
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if topic.Status == constants.StatusReview {
|
||||
if user != nil {
|
||||
if topic.UserId != user.Id && !user.IsOwnerOrAdmin() {
|
||||
return web.JsonErrorCode(403, "文章审核中")
|
||||
}
|
||||
} else {
|
||||
return web.JsonErrorCode(403, "文章审核中")
|
||||
}
|
||||
}
|
||||
|
||||
services.TopicService.IncrViewCount(topicId) // 增加浏览量
|
||||
return web.JsonData(render.BuildTopic(topic, user))
|
||||
}
|
||||
|
||||
// 点赞用户
|
||||
func (c *TopicController) GetRecentlikesBy(topicId int64) *web.JsonResult {
|
||||
likes := services.UserLikeService.Recent(constants.EntityTopic, topicId, 5)
|
||||
var users []models.UserInfo
|
||||
for _, like := range likes {
|
||||
userInfo := render.BuildUserInfoDefaultIfNull(like.UserId)
|
||||
if userInfo != nil {
|
||||
users = append(users, *userInfo)
|
||||
}
|
||||
}
|
||||
return web.JsonData(users)
|
||||
}
|
||||
|
||||
// 最新帖子
|
||||
func (c *TopicController) GetRecent() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
topics := services.TopicService.Find(sqls.NewCnd().Where("status = ?", constants.StatusOk).Desc("id").Limit(10))
|
||||
return web.JsonData(render.BuildSimpleTopics(topics, user))
|
||||
}
|
||||
|
||||
// 用户帖子列表
|
||||
func (c *TopicController) GetUserTopics() *web.JsonResult {
|
||||
userId, err := params.FormValueInt64(c.Ctx, "userId")
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
topics, cursor, hasMore := services.TopicService.GetUserTopics(userId, cursor)
|
||||
return web.JsonCursorData(render.BuildSimpleTopics(topics, user), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
// 帖子列表
|
||||
func (c *TopicController) GetTopics() *web.JsonResult {
|
||||
var (
|
||||
cursor = params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
nodeId = params.FormValueInt64Default(c.Ctx, "nodeId", 0)
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
)
|
||||
if nodeId == constants.NodeIdFollow && user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
|
||||
var temp []models.Topic
|
||||
if cursor <= 0 {
|
||||
stickyTopics := services.TopicService.GetStickyTopics(nodeId, 3)
|
||||
temp = append(temp, stickyTopics...)
|
||||
}
|
||||
topics, cursor, hasMore := services.TopicService.GetTopics(user, nodeId, cursor)
|
||||
for _, topic := range topics {
|
||||
topic.Sticky = false // 正常列表不要渲染置顶
|
||||
temp = append(temp, topic)
|
||||
}
|
||||
list := common.Distinct(temp, func(t models.Topic) any {
|
||||
return t.Id
|
||||
})
|
||||
return web.JsonCursorData(render.BuildSimpleTopics(list, user), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
// 标签帖子列表
|
||||
func (c *TopicController) GetTagTopics() *web.JsonResult {
|
||||
var (
|
||||
cursor = params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
tagId, err = params.FormValueInt64(c.Ctx, "tagId")
|
||||
user = services.UserTokenService.GetCurrent(c.Ctx)
|
||||
)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
topics, cursor, hasMore := services.TopicService.GetTagTopics(tagId, cursor)
|
||||
return web.JsonCursorData(render.BuildSimpleTopics(topics, user), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
// 收藏
|
||||
func (c *TopicController) GetFavoriteBy(topicId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
err := services.FavoriteService.AddTopicFavorite(user.Id, topicId)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 推荐话题列表(目前逻辑为取最近50条数据随机展示)
|
||||
func (c *TopicController) GetRecommend() *web.JsonResult {
|
||||
topics := cache.TopicCache.GetRecommendTopics()
|
||||
if len(topics) == 0 {
|
||||
return web.JsonSuccess()
|
||||
} else {
|
||||
dest := make([]models.Topic, len(topics))
|
||||
perm := rand.Perm(len(topics))
|
||||
for i, v := range perm {
|
||||
dest[v] = topics[i]
|
||||
}
|
||||
end := 10
|
||||
if end > len(topics) {
|
||||
end = len(topics)
|
||||
}
|
||||
ret := dest[0:end]
|
||||
return web.JsonData(render.BuildSimpleTopics(ret, nil))
|
||||
}
|
||||
}
|
||||
|
||||
// 最新话题
|
||||
func (c *TopicController) GetNewest() *web.JsonResult {
|
||||
topics := services.TopicService.Find(sqls.NewCnd().Eq("status", constants.StatusOk).Desc("id").Limit(6))
|
||||
return web.JsonData(render.BuildSimpleTopics(topics, nil))
|
||||
}
|
||||
|
||||
// 设置置顶
|
||||
func (c *TopicController) PostStickyBy(topicId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if !user.HasAnyRole(constants.RoleOwner, constants.RoleAdmin) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
|
||||
var (
|
||||
sticky = params.FormValueBoolDefault(c.Ctx, "sticky", false) // 是否指定
|
||||
)
|
||||
if err := services.TopicService.SetSticky(topicId, sticky); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *TopicController) GetHide_content() *web.JsonResult {
|
||||
topicId := params.FormValueInt64Default(c.Ctx, "topicId", 0)
|
||||
var (
|
||||
exists = false // 是否有隐藏内容
|
||||
show = false // 是否显示隐藏内容
|
||||
hideContent = "" // 隐藏内容
|
||||
)
|
||||
topic := services.TopicService.Get(topicId)
|
||||
if topic != nil && topic.Status == constants.StatusOk && strs.IsNotBlank(topic.HideContent) {
|
||||
exists = true
|
||||
if user := services.UserTokenService.GetCurrent(c.Ctx); user != nil {
|
||||
if user.Id == topic.UserId || services.CommentService.IsCommented(user.Id, constants.EntityTopic, topic.Id) {
|
||||
show = true
|
||||
hideContent = markdown.ToHTML(topic.HideContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
return web.JsonData(map[string]interface{}{
|
||||
"exists": exists,
|
||||
"show": show,
|
||||
"content": hideContent,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/uploader"
|
||||
"io"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/web"
|
||||
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type UploadController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *UploadController) Post() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if err := services.UserService.CheckPostStatus(user); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
file, header, err := c.Ctx.FormFile("image")
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if header.Size > constants.UploadMaxBytes {
|
||||
return web.JsonErrorMsg("图片不能超过" + strconv.Itoa(constants.UploadMaxM) + "M")
|
||||
}
|
||||
|
||||
contentType := header.Header.Get("Content-Type")
|
||||
fileBytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
|
||||
slog.Info("上传文件:", slog.Any("filename", header.Filename), slog.Any("size", header.Size))
|
||||
|
||||
url, err := uploader.PutImage(fileBytes, contentType)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.NewEmptyRspBuilder().Put("url", url).JsonResult()
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/pkg/msg"
|
||||
"bbs-go/internal/pkg/validate"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/dates"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"bbs-go/internal/cache"
|
||||
"bbs-go/internal/controllers/render"
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/services"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
// 获取当前登录用户
|
||||
func (c *UserController) GetCurrent() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user != nil {
|
||||
return web.JsonData(render.BuildUserProfile(user))
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 用户详情
|
||||
func (c *UserController) GetBy(userId int64) *web.JsonResult {
|
||||
user := cache.UserCache.Get(userId)
|
||||
if user != nil && user.Status != constants.StatusDeleted {
|
||||
return web.JsonData(render.BuildUserDetail(user))
|
||||
}
|
||||
return web.JsonErrorMsg("用户不存在")
|
||||
}
|
||||
|
||||
// 修改用户资料
|
||||
func (c *UserController) PostEditBy(userId int64) *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if user.Id != userId {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
var (
|
||||
nickname = strings.TrimSpace(params.FormValue(c.Ctx, "nickname"))
|
||||
homePage = params.FormValue(c.Ctx, "homePage")
|
||||
description = params.FormValue(c.Ctx, "description")
|
||||
gender = strings.TrimSpace(params.FormValue(c.Ctx, "gender"))
|
||||
birthdayStr = strings.TrimSpace(params.FormValue(c.Ctx, "birthday"))
|
||||
birthday *time.Time
|
||||
err error
|
||||
)
|
||||
|
||||
if len(nickname) == 0 {
|
||||
return web.JsonErrorMsg("昵称不能为空")
|
||||
}
|
||||
|
||||
if strs.IsNotBlank(gender) {
|
||||
if gender != string(constants.GenderMale) && gender != string(constants.GenderFemale) {
|
||||
return web.JsonErrorMsg("性别数据错误")
|
||||
}
|
||||
}
|
||||
if strs.IsNotBlank(birthdayStr) {
|
||||
*birthday, err = dates.Parse(birthdayStr, dates.FmtDate)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(homePage) > 0 && validate.IsURL(homePage) != nil {
|
||||
return web.JsonErrorMsg("个人主页地址错误")
|
||||
}
|
||||
|
||||
columns := map[string]interface{}{
|
||||
"nickname": nickname,
|
||||
"home_page": homePage,
|
||||
"description": description,
|
||||
"gender": gender,
|
||||
}
|
||||
if birthday != nil {
|
||||
columns["birthday"] = birthday
|
||||
}
|
||||
err = services.UserService.Updates(user.Id, columns)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 修改头像
|
||||
func (c *UserController) PostUpdateAvatar() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
avatar := strings.TrimSpace(params.FormValue(c.Ctx, "avatar"))
|
||||
if len(avatar) == 0 {
|
||||
return web.JsonErrorMsg("头像不能为空")
|
||||
}
|
||||
err := services.UserService.UpdateAvatar(user.Id, avatar)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *UserController) PostUpdateNickname() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
nickname := strings.TrimSpace(params.FormValue(c.Ctx, "nickname"))
|
||||
if len(nickname) == 0 {
|
||||
return web.JsonErrorMsg("Nickname cannot be empty")
|
||||
}
|
||||
err := services.UserService.UpdateNickname(user.Id, nickname)
|
||||
if err != nil {
|
||||
return web.JsonErrorMsg(err.Error())
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *UserController) PostUpdateDescription() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
description := strings.TrimSpace(params.FormValue(c.Ctx, "description"))
|
||||
err := services.UserService.UpdateDescription(user.Id, description)
|
||||
if err != nil {
|
||||
return web.JsonErrorMsg(err.Error())
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *UserController) PostUpdateGender() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
gender := strings.TrimSpace(params.FormValue(c.Ctx, "gender"))
|
||||
err := services.UserService.UpdateGender(user.Id, gender)
|
||||
if err != nil {
|
||||
return web.JsonErrorMsg(err.Error())
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
func (c *UserController) PostUpdateBirthday() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
birthday := strings.TrimSpace(params.FormValue(c.Ctx, "birthday"))
|
||||
err := services.UserService.UpdateBirthday(user.Id, birthday)
|
||||
if err != nil {
|
||||
return web.JsonErrorMsg(err.Error())
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 设置用户名
|
||||
func (c *UserController) PostSetUsername() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
username := strings.TrimSpace(params.FormValue(c.Ctx, "username"))
|
||||
err := services.UserService.SetUsername(user.Id, username)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 设置邮箱
|
||||
func (c *UserController) PostSetEmail() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
email := strings.TrimSpace(params.FormValue(c.Ctx, "email"))
|
||||
err := services.UserService.SetEmail(user.Id, email)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
func (c *UserController) PostSetPassword() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
password := params.FormValue(c.Ctx, "password")
|
||||
rePassword := params.FormValue(c.Ctx, "rePassword")
|
||||
err := services.UserService.SetPassword(user.Id, password, rePassword)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
func (c *UserController) PostUpdatePassword() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
var (
|
||||
oldPassword = params.FormValue(c.Ctx, "oldPassword")
|
||||
password = params.FormValue(c.Ctx, "password")
|
||||
rePassword = params.FormValue(c.Ctx, "rePassword")
|
||||
)
|
||||
if err := services.UserService.UpdatePassword(user.Id, oldPassword, password, rePassword); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 设置背景图
|
||||
func (c *UserController) PostSet_background_image() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
backgroundImage := params.FormValue(c.Ctx, "backgroundImage")
|
||||
if strs.IsBlank(backgroundImage) {
|
||||
return web.JsonErrorMsg("请上传图片")
|
||||
}
|
||||
if err := services.UserService.UpdateBackgroundImage(user.Id, backgroundImage); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// 用户收藏
|
||||
func (c *UserController) GetFavorites() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
cursor := params.FormValueInt64Default(c.Ctx, "cursor", 0)
|
||||
|
||||
// 用户必须登录
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
|
||||
// 查询列表
|
||||
limit := 20
|
||||
var favorites []models.Favorite
|
||||
if cursor > 0 {
|
||||
favorites = services.FavoriteService.Find(sqls.NewCnd().Where("user_id = ? and id < ?",
|
||||
user.Id, cursor).Desc("id").Limit(20))
|
||||
} else {
|
||||
favorites = services.FavoriteService.Find(sqls.NewCnd().Where("user_id = ?", user.Id).Desc("id").Limit(limit))
|
||||
}
|
||||
|
||||
hasMore := false
|
||||
if len(favorites) > 0 {
|
||||
cursor = favorites[len(favorites)-1].Id
|
||||
hasMore = len(favorites) >= limit
|
||||
}
|
||||
|
||||
return web.JsonCursorData(render.BuildFavorites(favorites), strconv.FormatInt(cursor, 10), hasMore)
|
||||
}
|
||||
|
||||
// 获取最近3条未读消息
|
||||
func (c *UserController) GetMsgrecent() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
var count int64 = 0
|
||||
var messages []models.Message
|
||||
if user != nil {
|
||||
count = services.MessageService.GetUnReadCount(user.Id)
|
||||
messages = services.MessageService.Find(sqls.NewCnd().Eq("user_id", user.Id).
|
||||
Eq("status", msg.StatusUnread).Limit(3).Desc("id"))
|
||||
}
|
||||
return web.NewEmptyRspBuilder().Put("count", count).Put("messages", render.BuildMessages(messages)).JsonResult()
|
||||
}
|
||||
|
||||
// 用户消息
|
||||
func (c *UserController) GetMessages() *web.JsonResult {
|
||||
user, err := services.UserTokenService.CheckLogin(c.Ctx)
|
||||
if err != nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
var (
|
||||
limit = 20
|
||||
cursor, _ = params.GetInt64(c.Ctx, "cursor")
|
||||
)
|
||||
|
||||
cnd := sqls.NewCnd().Eq("user_id", user.Id).Limit(limit).Desc("id")
|
||||
if cursor > 0 {
|
||||
cnd.Lt("id", cursor)
|
||||
}
|
||||
list := services.MessageService.Find(cnd)
|
||||
|
||||
var (
|
||||
nextCursor = cursor
|
||||
hasMore = false
|
||||
)
|
||||
if len(list) > 0 {
|
||||
nextCursor = list[len(list)-1].Id
|
||||
hasMore = len(list) == limit
|
||||
}
|
||||
|
||||
// 全部标记为已读
|
||||
services.MessageService.MarkRead(user.Id)
|
||||
|
||||
return web.JsonCursorData(render.BuildMessages(list), cast.ToString(nextCursor), hasMore)
|
||||
}
|
||||
|
||||
// 用户积分记录
|
||||
func (c *UserController) GetScore_logs() *web.JsonResult {
|
||||
user, err := services.UserTokenService.CheckLogin(c.Ctx)
|
||||
if err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
var (
|
||||
limit = 20
|
||||
cursor, _ = params.GetInt64(c.Ctx, "cursor")
|
||||
)
|
||||
cnd := sqls.NewCnd().Eq("user_id", user.Id).Limit(limit).Desc("id")
|
||||
if cursor > 0 {
|
||||
cnd.Lt("id", cursor)
|
||||
}
|
||||
list := services.UserScoreLogService.Find(cnd)
|
||||
|
||||
var (
|
||||
nextCursor = cursor
|
||||
hasMore = false
|
||||
)
|
||||
if len(list) > 0 {
|
||||
nextCursor = list[len(list)-1].Id
|
||||
hasMore = len(list) == limit
|
||||
}
|
||||
|
||||
return web.JsonCursorData(list, cast.ToString(nextCursor), hasMore)
|
||||
}
|
||||
|
||||
// 积分排行
|
||||
func (c *UserController) GetScoreRank() *web.JsonResult {
|
||||
users := cache.UserCache.GetScoreRank()
|
||||
var results []*models.UserInfo
|
||||
for _, user := range users {
|
||||
results = append(results, render.BuildUserInfo(&user))
|
||||
}
|
||||
return web.JsonData(results)
|
||||
}
|
||||
|
||||
// 禁言
|
||||
func (c *UserController) PostForbidden() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if !user.HasAnyRole(constants.RoleOwner, constants.RoleAdmin) {
|
||||
return web.JsonErrorMsg("无权限")
|
||||
}
|
||||
var (
|
||||
userId = params.FormValueInt64Default(c.Ctx, "userId", 0)
|
||||
days = params.FormValueIntDefault(c.Ctx, "days", 0)
|
||||
reason = params.FormValue(c.Ctx, "reason")
|
||||
)
|
||||
if userId < 0 {
|
||||
return web.JsonErrorMsg("请传入:userId")
|
||||
}
|
||||
if days == -1 && !user.HasRole(constants.RoleOwner) {
|
||||
return web.JsonErrorMsg("无永久禁言权限")
|
||||
}
|
||||
if days == 0 {
|
||||
services.UserService.RemoveForbidden(user.Id, userId, c.Ctx.Request())
|
||||
} else {
|
||||
if err := services.UserService.Forbidden(user.Id, userId, days, reason, c.Ctx.Request()); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// PostEmailVerify 请求邮箱验证邮件
|
||||
func (c *UserController) PostSend_verify_email() *web.JsonResult {
|
||||
user := services.UserTokenService.GetCurrent(c.Ctx)
|
||||
if user == nil {
|
||||
return web.JsonError(errs.NotLogin)
|
||||
}
|
||||
if err := services.UserService.SendEmailVerifyEmail(user.Id); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
|
||||
// PostVerify_email 获取邮箱验证码
|
||||
func (c *UserController) PostVerify_email() *web.JsonResult {
|
||||
token := params.FormValue(c.Ctx, "token")
|
||||
if strs.IsBlank(token) {
|
||||
return web.JsonErrorMsg("Illegal request")
|
||||
}
|
||||
var (
|
||||
email string
|
||||
err error
|
||||
)
|
||||
if email, err = services.UserService.VerifyEmail(token); err != nil {
|
||||
return web.JsonError(err)
|
||||
}
|
||||
return web.NewEmptyRspBuilder().Put("email", email).JsonResult()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/services"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/dates"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
)
|
||||
|
||||
type UserReportController struct {
|
||||
Ctx iris.Context
|
||||
}
|
||||
|
||||
func (c *UserReportController) PostSubmit() *web.JsonResult {
|
||||
var (
|
||||
dataId, _ = params.FormValueInt64(c.Ctx, "dataId")
|
||||
dataType = params.FormValue(c.Ctx, "dataId")
|
||||
reason = params.FormValue(c.Ctx, "reason")
|
||||
)
|
||||
report := &models.UserReport{
|
||||
DataId: dataId,
|
||||
DataType: dataType,
|
||||
Reason: reason,
|
||||
CreateTime: dates.NowTimestamp(),
|
||||
}
|
||||
|
||||
if user := services.UserTokenService.GetCurrent(c.Ctx); user != nil {
|
||||
report.UserId = user.Id
|
||||
}
|
||||
services.UserReportService.Create(report)
|
||||
return web.JsonSuccess()
|
||||
}
|
||||
Reference in New Issue
Block a user