diff --git a/internal/dao/post.go b/internal/dao/post.go index 290135f2..e7ed83e8 100644 --- a/internal/dao/post.go +++ b/internal/dao/post.go @@ -20,6 +20,11 @@ func (d *Dao) LockPost(post *model.Post) error { return post.Update(d.engine) } +func (d *Dao) StickPost(post *model.Post) error { + post.IsTop = 1 - post.IsTop + return post.Update(d.engine) +} + func (d *Dao) GetPostByID(id int64) (*model.Post, error) { post := &model.Post{ Model: &model.Model{ diff --git a/internal/routers/api/post.go b/internal/routers/api/post.go index 270fb207..a7beaaac 100644 --- a/internal/routers/api/post.go +++ b/internal/routers/api/post.go @@ -266,6 +266,43 @@ func LockPost(c *gin.Context) { }) } +func StickPost(c *gin.Context) { + param := service.PostStickReq{} + response := app.NewResponse(c) + valid, errs := app.BindAndValid(c, ¶m) + if !valid { + global.Logger.Errorf("app.BindAndValid errs: %v", errs) + response.ToErrorResponse(errcode.InvalidParams.WithDetails(errs.Errors()...)) + return + } + + user, _ := c.Get("USER") + svc := service.New(c) + + // 获取Post + postFormated, err := svc.GetPost(param.ID) + if err != nil { + global.Logger.Errorf("svc.GetPost err: %v\n", err) + response.ToErrorResponse(errcode.GetPostFailed) + return + } + + if !user.(*model.User).IsAdmin { + response.ToErrorResponse(errcode.NoPermission) + return + } + err = svc.StickPost(param.ID) + if err != nil { + global.Logger.Errorf("svc.StickPost err: %v\n", err) + response.ToErrorResponse(errcode.LockPostFailed) + return + } + + response.ToResponse(gin.H{ + "top_status": 1 - postFormated.IsTop, + }) +} + func GetPostTags(c *gin.Context) { param := service.PostTagsReq{} response := app.NewResponse(c) diff --git a/internal/routers/router.go b/internal/routers/router.go index 52ee4089..449f3e02 100644 --- a/internal/routers/router.go +++ b/internal/routers/router.go @@ -146,6 +146,9 @@ func NewRouter() *gin.Engine { // 锁定动态 privApi.POST("/post/lock", api.LockPost) + // 置顶动态 + privApi.POST("/post/stick", api.StickPost) + // 发布动态评论 privApi.POST("/post/comment", api.CreatePostComment) diff --git a/internal/service/post.go b/internal/service/post.go index e9ca0942..ea89dbc9 100644 --- a/internal/service/post.go +++ b/internal/service/post.go @@ -42,6 +42,9 @@ type PostDelReq struct { type PostLockReq struct { ID int64 `json:"id" binding:"required"` } +type PostStickReq struct { + ID int64 `json:"id" binding:"required"` +} type PostStarReq struct { ID int64 `json:"id" binding:"required"` } @@ -167,6 +170,18 @@ func (svc *Service) LockPost(id int64) error { return nil } +func (svc *Service) StickPost(id int64) error { + post, _ := svc.dao.GetPostByID(id) + + err := svc.dao.StickPost(post) + + if err != nil { + return err + } + + return nil +} + func (svc *Service) GetPostStar(postID, userID int64) (*model.PostStar, error) { return svc.dao.GetUserPostStar(postID, userID) } diff --git a/pkg/errcode/module_code.go b/pkg/errcode/module_code.go index 8d78aaca..0196d121 100644 --- a/pkg/errcode/module_code.go +++ b/pkg/errcode/module_code.go @@ -33,6 +33,7 @@ var ( DownloadReqError = NewError(30008, "附件下载请求失败") InsuffientDownloadMoney = NewError(30009, "附件下载失败:账户资金不足") DownloadExecFail = NewError(30010, "附件下载失败:扣费失败") + StickPostFailed = NewError(30011, "动态置顶失败") GetCommentsFailed = NewError(40001, "获取评论列表失败") CreateCommentFailed = NewError(40002, "评论发布失败") diff --git a/web/src/api/post.ts b/web/src/api/post.ts index 0c845765..3488eed5 100644 --- a/web/src/api/post.ts +++ b/web/src/api/post.ts @@ -148,6 +148,20 @@ export const lockPost = (data: NetParams.PostLockPost) => { }) as unknown as Promise; }; +/** + * 置顶/取消置顶动态 + * @param {Object} data + * - @param {number} id + * @returns Promise + */ +export const stickPost = (data: NetParams.PostStickPost) => { + return request({ + method: 'post', + url: '/post/stick', + data + }) as unknown as Promise; +}; + /** * 发布动态评论 * @param {Object} data diff --git a/web/src/components/post-detail.vue b/web/src/components/post-detail.vue index 1d22b223..5bfc9a43 100644 --- a/web/src/components/post-detail.vue +++ b/web/src/components/post-detail.vue @@ -59,11 +59,30 @@ :mask-closable="false" preset="dialog" title="提示" - content="确定锁定该泡泡动态吗?" + :content=" + '确定' + + (post.is_lock ? '解锁' : '锁定') + + '该泡泡动态吗?' + " positive-text="确认" negative-text="取消" @positive-click="execLockAction" /> + +
(), {}); +const props = withDefaults( + defineProps<{ + post: Item.PostProps; + }>(), + {} +); const showDelModal = ref(false); const showLockModal = ref(false); +const showStickModal = ref(false); const loading = ref(false); const emit = defineEmits<{ - (e: "reload"): void + (e: 'reload'): void; }>(); const post = computed({ @@ -232,16 +256,17 @@ const adminOptions = computed(() => { }); } if (store.state.userInfo.is_admin) { - options.push( - { + if (post.value.is_top === 0) { + options.push({ label: '置顶', - key: 'top', - }, - { - label: '精华', - key: 'essence', - } - ); + key: 'stick', + }); + } else { + options.push({ + label: '取消置顶', + key: 'unstick', + }); + } } return options; }); @@ -280,13 +305,18 @@ const doClickText = (e: MouseEvent, id: number) => { } goPostDetail(id); }; -const handlePostAction = (item: "delete" | "lock" | "unlock") => { +const handlePostAction = ( + item: 'delete' | 'lock' | 'unlock' | 'stick' | 'unstick' +) => { if (item === 'delete') { showDelModal.value = true; } if (item === 'lock' || item === 'unlock') { showLockModal.value = true; } + if (item === 'stick' || item === 'unstick') { + showStickModal.value = true; + } }; const execDelAction = () => { deletePost({ @@ -320,6 +350,22 @@ const execLockAction = () => { loading.value = false; }); }; +const execStickAction = () => { + stickPost({ + id: post.value.id, + }) + .then((res) => { + emit('reload'); + if (res.top_status === 1) { + window.$message.success('置顶成功'); + } else { + window.$message.success('取消置顶成功'); + } + }) + .catch((err) => { + loading.value = false; + }); +}; const handlePostStar = () => { postStar({ id: post.value.id, diff --git a/web/src/types/NetParams.d.ts b/web/src/types/NetParams.d.ts index 96abf371..435e0ed1 100644 --- a/web/src/types/NetParams.d.ts +++ b/web/src/types/NetParams.d.ts @@ -84,6 +84,10 @@ declare module NetParams { id: number } + interface PostStickPost { + id: number + } + interface PostGetPostStar { id: number } diff --git a/web/src/types/NetReq.d.ts b/web/src/types/NetReq.d.ts index 6f21dc17..606e834f 100644 --- a/web/src/types/NetReq.d.ts +++ b/web/src/types/NetReq.d.ts @@ -17,7 +17,7 @@ declare module NetReq { } type UserGetAttachment = string - + interface UserGetUnreadMsgCount { count: number } @@ -26,7 +26,7 @@ declare module NetReq { list: Item.MessageProps[], pager: Item.PagerProps } - + interface UserGetUserPosts { list: Item.PostProps[], pager: Item.PagerProps @@ -73,6 +73,10 @@ declare module NetReq { lock_status: number } + interface PostStickPost { + top_status: number + } + interface PostGetPostStar { status: boolean } diff --git a/web/src/types/item.d.ts b/web/src/types/item.d.ts index a61da99f..adcebfa4 100644 --- a/web/src/types/item.d.ts +++ b/web/src/types/item.d.ts @@ -46,7 +46,7 @@ declare module Item { content: string, contents: PostProps[], is_lock: number, - is_top: boolean, + is_top: number, texts?: PostProps[], imgs?: PostProps[], videos?: PostProps[],