From 7a9b9d0fc540a6b1238626ad13638e91f61a784f Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Wed, 9 Aug 2023 15:37:55 +0800 Subject: [PATCH] feat(controller, poll): poll --- api/poll/v1/cancel.go | 4 +- api/poll/v1/poll.go | 6 +-- internal/controller/poll/poll_v1_poll.go | 65 +++++++++++++++++++++++- internal/logic/poll/convert.go | 10 ++++ internal/logic/poll/poll.go | 2 +- internal/service/poll.go | 4 ++ 6 files changed, 84 insertions(+), 7 deletions(-) diff --git a/api/poll/v1/cancel.go b/api/poll/v1/cancel.go index bb68a2b..edbb837 100644 --- a/api/poll/v1/cancel.go +++ b/api/poll/v1/cancel.go @@ -6,8 +6,8 @@ import ( ) type CancelPollReq struct { - g.Meta `path:"/poll/cancel" tags:"Poll" method:"delete" summary:"取消投票"` - SentenceUUID string `json:"sentence_uuid" dc:"句子 UUID" v:"required|size:36"` + g.Meta `path:"/poll/:id/cancel" tags:"Poll" method:"delete" summary:"取消投票"` + ID int `json:"id" dc:"投票 ID" v:"required|min:1#请输入投票 ID"` } type CancelPollRes struct { diff --git a/api/poll/v1/poll.go b/api/poll/v1/poll.go index 6437588..3e1c3c3 100644 --- a/api/poll/v1/poll.go +++ b/api/poll/v1/poll.go @@ -7,10 +7,10 @@ import ( type PollReq struct { g.Meta `path:"/poll/:id" tags:"Poll" method:"put" summary:"投票"` - ID uint `json:"id" dc:"投票ID" v:"required|uint" in:"path"` + ID int `json:"id" dc:"投票ID" v:"required|int" in:"path"` Method consts.PollMethod `json:"method" dc:"投票方式" v:"required|enums"` - MarkID uint `json:"mark_id" dc:"标记" v:"required-unless:method,1"` - Comment string `json:"comment" dc:"理由" v:"required-if:method,2,3|length:1,255"` + MarkIDs []int `json:"mark_ids" dc:"标记"` + Comment string `json:"comment" dc:"理由" v:"length:1,255"` } // PollRes 成功返回句子的投票记录 diff --git a/internal/controller/poll/poll_v1_poll.go b/internal/controller/poll/poll_v1_poll.go index 3c30fdd..c73c00e 100644 --- a/internal/controller/poll/poll_v1_poll.go +++ b/internal/controller/poll/poll_v1_poll.go @@ -3,6 +3,13 @@ package poll import ( "context" + "github.com/hitokoto-osc/reviewer/internal/consts" + "github.com/hitokoto-osc/reviewer/internal/model" + "github.com/hitokoto-osc/reviewer/internal/model/entity" + "golang.org/x/sync/errgroup" + + "github.com/hitokoto-osc/reviewer/internal/service" + "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" @@ -10,5 +17,61 @@ import ( ) func (c *ControllerV1) Poll(ctx context.Context, req *v1.PollReq) (res *v1.PollRes, err error) { - return nil, gerror.NewCode(gcode.CodeNotImplemented) + if req.Method != consts.PollMethodApprove && req.Comment == "" && len(req.MarkIDs) == 0 { // 因为验证器规则太简单了,所以这里需要手动判断 + return nil, gerror.NewCode(gcode.CodeInvalidOperation, "请至少选择一个标记或者填写理由。") + } + + var ( + poll *entity.Poll + polledData *model.PolledData + ) + user := service.BizCtx().GetUser(ctx) + eg, egCtx := errgroup.WithContext(ctx) + eg.Go(func() error { + var e error + poll, e = service.Poll().GetPollByID(egCtx, req.ID) + return e + }) + eg.Go(func() error { + var e error + polledData, e = service.User().GetUserPolledDataWithPollID(egCtx, user.Id, uint(req.ID)) + return e + }) + err = eg.Wait() + if err != nil { + return nil, err + } else if poll == nil { + return nil, gerror.NewCode(gcode.CodeNotFound, "投票不存在") + } + if polledData != nil { + return nil, gerror.NewCode(gcode.CodeOperationFailed, "您已经投过票了,请勿重复投票!") + } + if poll.Status != int(consts.PollStatusOpen) { + return nil, gerror.NewCode(gcode.CodeOperationFailed, "该投票未开放投票。") + } + + sentence, err := service.Hitokoto().GetHitokotoV1SchemaByUUID(ctx, poll.SentenceUuid) + if err != nil { + return nil, gerror.WrapCode(gcode.CodeInternalError, err, "获取句子信息失败") + } else if sentence == nil { + return nil, gerror.NewCode(gcode.CodeNotFound, "句子不存在") + } + if sentence.CreatorUID == user.Id && req.Method == consts.PollMethodApprove { + return nil, gerror.NewCode(gcode.CodeOperationFailed, "您不能给自己提交的句子投赞成票。") + } + points := service.Poll().GetPointsByRole(user.Role) + err = service.Poll().Poll(ctx, &model.PollInput{ + Method: req.Method, + Point: int(points), + PollID: uint(req.ID), + SentenceUUID: poll.SentenceUuid, + Comment: req.Comment, + UserID: user.Id, + IsAdmin: user.Role == consts.UserRoleAdmin, + Marks: req.MarkIDs, + }) + if err != nil { + return nil, gerror.WrapCode(gcode.CodeOperationFailed, err, "投票失败:") + } + return nil, nil } diff --git a/internal/logic/poll/convert.go b/internal/logic/poll/convert.go index c104953..f114724 100644 --- a/internal/logic/poll/convert.go +++ b/internal/logic/poll/convert.go @@ -15,3 +15,13 @@ var pollMethodsMap = map[consts.PollMethod]string{ func translatePollMethodToField(in consts.PollMethod) string { return pollMethodsMap[in] } + +var pointsMap = map[consts.UserRole]consts.UserPollPoints{ + consts.UserRoleUser: consts.UserPollPointsNormal, + consts.UserRoleReviewer: consts.UserPollPointsReviewer, + consts.UserRoleAdmin: consts.UserPollPointsAdmin, +} + +func (s *sPoll) GetPointsByRole(role consts.UserRole) consts.UserPollPoints { + return pointsMap[role] +} diff --git a/internal/logic/poll/poll.go b/internal/logic/poll/poll.go index d645716..d9566d1 100644 --- a/internal/logic/poll/poll.go +++ b/internal/logic/poll/poll.go @@ -203,7 +203,7 @@ func (s *sPoll) GetPollList(ctx context.Context, in *model.GetPollListInput) (*m } // Poll 投票 -func Poll(ctx context.Context, in *model.PollInput) error { +func (s *sPoll) Poll(ctx context.Context, in *model.PollInput) error { if in == nil { return gerror.New("input is empty") } diff --git a/internal/service/poll.go b/internal/service/poll.go index 048dba2..cd39693 100644 --- a/internal/service/poll.go +++ b/internal/service/poll.go @@ -8,18 +8,22 @@ package service import ( "context" + "github.com/hitokoto-osc/reviewer/internal/consts" "github.com/hitokoto-osc/reviewer/internal/model" "github.com/hitokoto-osc/reviewer/internal/model/entity" ) type ( IPoll interface { + GetPointsByRole(role consts.UserRole) consts.UserPollPoints GetPollByID(ctx context.Context, pid int) (poll *entity.Poll, err error) // GetPollBySentenceUUID 根据 Sentence UUID 获取最新发起的投票 GetPollBySentenceUUID(ctx context.Context, sentenceUUID string) (poll *entity.Poll, err error) CountOpenedPoll(ctx context.Context) (int, error) CreatePollByPending(ctx context.Context, pending *entity.Pending) (*entity.Poll, error) GetPollList(ctx context.Context, in *model.GetPollListInput) (*model.GetPollListOutput, error) + // Poll 投票 + Poll(ctx context.Context, in *model.PollInput) error GetPollLogsBySentenceUUID(ctx context.Context, uuid string) ([]entity.PollLog, error) GetPollLogsByPollID(ctx context.Context, pid int) ([]entity.PollLog, error) GetPollMarkLabels(ctx context.Context) ([]entity.PollMark, error)