diff --git a/api/consts/option.go b/api/consts/option.go index 6af6910e..722761eb 100644 --- a/api/consts/option.go +++ b/api/consts/option.go @@ -38,3 +38,13 @@ const ( MediaTypeImg = 1 // 图片 MediaTypeVideo = 2 // 视频 ) + +const ( + ZoneMomentHead_Head = 0 + ZoneMomentHead_UnHead = 1 +) + +const ( + ZoneMomentPriorityInZone_Increment = 2000000000 + ZoneMomentPriorityInZone_Decrement = -2000000000 +) diff --git a/api/proto/zonemoment/proto/moment_vo_api.go b/api/proto/zonemoment/proto/moment_vo_api.go index d772f734..39fdc35d 100644 --- a/api/proto/zonemoment/proto/moment_vo_api.go +++ b/api/proto/zonemoment/proto/moment_vo_api.go @@ -13,6 +13,7 @@ type ApiZoneMomentVO struct { IsIronfanshipUnlocked int64 `json:"is_ironfanship_unlocked"` IsSuperfanshipUnlocked int64 `json:"is_superfanship_unlocked"` IsZoneMomentUnlocked int64 `json:"is_zone_moment_unlocked"` + Expenditure int64 `json:"expenditure"` } func (vo *ApiZoneMomentVO) CopyZoneMoment(zonemoment *dbstruct.ZoneMoment) { diff --git a/api/proto/zonemoment/proto/not_null_def_api.go b/api/proto/zonemoment/proto/not_null_def_api.go index 8e395a4d..83747332 100644 --- a/api/proto/zonemoment/proto/not_null_def_api.go +++ b/api/proto/zonemoment/proto/not_null_def_api.go @@ -35,20 +35,22 @@ func (p *ApiUpdateReq) ProvideNotNullValue() (params []*validator.JsonParam) { params = append(params, validator.NewInt64PtrParam("请确认创建动态的可见范围!", p.ZoneMoment.CType)) params = append(params, validator.NewInt64PtrParam("请确认创建动态的媒体类型!", p.ZoneMoment.MType)) - params = append(params, validator.NewStringPtrParam("请确认创建动态的文案!", p.Text)) - params = append(params, validator.NewStructPtrParam("请确认创建动态的媒体!", p.MediaComp)) switch util.DerefInt64(p.ZoneMoment.CType) { case consts.ZoneMomentCType_Paid: - params = append(params, validator.NewInt64PtrParam("请确认创建动态的文字可见范围!", p.ZoneMoment.TextVisibleRange)) - params = append(params, validator.NewInt64PtrParam("请确认创建动态的价格!", p.ZoneMoment.Price)) - switch util.DerefInt64(p.ZoneMoment.MType) { - case consts.MediaTypeImg: - params = append(params, validator.NewInt64PtrParam("请确认创建动态的媒体可见范围!", p.ZoneMoment.MediaVisibleRange)) - case consts.MediaTypeVideo: - params = append(params, validator.NewInt64PtrParam("请确认创建动态是否要模糊封面!", p.ZoneMoment.IsBlurringCover)) + if p.Text != nil { + params = append(params, validator.NewStringPtrParam("请确认创建动态的文案!", p.Text)) + params = append(params, validator.NewInt64PtrParam("请确认创建动态的文字可见范围!", p.ZoneMoment.TextVisibleRange)) + } + if p.MediaComp != nil { + params = append(params, validator.NewStructPtrParam("请确认创建动态的媒体!", p.MediaComp)) + switch util.DerefInt64(p.ZoneMoment.MType) { + case consts.MediaTypeImg: + params = append(params, validator.NewInt64PtrParam("请确认创建动态的媒体可见范围!", p.ZoneMoment.MediaVisibleRange)) + case consts.MediaTypeVideo: + params = append(params, validator.NewInt64PtrParam("请确认创建动态是否要模糊封面!", p.ZoneMoment.IsBlurringCover)) + } } - } return } diff --git a/api/proto/zonemoment/proto/not_null_def_op.go b/api/proto/zonemoment/proto/not_null_def_op.go index 475f1985..f4515a31 100644 --- a/api/proto/zonemoment/proto/not_null_def_op.go +++ b/api/proto/zonemoment/proto/not_null_def_op.go @@ -34,3 +34,11 @@ func (p *OpReviewReq) ProvideNotNullValue() (params []*validator.JsonParam) { return } + +func (p *OpHeadReq) ProvideNotNullValue() (params []*validator.JsonParam) { + params = make([]*validator.JsonParam, 0) + + params = append(params, validator.NewInt64SliceParam("请确认待审批动态的ids!", p.ZoneMomentIds)) + + return +} diff --git a/api/proto/zonemoment/proto/zonemoment_op.go b/api/proto/zonemoment/proto/zonemoment_op.go index c4f30bfb..835de296 100644 --- a/api/proto/zonemoment/proto/zonemoment_op.go +++ b/api/proto/zonemoment/proto/zonemoment_op.go @@ -171,3 +171,18 @@ type OpReviewResp struct { base.BaseResponse Data *OpReviewData `json:"data"` } + +// op 置顶 +type OpHeadReq struct { + base.BaseRequest + ZoneMomentIds []int64 `json:"zone_moment_ids"` + OpType int64 `json:"op_type"` +} + +type OpHeadData struct { +} + +type OpHeadResp struct { + base.BaseResponse + Data *OpHeadData `json:"data"` +} diff --git a/app/mix/controller/init.go b/app/mix/controller/init.go index 7250abf2..1597fc4f 100644 --- a/app/mix/controller/init.go +++ b/app/mix/controller/init.go @@ -489,6 +489,7 @@ func Init(r *gin.Engine) { opZoneMomentGroup.POST("delete", middleware.JSONParamValidator(zonemomentproto.OpDeleteReq{}), middleware.JwtAuthenticator(), OpDeleteZoneMoment) opZoneMomentGroup.POST("list", middleware.JSONParamValidator(zonemomentproto.OpListReq{}), middleware.JwtAuthenticator(), OpGetZoneMomentList) opZoneMomentGroup.POST("review", middleware.JSONParamValidator(zonemomentproto.OpReviewReq{}), middleware.JwtAuthenticator(), OpReviewZoneMoment) + opZoneMomentGroup.POST("head", middleware.JSONParamValidator(zonemomentproto.OpHeadReq{}), middleware.JwtAuthenticator(), OpHeadZoneMoment) // 账号相关 //accountGroup := r.Group("/account") diff --git a/app/mix/controller/zonemoment_op.go b/app/mix/controller/zonemoment_op.go index 14be0f46..5306aecc 100644 --- a/app/mix/controller/zonemoment_op.go +++ b/app/mix/controller/zonemoment_op.go @@ -91,3 +91,15 @@ func OpReviewZoneMoment(ctx *gin.Context) { ReplyOk(ctx, nil) } + +func OpHeadZoneMoment(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*zonemomentproto.OpHeadReq) + ec := service.DefaultService.OpHeadZoneMoment(ctx, req) + if ec != errcode.ErrCodeZoneMomentSrvOk { + logger.Error("OpHeadZoneMoment fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + ReplyOk(ctx, nil) +} diff --git a/app/mix/dao/mongo.go b/app/mix/dao/mongo.go index 53275475..e6d7a8f4 100644 --- a/app/mix/dao/mongo.go +++ b/app/mix/dao/mongo.go @@ -4069,7 +4069,7 @@ func (m *Mongo) GetZoneMomentListByZid(ctx *gin.Context, req *zonemomentproto.Op if len(ctClause) != 0 { query["ct"] = ctClause } - err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list) + err := col.Find(ctx, query).Sort("-priority_in_zone").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list) if err == qmgo.ErrNoSuchDocuments { err = nil return list, err @@ -4203,6 +4203,23 @@ func (m *Mongo) GetZidsByZoneMomentIds(ctx *gin.Context, zonemomentIds []int64) return zids, err } +func (m *Mongo) IncZoneMomentPriorityByIds(ctx *gin.Context, ids []int64, increment int64) error { + col := m.getColZoneMoment() + query := qmgo.M{ + "_id": qmgo.M{ + "$in": ids, + }, + "del_flag": 0, + } + up := qmgo.M{ + "$inc": qmgo.M{ + "priority_in_zone": increment, + }, + } + _, err := col.UpdateAll(ctx, query, up) + return err +} + // 点赞相关 func (m *Mongo) CreateZoneMomentThumbsUp(ctx *gin.Context, zonemomentthumbsup *dbstruct.ZoneMomentThumbsUp) error { col := m.getColZoneMomentThumbsUp() diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index 26741dae..75786cf9 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -2272,19 +2272,25 @@ func (s *Service) ApiCreateZoneMoment(ctx *gin.Context, req *zonemomentproto.Api func (s *Service) ApiUpdateZoneMoment(ctx *gin.Context, req *zonemomentproto.ApiUpdateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeZoneMomentSrvOk - // 抹消所有审核信息,回退到初始 - req.ZoneMoment.Status = goproto.Int64(consts.ZoneMoment_Auditing) // 正在审核中 - if req.ZoneMoment.MediaComp != nil && len(req.ZoneMoment.MediaComp.GetImageIds()) > 0 { + // 抹消审核信息,回退到初始 + isReauditRequired := false + if req.ZoneMoment.MediaComp != nil && util.DerefInt64(req.ZoneMoment.MType) == consts.MediaTypeImg { + isReauditRequired = true req.ZoneMoment.ImageAuditStatus = goproto.Int64(consts.ImageAudit_Created) // 创建 - } else { - req.ZoneMoment.ImageAuditStatus = goproto.Int64(consts.ImageAudit_Passed) // 视频贴默认已通过 + req.ZoneMoment.ImageAuditOpinion = goproto.String("") // 信息抹除 + } + if req.ZoneMoment.Text != nil { + isReauditRequired = true + req.ZoneMoment.TextAuditStatus = goproto.Int64(consts.TextAudit_Created) // 创建 + req.ZoneMoment.TextAuditOpinion = goproto.String("") // 信息抹除 + } + + if isReauditRequired { + req.ZoneMoment.Status = goproto.Int64(consts.ZoneMoment_Auditing) // 正在审核中 + req.ZoneMoment.ManuallyReviewStatus = goproto.Int64(consts.ZoneMomentManuallyReview_Waiting) // 等待复审 + req.ZoneMoment.ManuallyReviewOpinion = goproto.String("") // 信息抹除 + req.ZoneMoment.ManuallyReviewOperator = goproto.Int64(0) // 信息抹除 } - req.ZoneMoment.TextAuditStatus = goproto.Int64(consts.TextAudit_Created) // 创建 - req.ZoneMoment.ManuallyReviewStatus = goproto.Int64(consts.ZoneMomentManuallyReview_Waiting) // 等待复审 - req.ZoneMoment.ImageAuditOpinion = goproto.String("") // 信息抹除 - req.ZoneMoment.TextAuditOpinion = goproto.String("") // 信息抹除 - req.ZoneMoment.ManuallyReviewOpinion = goproto.String("") // 信息抹除 - req.ZoneMoment.ManuallyReviewOperator = goproto.Int64(0) // 信息抹除 err := _DefaultZoneMoment.OpUpdate(ctx, &zonemomentproto.OpUpdateReq{ BaseRequest: req.BaseRequest, @@ -2405,7 +2411,7 @@ func (s *Service) ApiGetZoneMomentListByVisitorMid(ctx *gin.Context, req *zonemo return } - // 3.初始化返回的volist,获取mids,并将动态基底填充进去 + // 3.填充信息 volist = make([]*zonemomentproto.ApiZoneMomentVO, 0) midSet := make(map[int64]*dbstruct.Moment) mids := make([]int64, 0) @@ -2437,7 +2443,19 @@ func (s *Service) ApiGetZoneMomentListByVisitorMid(ctx *gin.Context, req *zonemo // 6.获取访客已解锁的超粉资格 unlockedSuperfanshipMap := make(map[int64]*int64, 0) - // 7.填充所有信息 + // 7.获取访客创建的空间 + zoneMap, err := _DefaultZone.GetZoneMapByMids(ctx, []int64{req.BaseRequest.Mid}) + if err != nil { + logger.Error("_DefaultZone GetZoneMapByMids fail, req: %v, err: %v", err) + return + } + zones := zoneMap[req.BaseRequest.Mid] + zoneZidMap := make(map[int64]*dbstruct.Zone, 0) + for _, zone := range zones { + zoneZidMap[util.DerefInt64(zone.Id)] = zone + } + + // 8.填充所有信息 for _, vo := range volist { // 主播信息 @@ -2465,7 +2483,7 @@ func (s *Service) ApiGetZoneMomentListByVisitorMid(ctx *gin.Context, req *zonemo } // 是否解锁动态 - s.utilFillIsZoneMomentUnlocked(vo) + s.utilFillIsZoneMomentUnlocked(vo, zoneZidMap) } return @@ -2566,7 +2584,7 @@ func (s *Service) ApiGetZoneMomentListByZid(ctx *gin.Context, req *zonemomentpro } // 是否解锁动态 - s.utilFillIsZoneMomentUnlocked(vo) + s.utilFillIsZoneMomentUnlocked(vo, zoneZidMap) } return @@ -2577,6 +2595,7 @@ func (s *Service) ApiGetZoneMomentListByCreaterMid(ctx *gin.Context, req *zonemo // 1.根据mid查询得到这一轮的动态基底 list, err := _DefaultZoneMoment.OpListByMid(ctx, &zonemomentproto.OpListByMidReq{ + BaseRequest: req.BaseRequest, MType: req.MType, Status: req.Status, CtUpperBound: req.CtUpperBound, @@ -2746,7 +2765,8 @@ func (s *Service) ApiGetZoneThirdPartnerList(ctx *gin.Context, req *zone_third_p return } if zoneThirdPartner == nil { - return &zone_third_partner_proto.ZoneThirdPartnerApiVO{}, errcode.ErrCodeZoneThirdPartnerNotExist + vo = &zone_third_partner_proto.ZoneThirdPartnerApiVO{} + return } account, err := _DefaultAccount.OpListByMid(ctx, &accountproto.OpListByMidReq{ diff --git a/app/mix/service/logic/zonemoment.go b/app/mix/service/logic/zonemoment.go index 3dba196d..6c930bfe 100644 --- a/app/mix/service/logic/zonemoment.go +++ b/app/mix/service/logic/zonemoment.go @@ -36,6 +36,7 @@ func (p *ZoneMoment) OpCreate(ctx *gin.Context, req *zonemomentproto.OpCreateReq req.ZoneMoment.Ct = goproto.Int64(time.Now().Unix()) req.ZoneMoment.Ut = goproto.Int64(time.Now().Unix()) req.ZoneMoment.DelFlag = goproto.Int64(consts.Exist) + req.ZoneMoment.PriorityInZone = req.ZoneMoment.Ct // 优先级默认按创建时间 err = p.store.CreateZoneMoment(ctx, req.ZoneMoment) if err != nil { logger.Error("CreateZoneMoment fail, err: %v", err) @@ -153,3 +154,12 @@ func (p *ZoneMoment) GetZidsByZoneMomentIds(ctx *gin.Context, zonemomentIds []in } return zids, err } + +func (p *ZoneMoment) OpIncPriorityByIds(ctx *gin.Context, ids []int64, increment int64) error { + err := p.store.IncZoneMomentPriorityByIds(ctx, ids, increment) + if err != nil { + logger.Error("IncZoneMomentPriorityByIds fail, err: %v", err) + return err + } + return nil +} diff --git a/app/mix/service/opservice_business_validation.go b/app/mix/service/opservice_business_validation.go index 04e3b1a0..e02924fa 100644 --- a/app/mix/service/opservice_business_validation.go +++ b/app/mix/service/opservice_business_validation.go @@ -1443,3 +1443,19 @@ func (s *Service) OpReviewZoneMomentBusinessValidate(ctx *gin.Context, req *zone } return } + +func (s *Service) OpHeadZoneMomentBusinessValidate(ctx *gin.Context, req *zonemomentproto.OpHeadReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeMomentSrvOk + // 1.业务校验 + result := businessvalidator.NewAuthBusinessValidator(ctx, req). + QueryAccount(_DefaultAccount.OpListByMid). + EnsureAccountExist(). + EnsureIsOpRole(). + Validate(). + Collect() + if ec = result[0].(errcode.ErrCode); ec != errcode.ErrCodeOk { + logger.Error("OpHeadMoment business validation failed") + return + } + return +} diff --git a/app/mix/service/service.go b/app/mix/service/service.go index d84f68e0..100082b0 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -3365,6 +3365,31 @@ func (s *Service) OpReviewZoneMoment(ctx *gin.Context, req *zonemomentproto.OpRe return } +func (s *Service) OpHeadZoneMoment(ctx *gin.Context, req *zonemomentproto.OpHeadReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeZoneMomentSrvOk + + if ec = s.OpHeadZoneMomentBusinessValidate(ctx, req); ec != errcode.ErrCodeZoneMomentSrvOk { + return + } + + incr := int64(0) + if req.OpType == consts.ZoneMomentHead_Head { + incr = consts.ZoneMomentPriorityInZone_Increment + } else { + incr = consts.ZoneMomentPriorityInZone_Decrement + } + + // 更新动态的状态 + err := _DefaultZoneMoment.OpIncPriorityByIds(ctx, req.ZoneMomentIds, incr) + if err != nil { + logger.Error("_DefaultZoneMoment OpIncPriorityByIds fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneMomentSrvFail + return + } + + return +} + // ZoneThirdPartner func (s *Service) OpCreateZoneThirdPartner(ctx *gin.Context, req *zone_third_partner_proto.OpCreateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeZoneThirdPartnerSrvOk diff --git a/app/mix/service/utilservice.go b/app/mix/service/utilservice.go index c6cc6746..ce73b42d 100644 --- a/app/mix/service/utilservice.go +++ b/app/mix/service/utilservice.go @@ -873,7 +873,12 @@ func (s *Service) utilEncryptInaccessibleZoneMoment(vo *zonemomentproto.ApiZoneM } // 填充动态是否解锁 -func (s *Service) utilFillIsZoneMomentUnlocked(vo *zonemomentproto.ApiZoneMomentVO) { +func (s *Service) utilFillIsZoneMomentUnlocked(vo *zonemomentproto.ApiZoneMomentVO, zoneZidMap map[int64]*dbstruct.Zone) { + // 若动态在本人创建的空间内,则必然解锁 + if zoneZidMap[util.DerefInt64(vo.ZoneMoment.Zid)] != nil { + vo.SetIsZoneMomentUnlocked(consts.IsZoneMomentUnlocked_Yes) + return + } switch util.DerefInt64(vo.ZoneMoment.CType) { case consts.ZoneMomentCType_Free: vo.SetIsZoneMomentUnlocked(consts.IsZoneMomentUnlocked_Yes) @@ -1523,10 +1528,11 @@ func (s *Service) utilFillZonesWithApiVOInfo(ctx *gin.Context, list []*dbstruct. func (s *Service) utilGetZonePreviews(ctx *gin.Context, zid int64) (previews *dbstruct.MediaComponent, err error) { list, err := _DefaultZoneMoment.OpListByZid(ctx, &zonemomentproto.OpListByZidReq{ - Zid: goproto.Int64(zid), - MType: goproto.Int64(consts.MediaTypeImg), - CType: goproto.Int64(consts.ZoneMomentCType_Free), - Limit: 4, + Zid: goproto.Int64(zid), + MType: goproto.Int64(consts.MediaTypeImg), + CType: goproto.Int64(consts.ZoneMomentCType_Free), + Status: goproto.Int64(consts.ZoneMoment_Public), + Limit: 4, }) if err != nil { logger.Error("_DefaultZoneMoment OpListByZid fail, req: %v, err: %v", err) diff --git a/dbstruct/zonemoment.go b/dbstruct/zonemoment.go index 635f5699..a26adc32 100644 --- a/dbstruct/zonemoment.go +++ b/dbstruct/zonemoment.go @@ -27,6 +27,7 @@ type ZoneMoment struct { TextAuditOpinion *string `json:"text_audit_opinion" bson:"text_audit_opinion"` // 文字审核意见 ManuallyReviewOpinion *string `json:"manually_review_opinion" bson:"manually_review_opinion"` // 人工复审意见 ManuallyReviewOperator *int64 `json:"manually_review_operator" bson:"manually_review_operator"` // 人工复审操作人 + PriorityInZone *int64 `json:"priority_in_zone" bson:"priority_in_zone"` // 优先级 Ct *int64 `json:"ct" bson:"ct"` // 创建时间 Ut *int64 `json:"ut" bson:"ut"` // 更新时间 DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记