diff --git a/api/consts/consts.go b/api/consts/consts.go index 41a49929..e57671e4 100644 --- a/api/consts/consts.go +++ b/api/consts/consts.go @@ -92,8 +92,9 @@ const ( // redis键前缀 const ( - RedisStreamerPrefix = "streamer:" //streamer服务前缀 - RedisMomentPrefix = "moment:" //moment服务前缀 + RedisStreamerPrefix = "streamer:" //streamer服务前缀 + RedisMomentPrefix = "moment:" //moment服务前缀 + RedisNotificationPrefix = "notification:" //notification服务前缀 ) //const PackageRootPath = "C:/Users/PC/Desktop/service" diff --git a/api/consts/status.go b/api/consts/status.go index 51556664..80018f05 100644 --- a/api/consts/status.go +++ b/api/consts/status.go @@ -321,3 +321,9 @@ const ( VideoManuallyReview_Passed = 1 //已复审通过 VideoManuallyReview_Rejected = 2 //已复审拒绝 ) + +// 系统通知表的已读状态 +const ( + Notification_NotRead = 0 //未读 + Notification_Read = 1 //已读 +) diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index d7f266f0..c7c9f93a 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -249,6 +249,10 @@ var ErrCodeMsgMap = map[ErrCode]string{ ErrCodeEmailSrvFail: "电子邮件表服务错误", ErrCodeEmailNotExist: "电子邮件表不存在", + ErrCodeNotificationSrvFail: "系统通知表服务错误", + ErrCodeNotificationNotExist: "系统通知表不存在", + ErrCodeNotificationCountRedisCacheInvalid: "系统通知表redis缓存失效", + ErrCodeRavenIQTestSrvFail: "瑞文智商测试表服务错误", ErrCodeRavenIQTestNotExist: "瑞文智商测试表不存在", ErrCodeRavenIQTestQuestionNotExist: "瑞文智商测试表题目不存在", @@ -593,6 +597,12 @@ const ( ErrCodeEmailSrvFail ErrCode = -45001 // 电子邮件表服务错误 ErrCodeEmailNotExist ErrCode = -45002 // 电子邮件表不存在 + // Notification: 45xxx + ErrCodeNotificationSrvOk ErrCode = ErrCodeOk + ErrCodeNotificationSrvFail ErrCode = -45001 // 系统通知表服务错误 + ErrCodeNotificationNotExist ErrCode = -45002 // 系统通知表不存在 + ErrCodeNotificationCountRedisCacheInvalid ErrCode = -45003 // 系统通知表redis缓存失效 + // Media: 60xxx ErrCodeMediaSrvOk ErrCode = ErrCodeOk ErrCodeMediaSrvFail ErrCode = -60001 // 媒体服务错误 diff --git a/api/proto/notification/proto/notification_api.go b/api/proto/notification/proto/notification_api.go new file mode 100644 index 00000000..f56fb3d6 --- /dev/null +++ b/api/proto/notification/proto/notification_api.go @@ -0,0 +1,52 @@ +package proto + +import ( + "service/api/base" + "service/dbstruct" +) + +// op 列表 +type ApiListUnreadByMidReq struct { + base.BaseRequest + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +type ApiListUnreadByMidData struct { + List []*dbstruct.Notification `json:"list"` + Offset int `json:"offset"` + More int `json:"more"` +} + +type ApiListUnreadByMidResp struct { + base.BaseResponse + Data *ApiListUnreadByMidData `json:"data"` +} + +// op 列表 +type ApiCountUnreadByMidReq struct { + base.BaseRequest +} + +type ApiCountUnreadByMidData struct { + UnreadCount int64 `json:"unread_count"` +} + +type ApiCountUnreadByMidResp struct { + base.BaseResponse + Data *ApiCountUnreadByMidData `json:"data"` +} + +// op 更新 +type ApiReadReq struct { + base.BaseRequest + Ids []int64 +} + +type ApiReadData struct { +} + +type ApiReadResp struct { + base.BaseResponse + Data *ApiReadData `json:"data"` +} diff --git a/api/proto/notification/proto/notification_op.go b/api/proto/notification/proto/notification_op.go new file mode 100644 index 00000000..4bcca8d0 --- /dev/null +++ b/api/proto/notification/proto/notification_op.go @@ -0,0 +1,68 @@ +package proto + +import ( + "service/api/base" + "service/dbstruct" +) + +// op 创建 +type OpCreateReq struct { + base.BaseRequest + *dbstruct.Notification +} + +type OpCreateData struct { +} + +type OpCreateResp struct { + base.BaseResponse + Data *OpCreateData `json:"data"` +} + +// op 删除 +type OpDeleteReq struct { + base.BaseRequest + Id int64 `json:"id"` +} + +type OpDeleteData struct { +} + +type OpDeleteResp struct { + base.BaseResponse + Data *OpDeleteData `json:"data"` +} + +// op 更新 +type OpUpdateReq struct { + base.BaseRequest + *dbstruct.Notification +} + +type OpUpdateData struct { +} + +type OpUpdateResp struct { + base.BaseResponse + Data *OpUpdateData `json:"data"` +} + +// op 列表 +type OpListByMidReq struct { + base.BaseRequest + Uid *int64 `json:"mid"` + IsRead *int64 `json:"is_read"` + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +type OpListByMidData struct { + List []*dbstruct.Notification `json:"list"` + Offset int `json:"offset"` + More int `json:"more"` +} + +type OpListByMidResp struct { + base.BaseResponse + Data *OpListByMidData `json:"data"` +} diff --git a/app/mix/controller/init.go b/app/mix/controller/init.go index 676843fd..b0fc24cb 100644 --- a/app/mix/controller/init.go +++ b/app/mix/controller/init.go @@ -37,6 +37,7 @@ import ( loginproto "service/api/proto/login/proto" momentproto "service/api/proto/moment/proto" moment_audit_taskproto "service/api/proto/moment_audit_task/proto" + notificationproto "service/api/proto/notification/proto" productproto "service/api/proto/product/proto" realname_authenticationproto "service/api/proto/realname_authentication/proto" streamerproto "service/api/proto/streamer/proto" @@ -300,6 +301,12 @@ func Init(r *gin.Engine) { apiRavenIQTestGroup.POST("create", middleware.JSONParamValidator(Raven_IQ_testproto.ApiCreateReq{}), ApiCreateRavenIQTest) apiRavenIQTestGroup.POST("list", middleware.JSONParamValidator(Raven_IQ_testproto.ApiListReq{}), ApiGetRavenIQTestList) + // 系统通知表 + apiNotificationGroup := r.Group("/api/notification", PrepareToC()) + apiNotificationGroup.POST("list_unread_by_mid", middleware.JSONParamValidator(notificationproto.ApiListUnreadByMidReq{}), middleware.JwtAuthenticator(), ApiGetUnreadNotificationListByMid) + apiNotificationGroup.POST("read", middleware.JSONParamValidator(notificationproto.ApiReadReq{}), middleware.JwtAuthenticator(), ApiReadNotification) + apiNotificationGroup.POST("get_unread_count_by_mid", middleware.JSONParamValidator(notificationproto.ApiCountUnreadByMidReq{}), middleware.JwtAuthenticator(), ApiGetUnreadNotificationCountByMid) + // =============================== 以下是服务,只允许内网调用 =============================== // op相关,直接调用服务,不调用gateway @@ -597,6 +604,13 @@ func Init(r *gin.Engine) { opDailyStatementZoneInfoGroup := r.Group("/op/daily_statement_zone_info", PrepareOp()) opDailyStatementZoneInfoGroup.POST("list", middleware.JSONParamValidator(daily_statement_zone_info_proto.OpListReq{}), middleware.JwtAuthenticator(), OpGetDailyStatementZoneInfoList) + // 系统通知表 + opNotificationGroup := r.Group("/op/notification", PrepareOp()) + opNotificationGroup.POST("create", middleware.JSONParamValidator(notificationproto.OpCreateReq{}), middleware.JwtAuthenticator(), OpCreateNotification) + //opNotificationGroup.POST("update", middleware.JSONParamValidator(notificationproto.OpUpdateReq{}), middleware.JwtAuthenticator(), OpUpdateNotification) + opNotificationGroup.POST("delete", middleware.JSONParamValidator(notificationproto.OpDeleteReq{}), middleware.JwtAuthenticator(), OpDeleteNotification) + opNotificationGroup.POST("list_by_mid", middleware.JSONParamValidator(notificationproto.OpListByMidReq{}), middleware.JwtAuthenticator(), OpGetNotificationListByMid) + // 慧用工下发打款历史表 // opSingleDistributeHisGroup := r.Group("/api/single_distribute_his", PrepareOp()) // opSingleDistributeHisGroup.POST("create", middleware.JSONParamValidator(single_distribute_hisproto.OpCreateReq{}), middleware.JwtAuthenticator(), OpCreateSingleDistributeHis) diff --git a/app/mix/controller/notification_api.go b/app/mix/controller/notification_api.go new file mode 100644 index 00000000..62b24572 --- /dev/null +++ b/app/mix/controller/notification_api.go @@ -0,0 +1,65 @@ +package controller + +import ( + "service/api/consts" + "service/api/errcode" + notificationproto "service/api/proto/notification/proto" + "service/app/mix/service" + "service/bizcommon/util" + "service/library/logger" + + "github.com/gin-gonic/gin" +) + +func ApiGetUnreadNotificationListByMid(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.ApiListUnreadByMidReq) + + //设置默认页长 + if req.Limit == 0 { + req.Limit = consts.DefaultPageSize + } + + list, ec := service.DefaultService.ApiGetUnreadNotificationListByMid(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("ApiGetUnreadNotificationListByMid fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + data := ¬ificationproto.ApiListUnreadByMidData{ + List: list, + Offset: req.Offset + len(list), + } + if len(list) >= req.Limit { + data.More = 1 + } + ReplyOk(ctx, data) +} + +func ApiGetUnreadNotificationCountByMid(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.ApiCountUnreadByMidReq) + + unreadCount, ec := service.DefaultService.ApiGetUnreadNotificationCountByMid(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("ApiGetUnreadNotificationCountByMid fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + data := ¬ificationproto.ApiCountUnreadByMidData{ + UnreadCount: unreadCount, + } + ReplyOk(ctx, data) +} + +func ApiReadNotification(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.ApiReadReq) + ec := service.DefaultService.ApiReadNotification(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("ApiReadNotification fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + ReplyOk(ctx, nil) +} diff --git a/app/mix/controller/notification_op.go b/app/mix/controller/notification_op.go new file mode 100644 index 00000000..08dba1e3 --- /dev/null +++ b/app/mix/controller/notification_op.go @@ -0,0 +1,73 @@ +package controller + +import ( + "service/api/consts" + "service/api/errcode" + notificationproto "service/api/proto/notification/proto" + "service/app/mix/service" + "service/bizcommon/util" + "service/library/logger" + + "github.com/gin-gonic/gin" +) + +func OpCreateNotification(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.OpCreateReq) + ec := service.DefaultService.OpCreateNotification(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("OpCreateNotification fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrorMsg(ctx, "server error") + return + } + + ReplyOk(ctx, nil) +} + +func OpUpdateNotification(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.OpUpdateReq) + ec := service.DefaultService.OpUpdateNotification(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("OpUpdateNotification fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + ReplyOk(ctx, nil) +} + +func OpDeleteNotification(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.OpDeleteReq) + ec := service.DefaultService.OpDeleteNotification(ctx, req.Id) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("OpDeleteNotification fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + ReplyOk(ctx, nil) +} + +func OpGetNotificationListByMid(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.OpListByMidReq) + + //设置默认页长 + if req.Limit == 0 { + req.Limit = consts.DefaultPageSize + } + + list, ec := service.DefaultService.OpGetNotificationListByMid(ctx, req) + if ec != errcode.ErrCodeNotificationSrvOk { + logger.Error("OpGetNotificationList fail, req: %v, ec: %v", util.ToJson(req), ec) + ReplyErrCodeMsg(ctx, ec) + return + } + + data := ¬ificationproto.OpListByMidData{ + List: list, + Offset: req.Offset + len(list), + } + if len(list) >= req.Limit { + data.More = 1 + } + ReplyOk(ctx, data) +} diff --git a/app/mix/dao/mongo.go b/app/mix/dao/mongo.go index 36cc823d..79cbd6e1 100644 --- a/app/mix/dao/mongo.go +++ b/app/mix/dao/mongo.go @@ -35,6 +35,7 @@ import ( loginproto "service/api/proto/login/proto" momentproto "service/api/proto/moment/proto" moment_audit_taskproto "service/api/proto/moment_audit_task/proto" + notificationproto "service/api/proto/notification/proto" productproto "service/api/proto/product/proto" realname_authenticationproto "service/api/proto/realname_authentication/proto" single_distribute_his_proto "service/api/proto/single_distribute_his/proto" @@ -242,6 +243,9 @@ const ( DBEmail = "email" COLEmail = "email" + DBNotification = "notification" + COLNotification = "notification" + DBRavenIQTest = "Raven_IQ_test" COLRavenIQTest = "Raven_IQ_test" ) @@ -630,6 +634,11 @@ func (m *Mongo) getColEmail() *qmgo.Collection { return m.clientMix.Database(DBEmail).Collection(COLEmail) } +// 系统通知表表 +func (m *Mongo) getColNotification() *qmgo.Collection { + return m.clientMix.Database(DBNotification).Collection(COLNotification) +} + // 瑞文智商测试表表 func (m *Mongo) getColRavenIQTest() *qmgo.Collection { return m.clientMix.Database(DBRavenIQTest).Collection(COLRavenIQTest) @@ -6224,6 +6233,83 @@ func (m *Mongo) GetEmailList(ctx *gin.Context, req *emailproto.OpListReq) ([]*db return list, err } +// 系统通知表相关 +func (m *Mongo) CreateNotification(ctx *gin.Context, notification *dbstruct.Notification) error { + col := m.getColNotification() + _, err := col.InsertOne(ctx, notification) + return err +} + +func (m *Mongo) UpdateNotification(ctx *gin.Context, notification *dbstruct.Notification) error { + col := m.getColNotification() + set := util.EntityToM(notification) + set["ut"] = time.Now().Unix() + up := qmgo.M{ + "$set": set, + } + err := col.UpdateId(ctx, notification.Id, up) + return err +} + +func (m *Mongo) DeleteNotification(ctx *gin.Context, id int64) error { + col := m.getColNotification() + update := qmgo.M{ + "$set": qmgo.M{ + "del_flag": 1, + }, + } + err := col.UpdateId(ctx, id, update) + return err +} + +func (m *Mongo) GetNotificationListByMid(ctx *gin.Context, req *notificationproto.OpListByMidReq) ([]*dbstruct.Notification, error) { + list := make([]*dbstruct.Notification, 0) + col := m.getColNotification() + query := qmgo.M{ + "obj_mid": util.DerefInt64(req.Uid), + "del_flag": 0, + } + err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list) + if err == qmgo.ErrNoSuchDocuments { + err = nil + return list, err + } + return list, err +} + +func (m *Mongo) GetNotificationListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Notification, error) { + list := make([]*dbstruct.Notification, 0) + col := m.getColNotification() + query := qmgo.M{ + "_id": qmgo.M{ + "$in": ids, + }, + "del_flag": 0, + } + err := col.Find(ctx, query).Sort("-ct").All(&list) + if err == qmgo.ErrNoSuchDocuments { + err = nil + return list, err + } + return list, err +} + +func (m *Mongo) UpdateNotificationByIds(ctx *gin.Context, notification *dbstruct.Notification, ids []int64) error { + col := m.getColNotification() + query := qmgo.M{ + "_id": qmgo.M{ + "$in": ids, + }, + } + set := util.EntityToM(notification) + set["ut"] = time.Now().Unix() + up := qmgo.M{ + "$set": set, + } + _, err := col.UpdateAll(ctx, query, up) + return err +} + // 瑞文智商测试表相关 func (m *Mongo) CreateRavenIQTest(ctx *gin.Context, Raven_IQ_test *dbstruct.RavenIQTest) error { col := m.getColRavenIQTest() diff --git a/app/mix/dao/mongo_idseq.go b/app/mix/dao/mongo_idseq.go index 75a8bb2a..16c689cb 100644 --- a/app/mix/dao/mongo_idseq.go +++ b/app/mix/dao/mongo_idseq.go @@ -67,6 +67,9 @@ const ( DBRavenIQTestIdSeq = "Raven_IQ_test_id_seq" COLRavenIQTestIdSeq = "Raven_IQ_test_id_seq" + + DBNotificationIdSeq = "notification_id_seq" + COLNotificationIdSeq = "notification_id_seq" ) // UserIdSeq序列表 @@ -179,6 +182,11 @@ func (m *Mongo) getColRavenIQTestIdSeq() *qmgo.Collection { return m.clientMix.Database(DBRavenIQTestIdSeq).Collection(COLRavenIQTestIdSeq) } +// NotificationIdSeq序列表 +func (m *Mongo) getColNotificationIdSeq() *qmgo.Collection { + return m.clientMix.Database(DBNotificationIdSeq).Collection(COLNotificationIdSeq) +} + // account_id发号器 func (m *Mongo) GetAndUpdateAccountIdSeq(ctx *gin.Context) (accountIdSeq *dbstruct.AccountIdSeq, err error) { col := m.getColAccountIdSeq() @@ -646,3 +654,22 @@ func (m *Mongo) GetAndUpdateRavenIQTestIdSeq(ctx *gin.Context) (Raven_IQ_testIdS return &instance, err } + +// notification_id发号器 +func (m *Mongo) GetAndUpdateNotificationIdSeq(ctx *gin.Context) (notificationIdSeq *dbstruct.NotificationIdSeq, err error) { + col := m.getColNotificationIdSeq() + + change := qmgo.Change{ + Update: qmgo.M{"$inc": qmgo.M{"seq": 1}}, + Upsert: true, + ReturnNew: false, + } + + notificationIdSeqInstance := dbstruct.NotificationIdSeq{} + if err = col.Find(ctx, qmgo.M{"_id": "notification_id_seq_id"}).Apply(change, ¬ificationIdSeqInstance); err != nil { + logger.Error("change error : %v", err) + return + } + + return ¬ificationIdSeqInstance, err +} diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index f5bc922b..86a4f6bf 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -21,6 +21,7 @@ import ( loginproto "service/api/proto/login/proto" momentproto "service/api/proto/moment/proto" moment_audit_taskproto "service/api/proto/moment_audit_task/proto" + notificationproto "service/api/proto/notification/proto" realname_authenticationproto "service/api/proto/realname_authentication/proto" single_distribute_his_proto "service/api/proto/single_distribute_his/proto" streamerproto "service/api/proto/streamer/proto" @@ -44,6 +45,7 @@ import ( zonemomentthumbsupproto "service/api/proto/zonemomentthumbsup/proto" zonesessionproto "service/api/proto/zonesession/proto" "service/apollostruct" + "service/app/mix/service/logic" "service/bizcommon/common" "service/bizcommon/util" "service/dbstruct" @@ -4287,3 +4289,44 @@ func (s *Service) ApiGetRavenIQTestList(ctx *gin.Context, req *Raven_IQ_testprot return } + +// Notification +func (s *Service) ApiGetUnreadNotificationListByMid(ctx *gin.Context, req *notificationproto.ApiListUnreadByMidReq) (list []*dbstruct.Notification, ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + list, err := _DefaultNotification.OpListByMid(ctx, ¬ificationproto.OpListByMidReq{ + Uid: goproto.Int64(req.BaseRequest.Mid), + IsRead: goproto.Int64(consts.Notification_NotRead), + }) + if err != nil { + logger.Error("ApiGetNotificationList fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + return +} + +func (s *Service) ApiReadNotification(ctx *gin.Context, req *notificationproto.ApiReadReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + err := _DefaultNotification.OpUpdateByIds(ctx, &dbstruct.Notification{ + IsRead: goproto.Int64(consts.Notification_Read), + }, req.Ids) + if err == qmgo.ErrNoSuchDocuments { + ec = errcode.ErrCodeNotificationNotExist + err = nil + return + } + if err != nil { + logger.Error("ApiUpdate fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + return +} + +func (s *Service) ApiGetUnreadNotificationCountByMid(ctx *gin.Context, req *notificationproto.ApiCountUnreadByMidReq) (unreadCount int64, ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + + unreadCount, _ = redis.GetRedisClient().GetInt64(logic.GetNotificationCountIdForRedis(req.BaseRequest.Mid)) + + return +} diff --git a/app/mix/service/logic/notification.go b/app/mix/service/logic/notification.go new file mode 100644 index 00000000..6dd3d184 --- /dev/null +++ b/app/mix/service/logic/notification.go @@ -0,0 +1,96 @@ +package logic + +import ( + "fmt" + "service/api/consts" + notificationproto "service/api/proto/notification/proto" + "service/app/mix/dao" + "service/dbstruct" + "service/library/logger" + "time" + + "github.com/gin-gonic/gin" + goproto "google.golang.org/protobuf/proto" +) + +type Notification struct { + store *dao.Store +} + +func NewNotification(store *dao.Store) (a *Notification) { + a = &Notification{ + store: store, + } + return +} + +func (p *Notification) OpCreate(ctx *gin.Context, req *notificationproto.OpCreateReq) error { + + //生成自增id + notificationSeqId, err := p.store.GetAndUpdateNotificationIdSeq(ctx) + if err != nil { + logger.Error("GetAndUpdateNotificationIdSeq fail, err: %v", err) + return err + } + + req.Notification.Id = goproto.Int64(notificationSeqId.Seq) + req.Notification.Ct = goproto.Int64(time.Now().Unix()) + req.Notification.Ut = goproto.Int64(time.Now().Unix()) + req.Notification.DelFlag = goproto.Int64(consts.Exist) + req.Notification.IsRead = goproto.Int64(consts.Notification_NotRead) + err = p.store.CreateNotification(ctx, req.Notification) + if err != nil { + logger.Error("CreateNotification fail, err: %v", err) + return err + } + return nil +} + +func (p *Notification) OpUpdate(ctx *gin.Context, req *notificationproto.OpUpdateReq) error { + err := p.store.UpdateNotification(ctx, req.Notification) + if err != nil { + logger.Error("UpdateNotification fail, err: %v", err) + return err + } + return nil +} + +func (p *Notification) OpDelete(ctx *gin.Context, id int64) error { + err := p.store.DeleteNotification(ctx, id) + if err != nil { + logger.Error("DeleteNotification fail, err: %v", err) + return err + } + return nil +} + +func (p *Notification) OpListByMid(ctx *gin.Context, req *notificationproto.OpListByMidReq) ([]*dbstruct.Notification, error) { + list, err := p.store.GetNotificationListByMid(ctx, req) + if err != nil { + logger.Error("GetNotificationListByMid fail, err: %v", err) + return make([]*dbstruct.Notification, 0), err + } + return list, nil +} + +func (p *Notification) GetListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Notification, error) { + list, err := p.store.GetNotificationListByIds(ctx, ids) + if err != nil { + logger.Error("GetNotificationListByIds fail, ids: %v, err: %v", ids, err) + return make([]*dbstruct.Notification, 0), err + } + return list, nil +} + +func (p *Notification) OpUpdateByIds(ctx *gin.Context, notification *dbstruct.Notification, ids []int64) error { + err := p.store.UpdateNotificationByIds(ctx, notification, ids) + if err != nil { + logger.Error("UpdateNotificationByIds fail, err: %v", err) + return err + } + return nil +} + +func GetNotificationCountIdForRedis(mid int64) string { + return fmt.Sprintf("%sunread_count_%d", consts.RedisNotificationPrefix, mid) +} diff --git a/app/mix/service/service.go b/app/mix/service/service.go index 61a926ea..dd4bc80b 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -29,6 +29,7 @@ import ( mediaproto "service/api/proto/media/proto" momentproto "service/api/proto/moment/proto" moment_audit_taskproto "service/api/proto/moment_audit_task/proto" + notificationproto "service/api/proto/notification/proto" productproto "service/api/proto/product/proto" realname_authenticationproto "service/api/proto/realname_authentication/proto" resourceproto "service/api/proto/resource/proto" @@ -150,6 +151,7 @@ var ( _DefaultWorkerId *logic.WorkerId _DefaultSingleDistributeHis *logic.SingleDistributeHis _DefaultEmail *logic.Email + _DefaultNotification *logic.Notification _DefaultRavenIQTest *logic.RavenIQTest _DefaultAutoResponseCreateTimes *logic.AutoResponseCreateTimes @@ -256,6 +258,7 @@ func (s *Service) Init(c any) (err error) { _DefaultSingleDistributeHis = logic.NewSingleDistributeHis(store) _DefaultAutoResponseCreateTimes = logic.NewAutoResponseCreateTimes(store) _DefaultEmail = logic.NewEmail(store) + _DefaultNotification = logic.NewNotification(store) _DefaultRavenIQTest = logic.NewRavenIQTest(store) _DefaultVas = logic.NewVas(store, _DefaultStreamer, _DefaultAccount, _DefaultZone, _DefaultZoneThirdPartner, _DefaultZoneCollaborator) @@ -5007,3 +5010,62 @@ func (s *Service) OpGetSingleDistributeHisList(ctx *gin.Context, req *single_dis } return } + +// Notification +func (s *Service) OpCreateNotification(ctx *gin.Context, req *notificationproto.OpCreateReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + err := _DefaultNotification.OpCreate(ctx, req) + if err != nil { + logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + + // 加载进redis + _, err = redis.GetRedisClient().Incr(logic.GetNotificationCountIdForRedis(req.Notification.GetObjMid())) + if err != nil { + logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationCountRedisCacheInvalid + return + } + + return +} + +func (s *Service) OpUpdateNotification(ctx *gin.Context, req *notificationproto.OpUpdateReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + err := _DefaultNotification.OpUpdate(ctx, req) + if err == qmgo.ErrNoSuchDocuments { + ec = errcode.ErrCodeNotificationNotExist + err = nil + return + } + if err != nil { + logger.Error("OpUpdate fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + return +} + +func (s *Service) OpDeleteNotification(ctx *gin.Context, id int64) (ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + err := _DefaultNotification.OpDelete(ctx, id) + if err != nil { + logger.Error("OpDelete fail, id: %v, err: %v", id, err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + return +} + +func (s *Service) OpGetNotificationListByMid(ctx *gin.Context, req *notificationproto.OpListByMidReq) (list []*dbstruct.Notification, ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + list, err := _DefaultNotification.OpListByMid(ctx, req) + if err != nil { + logger.Error("OpGetNotificationList fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationSrvFail + return + } + return +} diff --git a/codecreate/codecreate.go b/codecreate/codecreate.go index 92407846..afd91b42 100644 --- a/codecreate/codecreate.go +++ b/codecreate/codecreate.go @@ -9,9 +9,9 @@ import ( func main() { genSource := &generator.GenSource{ - EntityName: "Email", - ModuleName: "email", - EntityCNName: "电子邮件表", + EntityName: "Notification", + ModuleName: "notification", + EntityCNName: "系统通知表", ErrCodeSeq: "45", } diff --git a/dbstruct/idSeq.go b/dbstruct/idSeq.go index d73d5974..e1a29395 100644 --- a/dbstruct/idSeq.go +++ b/dbstruct/idSeq.go @@ -92,3 +92,7 @@ type VideoModerationBatchId struct { type RavenIQTestIdSeq struct { Seq int64 //用户Id序列号 } + +type NotificationIdSeq struct { + Seq int64 //用户Id序列号 +} diff --git a/dbstruct/notification.go b/dbstruct/notification.go new file mode 100644 index 00000000..b83be294 --- /dev/null +++ b/dbstruct/notification.go @@ -0,0 +1,23 @@ +package dbstruct + +type Notification struct { + Id *int64 `json:"id" bson:"_id"` // 系统通知表id + SubMid *int64 `json:"sub_mid" bson:"sub_mid"` // 通知发送人mid + ObjMid *int64 `json:"obj_mid" bson:"obj_mid"` // 通知接收人mid + NType *int64 `json:"n_type" bson:"n_type"` // 消息类型 + NDesc *string `json:"n_desc" bson:"n_desc"` // 消息描述 + Message *string `json:"message" bson:"message"` // 消息内容 + Thumbnail *MediaComponent `json:"thumbnail" bson:"thumbnail"` // 缩略图 + LinkText *string `json:"link_text" bson:"link_text"` // 链接文案 + IsRead *int64 `json:"is_read" bson:"is_read"` // 是否已读 + Ct *int64 `json:"ct" bson:"ct"` // 创建时间 + Ut *int64 `json:"ut" bson:"ut"` // 更新时间 + DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记 +} + +func (p *Notification) GetObjMid() int64 { + if p != nil && p.ObjMid != nil { + return *p.ObjMid + } + return 0 +} diff --git a/library/idgenerator/genid.go b/library/idgenerator/genid.go index d69d6d4e..a92ed0d1 100644 --- a/library/idgenerator/genid.go +++ b/library/idgenerator/genid.go @@ -57,6 +57,7 @@ const ( NodeWorkerId // node 用户职业者id映射表 NodeSingleDistributeHis // node 慧用工下发打款历史表 NodeEmail // node 电子邮件表 + NodeNotification // node 系统通知表 ) func GenIdInt64(node int64) (int64, error) { @@ -280,3 +281,9 @@ func GenEmailId() int64 { id, _ := GenIdInt64(NodeEmail) return id } + +// notification +func GenNotificationId() int64 { + id, _ := GenIdInt64(NodeNotification) + return id +}