diff --git a/api/proto/streamer/proto/streamer_api.go b/api/proto/streamer/proto/streamer_api.go index b518bd91..d36ae003 100644 --- a/api/proto/streamer/proto/streamer_api.go +++ b/api/proto/streamer/proto/streamer_api.go @@ -78,9 +78,11 @@ type ApiListExtByMidReq struct { } type ApiListExtByMidData struct { - StreamerExt *ApiListExtVO `json:"streamer_ext"` - WechatLockType int32 `json:"wechat_lock_type"` // 微信解锁类型 - IsUnlockWechat int32 `json:"is_unlock_wechat"` // 是否解锁微信 + StreamerExt *ApiListExtVO `json:"streamer_ext"` + WechatLockType int32 `json:"wechat_lock_type"` // 微信解锁类型 + IsUnlockWechat int32 `json:"is_unlock_wechat"` // 是否解锁微信 + WechatOrderId string `json:"wechat_order_id"` // 微信订单id + WechatOrderStatus int32 `json:"wechat_order_status"` // 微信订单状态 } type ApiListExtByMidResp struct { diff --git a/api/proto/zone/proto/zone_api.go b/api/proto/zone/proto/zone_api.go index 846d0728..f4058810 100644 --- a/api/proto/zone/proto/zone_api.go +++ b/api/proto/zone/proto/zone_api.go @@ -3,6 +3,7 @@ package proto import ( "service/api/base" "service/dbstruct" + "service/library/payclients/wxpaycli" ) // op 创建 @@ -92,9 +93,10 @@ type ApiListByMidReq struct { } type ApiListByMidData struct { - List []*ApiZoneVO `json:"list"` - Offset int `json:"offset"` - More int `json:"more"` + List []*ApiZoneVO `json:"list"` + Offset int `json:"offset"` + More int `json:"more"` + RefundEnable int `json:"refund_enable"` // 1: 能退款,0: 不能退款 } type ApiListByMidResp struct { @@ -138,3 +140,77 @@ type OpListByMidResp struct { base.BaseResponse Data *OpListByMidData `json:"data"` } + +// 空间收银台 +type ZoneGetCashierReq struct { + Zid int64 `json:"zid"` // 空间id + MomentId int64 `json:"moment_id"` // 动态id + ProductId string `json:"product_id"` // 商品id,ProductIdH5Zone* +} + +type ZoneGetCashierData struct { + Name string `json:"name"` // 商品名 + Price int64 `json:"price"` // 价格,单位: 分 + Validity string `json:"validity"` // 有效期,直接展示就行,"30天"、"永久" + IsSuperfanshipGiveWechat int `json:"is_superfanship_give_wechat"` // 是否开启超粉空间赠送微信 0: 不赠送, 1: 赠送 +} + +type ZoneGetCashierResp struct { + base.BaseResponse + Data *ZoneGetCashierData `json:"data"` +} + +// 空间创建订单 +type ZoneCreateOrderReq struct { + base.BaseRequest + Zid int64 `json:"zid"` // 空间id + MomentId int64 `json:"moment_id"` // 动态id + ProductId string `json:"product_id"` // 商品id,ProductIdH5Zone* + PayType string `json:"pay_type"` // 支付方式 + From string `json:"from"` // 来源 + WechatAuthCode string `json:"wechat_auth_code"` // 微信auth_code +} + +type ZoneCreateOrderData struct { + OrderId string `json:"order_id"` // 订单id + AlipayParamStr string `json:"alipay_param_str"` // 支付宝 app支付参数 + AlipayH5ParamStr string `json:"alipay_h5_param_str"` // 支付宝 h5支付参数 + WxpayNativeParamStr string `json:"wxpay_native_param_str"` // 微信支付 native支付参数 + WxpayJsapiParamObj wxpaycli.JsapiPayResp `json:"wxpay_jsapi_param_obj"` // 微信支付 jsapi支付参数 + WxpayH5ParamStr string `json:"wxpay_h5_param_str"` // 微信支付 h5支付参数 +} + +type ZoneCreateOrderResp struct { + base.BaseResponse + Data *ZoneCreateOrderData `json:"data"` +} + +// 空间退款页面 +type ZoneRefundPageReq struct { + Zid int64 `json:"zid"` // 空间id +} + +type ZoneRefundPageData struct { + Price int64 `json:"price"` // 退款价格,单位:分 + Name string `json:"name"` // 退款商品名 +} + +type ZoneRefundPageResp struct { + base.BaseResponse + Data *ZoneRefundPageData `json:"data"` +} + +// 空间退款 +type ZoneRefundReq struct { + Zid int64 `json:"zid"` // 空间id + ContactName string `json:"contact_name"` // 联系人 + ContactPhone string `json:"contact_phone"` // 联系电话 + Note string `json:"note"` // 备注 +} + +type ZoneRefundData struct{} + +type ZoneRefundResp struct { + base.BaseResponse + Data *ZoneRefundData `json:"data"` +} diff --git a/api/proto/zonemoment/proto/moment_vo_api.go b/api/proto/zonemoment/proto/moment_vo_api.go index 39fdc35d..cecfc810 100644 --- a/api/proto/zonemoment/proto/moment_vo_api.go +++ b/api/proto/zonemoment/proto/moment_vo_api.go @@ -14,6 +14,7 @@ type ApiZoneMomentVO struct { IsSuperfanshipUnlocked int64 `json:"is_superfanship_unlocked"` IsZoneMomentUnlocked int64 `json:"is_zone_moment_unlocked"` Expenditure int64 `json:"expenditure"` + BuyerCnt int64 `json:"buyer_cnt"` // 动态购买人数 } func (vo *ApiZoneMomentVO) CopyZoneMoment(zonemoment *dbstruct.ZoneMoment) { diff --git a/app/mix/dao/mongo.go b/app/mix/dao/mongo.go index 5570cb49..7e3ae2e9 100644 --- a/app/mix/dao/mongo.go +++ b/app/mix/dao/mongo.go @@ -3823,6 +3823,19 @@ func (m *Mongo) GetZoneById(ctx *gin.Context, id int64) (*dbstruct.Zone, error) return zone, err } +func (m *Mongo) RecordZoneStatisticsById(ctx *gin.Context, id int64, zoneMomentCount int64, imageCount int64, videoCount int64) error { + col := m.getColZone() + up := qmgo.M{ + "$inc": qmgo.M{ + "zone_moment_count": zoneMomentCount, + "image_count": imageCount, + "video_count": videoCount, + }, + } + err := col.UpdateId(ctx, id, up) + return err +} + // 私密圈动态相关 func (m *Mongo) CreateZoneMoment(ctx *gin.Context, zonemoment *dbstruct.ZoneMoment) error { col := m.getColZoneMoment() diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index aae29fae..c720e42c 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -2272,6 +2272,17 @@ 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 + zonemoment, err := _DefaultZoneMoment.GetById(ctx, util.DerefInt64(req.Id)) + if err != nil { + logger.Error("_DefaultZoneMoment GetById fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneMomentSrvFail + return + } + if zonemoment == nil { + ec = errcode.ErrCodeZoneMomentNotExist + return + } + // 抹消审核信息,回退到初始 isReauditRequired := false if req.ZoneMoment.MediaComp != nil && util.DerefInt64(req.ZoneMoment.MType) == consts.MediaTypeImg { @@ -2292,7 +2303,7 @@ func (s *Service) ApiUpdateZoneMoment(ctx *gin.Context, req *zonemomentproto.Api req.ZoneMoment.ManuallyReviewOperator = goproto.Int64(0) // 信息抹除 } - err := _DefaultZoneMoment.OpUpdate(ctx, &zonemomentproto.OpUpdateReq{ + err = _DefaultZoneMoment.OpUpdate(ctx, &zonemomentproto.OpUpdateReq{ BaseRequest: req.BaseRequest, ZoneMoment: req.ZoneMoment, }) @@ -2307,6 +2318,19 @@ func (s *Service) ApiUpdateZoneMoment(ctx *gin.Context, req *zonemomentproto.Api return } + // 回退空间内统计总数 + if isReauditRequired { + id := util.DerefInt64(req.ZoneMoment.Id) + mediaCountInc := len(zonemoment.MediaComp.GetImageIds()) + videoCountInc := len(zonemoment.MediaComp.GetVideoIds()) + err := _DefaultZone.RecordStatisticsById(ctx, id, -1, -int64(mediaCountInc), -int64(videoCountInc)) + if err != nil { + logger.Error("RecordStatisticsById fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneSrvFail + return + } + } + // 添加审核任务 imageaudittasks := s.CreateZoneMomentImageAudit(ctx, req.ZoneMoment) textaudittasks := s.CreateZoneMomentTextAudit(ctx, req.ZoneMoment) diff --git a/app/mix/service/logic/zone.go b/app/mix/service/logic/zone.go index bd81d63f..17046e16 100644 --- a/app/mix/service/logic/zone.go +++ b/app/mix/service/logic/zone.go @@ -108,6 +108,15 @@ func (p *Zone) OpUpdateByIdAndLastZoneMomentCt(ctx *gin.Context, req *zoneproto. return nil } +func (p *Zone) RecordStatisticsById(ctx *gin.Context, id int64, zoneMomentCount int64, imageCount int64, videoCount int64) error { + err := p.store.RecordZoneStatisticsById(ctx, id, zoneMomentCount, imageCount, videoCount) + if err != nil { + logger.Error("RecordZoneStatisticsById fail, err: %v", err) + return err + } + return err +} + func (p *Zone) GetById(ctx *gin.Context, id int64) (*dbstruct.Zone, error) { zone, err := p.store.GetZoneById(ctx, id) if err != nil { diff --git a/app/mix/service/service.go b/app/mix/service/service.go index 2bb12993..7017c2fd 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -3292,6 +3292,16 @@ func (s *Service) OpDeleteZoneMoment(ctx *gin.Context, req *zonemomentproto.OpDe } } + // 回退空间内统计总数 + id := util.DerefInt64(req.Id) + mediaCountInc := len(zonemoment.MediaComp.GetImageIds()) + videoCountInc := len(zonemoment.MediaComp.GetVideoIds()) + err = _DefaultZone.RecordStatisticsById(ctx, id, -1, -int64(mediaCountInc), -int64(videoCountInc)) + if err != nil { + logger.Error("RecordStatisticsById fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneSrvFail + return + } return } @@ -3360,6 +3370,28 @@ func (s *Service) OpReviewZoneMoment(ctx *gin.Context, req *zonemomentproto.OpRe ec = errcode.ErrCodeZoneMomentSrvFail return } + + // 增加空间内统计总数 + for _, id := range req.ZoneMomentIds { + zonemoment, err := _DefaultZoneMoment.GetById(ctx, id) + if err != nil { + logger.Error("_DefaultZoneMoment GetById fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneMomentSrvFail + return + } + if zonemoment == nil { + ec = errcode.ErrCodeZoneMomentNotExist + return + } + mediaCountInc := len(zonemoment.MediaComp.GetImageIds()) + videoCountInc := len(zonemoment.MediaComp.GetVideoIds()) + err = _DefaultZone.RecordStatisticsById(ctx, id, 1, int64(mediaCountInc), int64(videoCountInc)) + if err != nil { + logger.Error("RecordStatisticsById fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeZoneSrvFail + return + } + } } return diff --git a/dbstruct/product.go b/dbstruct/product.go index 5a54cd08..01b7230d 100644 --- a/dbstruct/product.go +++ b/dbstruct/product.go @@ -20,6 +20,11 @@ const ( ProductIdMembership = "membership" // 会员 ProductIdH5Membership = "h5_membership" // 会员 + + ProductIdH5ZoneMoment = "h5_zone_moment" // 空间动态 + ProductIdH5ZoneAdmission = "h5_zone_admission" // 空间普通会员 + ProductIdH5ZoneIronfanship = "h5_zone_ironfanship" // 空间铁粉 + ProductIdH5ZoneSuperfanship = "h5_zone_superfanship" // 空间超粉 ) // 商品类型 diff --git a/dbstruct/vas_mysql.go b/dbstruct/vas_mysql.go index 04656f05..0b1d5303 100644 --- a/dbstruct/vas_mysql.go +++ b/dbstruct/vas_mysql.go @@ -891,3 +891,34 @@ func (p *UserVasMembershipUnlock) GetOrderId() string { } return "" } + +const ( + ZoneMemberTypeNormal = 1 // 普通会员 + ZoneMemberTypeIronfan = 2 // 铁粉 + ZoneMemberTypeSuperfan = 3 // 超粉 +) + +// 用户解锁空间详情 +type ZoneUnlock struct { + Id *int64 `json:"id"` + Mid *int64 `json:"mid"` // 用户mid + Zid *int64 `json:"zid"` // 空间id + Consume *int64 `json:"consume"` // 空间总消费 + AdmissionCt *int64 `json:"admission_ct"` // 普通会员开通时间 + AdmissionUntil *int64 `json:"admission_until"` // 普通会员到期时间,时间戳,-1: 永久 + AdmissionOrderId *string `json:"admission_order_id"` // 普通会员订单 + IronfanshipCt *int64 `json:"ironfanship_ct"` // 铁粉开通时间id + IronfanshipUntil *int64 `json:"ironfanship_until"` // 铁粉到期时间,时间戳,-1:永久 + IronfanshipOrderId *string `json:"ironfanship_order_id"` // 铁粉订单 + SuperfanCt *int64 `json:"superfan_ct"` // 超粉开通时间id + SuperfanshipUntil *int64 `json:"superfanship_until"` // 超粉到期时间,时间戳,-1:永久 + SuperfanshipOrderId *string `json:"superfanship_order_id"` // 超粉订单id +} + +// 空间成员列表 +type ZoneMember struct { + Zid *int64 `json:"zid" bson:"zid"` // 空间id + Mid *int64 `json:"mid" bson:"mid"` // 用户id + MemberType *int32 `json:"member_type" bson:"member_type"` // 空间成员类型 ZoneMemberType* + Ct *int64 `json:"ct" bson:"ct"` // 成为成员的时间 +} diff --git a/dbstruct/zone.go b/dbstruct/zone.go index 9d1bf975..29fb813a 100644 --- a/dbstruct/zone.go +++ b/dbstruct/zone.go @@ -5,7 +5,38 @@ type Zone struct { Mid *int64 `json:"mid" bson:"mid"` // 用户表id Profile *string `json:"profile" bson:"profile"` // 空间简介 LastZoneMomentCt *int64 `json:"last_zone_moment_ct" bson:"last_zone_moment_ct"` // 最后空间动态创建时间 + ZoneMomentCount *int64 `json:"zone_moment_count" bson:"zone_moment_count"` // 空间内动态总数 + ImageCount *int64 `json:"image_count" bson:"image_count"` // 空间内图片总数 + VideoCount *int64 `json:"video_count" bson:"video_count"` // 空间内视频总数 Ct *int64 `json:"ct" bson:"ct"` // 创建时间 Ut *int64 `json:"ut" bson:"ut"` // 更新时间 DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记 } + +const ( + SuperfanshipValidPeriodEternal = 0 // 永久生效 + SuperfanshipValidPeriodMonth = 1 // 30d + SuperfanshipValidPeriodSeason = 2 // 90d + SuperfanshipValidPeriodHalfYear = 3 // 180d + SuperfanshipValidPeriodYear = 4 // 366d +) + +// 空间增值相关,空间价格等 +type ZoneVas struct { + Zid int64 `json:"zid" bson:"_id"` + Mid int64 `json:"mid" bson:"mid"` // 主播mid + AdmissionPrice int64 `json:"admission_price" bson:"admission_price"` // 空间解锁价格, 单位: 分 + IronfanshipPrice int64 `json:"ironfanship_price" bson:"ironfanship_price"` // 铁粉解锁价格, 单位: 分 + IsSuperfanshipEnabled int `json:"is_superfanship_enabled" bson:"is_superfanship_enabled"` // 是否开启超粉空间 0: 关闭, 1: 开启 + SuperfanshipPrice int64 `json:"superfanship_price" bson:"superfanship_price"` // 超粉价格, 单位: 分 + SuperfanshipValidPeriod int `json:"superfanship_valid_period" bson:"superfanship_valid_period"` // 超粉有效期类型, SuperfanshipValidPeriod* + IsSuperfanshipGiveWechat int `json:"is_superfanship_give_wechat" bson:"is_superfanship_give_wechat"` // 是否开启超粉空间赠送微信 0: 不赠送, 1: 赠送 +} + +// 空间动态价格 +type ZoneMomentPrice struct { + Id int64 `json:"id" bson:"_id"` // 动态id + Zid int64 `json:"zid" bson:"zid"` // 空间id + Mid int64 `json:"mid" bson:"mid"` // 主播mid + Price int64 `json:"price" bson:"price"` // 动态价格,单位:分 +}