diff --git a/api/consts/consts.go b/api/consts/consts.go index 7e20f50b..e3716bb9 100644 --- a/api/consts/consts.go +++ b/api/consts/consts.go @@ -89,9 +89,10 @@ const ( // redis键前缀 const ( - RedisStreamerPrefix = "streamer:" //streamer服务前缀 - RedisMomentPrefix = "moment:" //moment服务前缀 - RedisNotificationPrefix = "notification:" //notification服务前缀 + RedisStreamerPrefix = "streamer:" //streamer服务前缀 + RedisMomentPrefix = "moment:" //moment服务前缀 + RedisNotificationPrefix = "notification:" //notification服务前缀 + RedisContactCustomerServicePrefix = "contact_customer_service:" //contact_customer_service服务前缀 ) //const PackageRootPath = "C:/Users/PC/Desktop/service" diff --git a/api/consts/status.go b/api/consts/status.go index 8689e17c..34a0c569 100644 --- a/api/consts/status.go +++ b/api/consts/status.go @@ -327,3 +327,9 @@ const ( Notification_NotRead = 0 //未读 Notification_Read = 1 //已读 ) + +// 系统通知表的推送状态 +const ( + NotificationStatus_Created = 0 //已创建 + NotificationStatus_Pushed = 1 //已推送 +) diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index 840a5688..7573c00c 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -133,9 +133,11 @@ var ErrCodeMsgMap = map[ErrCode]string{ ErrCodeRealNameAuthenticationNotExist: "实名认证不存在", ErrCodeRealNameAuthenticationDuplicateKey: "请勿重复提交实名认证", - ErrCodeContactCustomerServiceSrvFail: "联系客服服务错误", - ErrCodeContactCustomerServiceNotExist: "联系客服不存在", - ErrCodeAutoResponseSrvFail: "自动回复服务错误", + ErrCodeContactCustomerServiceSrvFail: "联系客服服务错误", + ErrCodeContactCustomerServiceNotExist: "联系客服不存在", + ErrCodeAutoResponseSrvFail: "自动回复服务错误", + ErrCodeContactCustomerServiceWrongSessionId: "联系客服对话ID非法", + ErrCodeContactCustomerServiceCountRedisCacheInvalid: "联系客服表redis缓存失效", ErrCodeImageAuditSrvFail: "图像审核服务错误", ErrCodeImageAuditNotExist: "图像审核不存在", @@ -431,10 +433,12 @@ const ( ErrCodeRealNameAuthenticationDuplicateKey ErrCode = -18003 // 实名认证重复提交 // ContactCustomerService: 19xxx - ErrCodeContactCustomerServiceSrvOk ErrCode = ErrCodeOk - ErrCodeContactCustomerServiceSrvFail ErrCode = -19001 // 联系客服服务错误 - ErrCodeContactCustomerServiceNotExist ErrCode = -19002 // 联系客服不存在 - ErrCodeAutoResponseSrvFail ErrCode = -19003 // 自动回复服务错误 + ErrCodeContactCustomerServiceSrvOk ErrCode = ErrCodeOk + ErrCodeContactCustomerServiceSrvFail ErrCode = -19001 // 联系客服服务错误 + ErrCodeContactCustomerServiceNotExist ErrCode = -19002 // 联系客服不存在 + ErrCodeAutoResponseSrvFail ErrCode = -19003 // 自动回复服务错误 + ErrCodeContactCustomerServiceWrongSessionId ErrCode = -19004 // 联系客服对话id非法 + ErrCodeContactCustomerServiceCountRedisCacheInvalid ErrCode = -19005 // 联系客服表redis缓存失效 // ImageAudit: 20xxx ErrCodeImageAuditSrvOk ErrCode = ErrCodeOk diff --git a/api/proto/contact_customer_service/proto/contact_customer_service_api.go b/api/proto/contact_customer_service/proto/contact_customer_service_api.go index 3a4d48be..6174221f 100644 --- a/api/proto/contact_customer_service/proto/contact_customer_service_api.go +++ b/api/proto/contact_customer_service/proto/contact_customer_service_api.go @@ -38,3 +38,32 @@ type ApiListBySessionIdResp struct { base.BaseResponse Data *ApiListBySessionIdData `json:"data"` } + +// op 更新 +type ApiUpdateByIdsReq struct { + base.BaseRequest + *dbstruct.ContactCustomerService + Ids []int64 +} + +type ApiUpdateByIdsData struct { +} + +type ApiUpdateByIdsResp struct { + base.BaseResponse + Data *ApiUpdateByIdsData `json:"data"` +} + +// op 一键已读 +type ApiReadAllReq struct { + base.BaseRequest + SessionId *int64 `json:"session_id"` +} + +type ApiReadAllData struct { +} + +type ApiReadAllResp struct { + base.BaseResponse + Data *ApiReadAllData `json:"data"` +} diff --git a/api/proto/contact_customer_service/proto/contact_customer_service_op.go b/api/proto/contact_customer_service/proto/contact_customer_service_op.go index a113dda3..a1c600bf 100644 --- a/api/proto/contact_customer_service/proto/contact_customer_service_op.go +++ b/api/proto/contact_customer_service/proto/contact_customer_service_op.go @@ -82,3 +82,17 @@ type OpListBySessionIdResp struct { base.BaseResponse Data *OpListBySessionIdData `json:"data"` } + +// op 一键已读 +type OpReadAllReq struct { + base.BaseRequest + SessionId *int64 `json:"session_id"` +} + +type OpReadAllData struct { +} + +type OpReadAllResp struct { + base.BaseResponse + Data *OpReadAllData `json:"data"` +} diff --git a/api/proto/contact_customer_service/proto/not_null_def_api.go b/api/proto/contact_customer_service/proto/not_null_def_api.go index fde6413b..32b2c1c1 100644 --- a/api/proto/contact_customer_service/proto/not_null_def_api.go +++ b/api/proto/contact_customer_service/proto/not_null_def_api.go @@ -21,3 +21,17 @@ func (p *ApiListBySessionIdReq) ProvideNotNullValue() (params []*validator.JsonP params = append(params, validator.NewInt64PtrParam("session_id should not be null", p.SessionId)) return params } + +// op 按id更新 +func (p *ApiUpdateByIdsReq) ProvideNotNullValue() (params []*validator.JsonParam) { + params = make([]*validator.JsonParam, 0) + params = append(params, validator.NewInt64SliceParam("欲更新的联系客服Ids为空!", p.Ids)) + return params +} + +// op 一键已读 +func (p *ApiReadAllReq) ProvideNotNullValue() (params []*validator.JsonParam) { + params = make([]*validator.JsonParam, 0) + params = append(params, validator.NewInt64PtrParam("请填写对话ID!", p.SessionId)) + return params +} diff --git a/api/proto/contact_customer_service/proto/not_null_def_op.go b/api/proto/contact_customer_service/proto/not_null_def_op.go index 31e6f26e..beec07c0 100644 --- a/api/proto/contact_customer_service/proto/not_null_def_op.go +++ b/api/proto/contact_customer_service/proto/not_null_def_op.go @@ -28,3 +28,10 @@ func (p *OpListBySessionIdReq) ProvideNotNullValue() (params []*validator.JsonPa params = append(params, validator.NewInt64PtrParam("session_id should not be null", p.SessionId)) return params } + +// op 一键已读 +func (p *OpReadAllReq) ProvideNotNullValue() (params []*validator.JsonParam) { + params = make([]*validator.JsonParam, 0) + params = append(params, validator.NewInt64PtrParam("请填写对话ID!", p.SessionId)) + return params +} diff --git a/api/proto/contact_customer_service_session/proto/contact_customer_service_session_api.go b/api/proto/contact_customer_service_session/proto/contact_customer_service_session_api.go index 89899fa4..c64b85f2 100644 --- a/api/proto/contact_customer_service_session/proto/contact_customer_service_session_api.go +++ b/api/proto/contact_customer_service_session/proto/contact_customer_service_session_api.go @@ -48,3 +48,18 @@ type ApiListResp struct { base.BaseResponse Data *ApiListByMidData `json:"data"` } + +// op 统计未读总数 +type ApiCountUnreadByMidReq struct { + base.BaseRequest + SessionId *int64 `json:"session_id"` +} + +type ApiCountUnreadByMidData struct { + UnreadCount int64 `json:"unread_count"` +} + +type ApiCountUnreadByMidResp struct { + base.BaseResponse + Data *ApiCountUnreadByMidData `json:"data"` +} diff --git a/api/proto/contact_customer_service_session/proto/contact_customer_service_session_op.go b/api/proto/contact_customer_service_session/proto/contact_customer_service_session_op.go index bc86348b..6a5c06ab 100644 --- a/api/proto/contact_customer_service_session/proto/contact_customer_service_session_op.go +++ b/api/proto/contact_customer_service_session/proto/contact_customer_service_session_op.go @@ -96,3 +96,18 @@ type OpListResp struct { base.BaseResponse Data *OpListData `json:"data"` } + +// op 统计未读总数 +type OpCountUnreadByMidReq struct { + base.BaseRequest + SessionId *int64 `json:"session_id"` +} + +type OpCountUnreadByMidData struct { + UnreadCount int64 `json:"unread_count"` +} + +type OpCountUnreadByMidResp struct { + base.BaseResponse + Data *OpCountUnreadByMidData `json:"data"` +} diff --git a/api/proto/contact_customer_service_session/proto/not_null_def_api.go b/api/proto/contact_customer_service_session/proto/not_null_def_api.go index f830ffa2..eec231b8 100644 --- a/api/proto/contact_customer_service_session/proto/not_null_def_api.go +++ b/api/proto/contact_customer_service_session/proto/not_null_def_api.go @@ -20,3 +20,10 @@ func (p *ApiListByMidReq) ProvideNotNullValue() (params []*validator.JsonParam) params = append(params, validator.NewInt64PtrParam("mid should not be null", p.Mid)) return params } + +// api 统计未读总数 +func (p *ApiCountUnreadByMidReq) ProvideNotNullValue() (params []*validator.JsonParam) { + params = make([]*validator.JsonParam, 0) + params = append(params, validator.NewInt64PtrParam("请输入对话id!", p.SessionId)) + return params +} diff --git a/app/mix/dao/mongo.go b/app/mix/dao/mongo.go index 23c55ba8..9f272e68 100644 --- a/app/mix/dao/mongo.go +++ b/app/mix/dao/mongo.go @@ -3359,6 +3359,38 @@ func (m *Mongo) GetContactCustomerServiceListBySessionId(ctx *gin.Context, req * return list, err } +func (m *Mongo) UpdateContactCustomerServiceBySessionIdAndPredicate(ctx *gin.Context, contact_customer_service *dbstruct.ContactCustomerService, sessionId int64, predicate int64) error { + col := m.getColContactCustomerService() + set := util.EntityToM(contact_customer_service) + set["ut"] = time.Now().Unix() + up := qmgo.M{ + "$set": set, + } + filter := qmgo.M{ + "session_id": sessionId, + "predicate": predicate, + } + _, err := col.UpdateAll(ctx, filter, up) + return err +} + +func (m *Mongo) GetContactCustomerServiceListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.ContactCustomerService, error) { + list := make([]*dbstruct.ContactCustomerService, 0) + col := m.getColContactCustomerService() + query := qmgo.M{ + "_id": bson.M{ + "$in": ids, + }, + "del_flag": 0, + } + err := col.Find(ctx, query).All(&list) + if err == qmgo.ErrNoSuchDocuments { + err = nil + return make([]*dbstruct.ContactCustomerService, 0), err + } + return list, err +} + // 自动回复创建频次 func (m *Mongo) GetAndUpdateAutoResponseCreateTimes(ctx *gin.Context, mid int64) (autoResponseCreateTimes *dbstruct.AutoResponseCreateTimes, err error) { col := m.getColAutoResponseCreateTimes() diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index 50f32c2f..3f7c3125 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -2000,6 +2000,20 @@ func (s *Service) ApiCreateContactCustomerService(ctx *gin.Context, req *contact return } + // 更新redis缓存 + _, err = redis.GetRedisClient().Incr(logic.GetCreateContactCustomerServiceCountIdForRedis(req.ContactCustomerService.GetSessionId(), consts.ContactCustomerService_FromUser)) + if err != nil { + logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + _, err = redis.GetRedisClient().Incr(consts.RedisContactCustomerServicePrefix + "sup_total_unread_count") + if err != nil { + logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + //如果在自动回复时间段,则创建一条自动回复信息 now := time.Now() st := util.GetTimestampAtThisMomentForTime(now, cfg.StartTime) @@ -2026,6 +2040,12 @@ func (s *Service) ApiCreateContactCustomerService(ctx *gin.Context, req *contact if err != nil { logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err) } + + // 更新redis缓存 + _, err = redis.GetRedisClient().Incr(logic.GetCreateContactCustomerServiceCountIdForRedis(req.ContactCustomerService.GetSessionId(), consts.ContactCustomerService_FromSupportor)) + if err != nil { + logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) + } }() isAutoResponsed = consts.ContactCustomerService_AutoResponsed } @@ -2048,6 +2068,82 @@ func (s *Service) ApiGetContactCustomerServiceListBySessionId(ctx *gin.Context, return } +func (s *Service) ApiUpdateContactCustomerServiceByIds(ctx *gin.Context, req *contact_customer_service_proto.ApiUpdateByIdsReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeContactCustomerServiceSrvOk + + if ec = s.ApiUpdateContactCustomerServiceByIdsBusinessValidate(ctx, req); ec != errcode.ErrCodeZoneCollaboratorSrvOk { + return + } + + err := _DefaultContactCustomerService.OpUpdateByIds(ctx, &contact_customer_service_proto.OpUpdateByIdsReq{ + BaseRequest: req.BaseRequest, + ContactCustomerService: req.ContactCustomerService, + Ids: req.Ids, + }) + if err == qmgo.ErrNoSuchDocuments { + ec = errcode.ErrCodeContactCustomerServiceNotExist + err = nil + return + } + if err != nil { + logger.Error("OpUpdate fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceSrvFail + return + } + + // 若更新为已读,则将缓存的该对话来自运营的未读消息总数去掉ids总量的值 + isRead := util.DerefInt64(req.ContactCustomerService.IsRead) + if isRead == consts.ContactCustomerService_Read { + session, err := _DefaultContactCustomerServiceSession.OpListByMid(ctx, &contact_customer_service_sessionproto.OpListByMidReq{ + Mid: goproto.Int64(req.BaseRequest.Mid), + }) + if err != nil { + logger.Error("OpListByMid fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceSrvFail + return + } + key := logic.GetCreateContactCustomerServiceCountIdForRedis(session.GetId(), consts.ContactCustomerService_FromSupportor) + _, err = redis.GetRedisClient().DecrBy(key, int64(len(req.Ids))) + if err != nil { + logger.Error("Redis DecrBy fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + } + return +} + +func (s *Service) ApiReadAllContactCustomerService(ctx *gin.Context, req *contact_customer_service_proto.ApiReadAllReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeContactCustomerServiceSrvOk + + updateEntity := &dbstruct.ContactCustomerService{ + IsRead: goproto.Int64(consts.ContactCustomerService_Read), + } + + // 将这个对话所有来自客服的消息全部设为已读 + err := _DefaultContactCustomerService.OpUpdateBySessionIdAndPredicate(ctx, updateEntity, util.DerefInt64(req.SessionId), consts.ContactCustomerService_FromSupportor) + if err == qmgo.ErrNoSuchDocuments { + ec = errcode.ErrCodeContactCustomerServiceNotExist + err = nil + return + } + if err != nil { + logger.Error("OpUpdateBySessionIdAndPredicate fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceSrvFail + return + } + + // 将缓存清零 + key := logic.GetCreateContactCustomerServiceCountIdForRedis(util.DerefInt64(req.SessionId), consts.ContactCustomerService_FromSupportor) + err = redis.GetRedisClient().Set(key, 0, 0) + if err != nil { + logger.Error("Redis Set fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + return +} + // ContactCustomerServiceSession func (s *Service) ApiCreateContactCustomerServiceSession(ctx *gin.Context, req *contact_customer_service_sessionproto.ApiCreateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeContactCustomerServiceSessionSrvOk diff --git a/app/mix/service/apiservice_business_validation.go b/app/mix/service/apiservice_business_validation.go index 556ef672..a22c2829 100644 --- a/app/mix/service/apiservice_business_validation.go +++ b/app/mix/service/apiservice_business_validation.go @@ -6,6 +6,8 @@ import ( "service/api/errcode" accountproto "service/api/proto/account/proto" accountrelationproto "service/api/proto/accountrelation/proto" + contact_customer_service_proto "service/api/proto/contact_customer_service/proto" + contact_customer_service_session_proto "service/api/proto/contact_customer_service_session/proto" loginproto "service/api/proto/login/proto" momentproto "service/api/proto/moment/proto" streamerproto "service/api/proto/streamer/proto" @@ -794,3 +796,23 @@ func (s *Service) ApiCreateOrderBusinessValidate(ctx *gin.Context, req *vasproto } return nil } + +func (s *Service) ApiUpdateContactCustomerServiceByIdsBusinessValidate(ctx *gin.Context, req *contact_customer_service_proto.ApiUpdateByIdsReq) (ec errcode.ErrCode) { + + result := businessvalidator.NewAuthBusinessValidator(ctx, req). + EnsureContactCustomerServiceIdsAreFromThisUser(_DefaultContactCustomerService.GetSessionCountMapByIds, + func(ctx *gin.Context, mid int64) (*dbstruct.ContactCustomerServiceSession, error) { + return _DefaultContactCustomerServiceSession.OpListByMid(ctx, &contact_customer_service_session_proto.OpListByMidReq{ + Mid: goproto.Int64(mid), + }) + }, req.Ids, req.BaseRequest.Mid). + Validate(). + Collect() + ec = result[0].(errcode.ErrCode) + if ec != errcode.ErrCodeOk { + logger.Error("ApiUpdateContactCustomerServiceByIds business validation failed") + return + } + + return +} diff --git a/app/mix/service/business_validator/auth.go b/app/mix/service/business_validator/auth.go index 1384bb26..19b37d1a 100644 --- a/app/mix/service/business_validator/auth.go +++ b/app/mix/service/business_validator/auth.go @@ -772,6 +772,40 @@ func (l *AuthBusinessValidator) EnsureStreamerAuthApprovalIsUnique(createFunc fu return l } +func (l *AuthBusinessValidator) EnsureContactCustomerServiceIdsAreFromThisUser(mpQueryFunc func(*gin.Context, []int64) (map[int64]int64, error), sessionQueryFunc func(*gin.Context, int64) (*dbstruct.ContactCustomerServiceSession, error), ids []int64, mid int64) *AuthBusinessValidator { + l.oplist = append(l.oplist, func() { + mp, err := mpQueryFunc(l.ctx, ids) + if err != nil { + l.ec = errcode.ErrCodeContactCustomerServiceSrvFail + return + } + if len(mp) == 0 { + l.ec = errcode.ErrCodeContactCustomerServiceNotExist + return + } + if len(mp) > 1 { + l.ec = errcode.ErrCodeContactCustomerServiceWrongSessionId + return + } + session, err := sessionQueryFunc(l.ctx, mid) + if err != nil { + l.ec = errcode.ErrCodeContactCustomerServiceSessionSrvFail + return + } + if session == nil { + l.ec = errcode.ErrCodeContactCustomerServiceSessionNotExist + return + } + for sessionId := range mp { + if sessionId != session.GetId() { + l.ec = errcode.ErrCodeContactCustomerServiceWrongSessionId + return + } + } + }) + return l +} + // 执行校验 func (a *AuthBusinessValidator) Validate() *AuthBusinessValidator { a.BusinessValidateStream.Validate() diff --git a/app/mix/service/logic/contact_customer_service.go b/app/mix/service/logic/contact_customer_service.go index 05552362..d4427cd6 100644 --- a/app/mix/service/logic/contact_customer_service.go +++ b/app/mix/service/logic/contact_customer_service.go @@ -1,6 +1,7 @@ package logic import ( + "fmt" "service/api/consts" contact_customer_serviceproto "service/api/proto/contact_customer_service/proto" "service/app/mix/dao" @@ -98,3 +99,36 @@ func (p *ContactCustomerService) OpListBySessionId(ctx *gin.Context, req *contac } return list, nil } + +func (p *ContactCustomerService) OpUpdateBySessionIdAndPredicate(ctx *gin.Context, updateEntity *dbstruct.ContactCustomerService, sessionId int64, predicate int64) error { + err := p.store.UpdateContactCustomerServiceBySessionIdAndPredicate(ctx, updateEntity, sessionId, predicate) + if err != nil { + logger.Error("UpdateContactCustomerServiceBySessionIdAndPredicate fail, err: %v", err) + return err + } + return nil +} + +func (p *ContactCustomerService) GetSessionCountMapByIds(ctx *gin.Context, ids []int64) (map[int64]int64, error) { + mp := make(map[int64]int64, 0) + list, err := p.store.GetContactCustomerServiceListByIds(ctx, ids) + if err != nil { + logger.Error("GetContactCustomerServiceListByIds fail, err: %v", err) + return make(map[int64]int64, 0), err + } + for _, svc := range list { + mp[svc.GetSessionId()]++ + } + return mp, nil +} + +func GetCreateContactCustomerServiceCountIdForRedis(sessionId int64, role_from int64) string { + rolestr := "" + switch role_from { + case consts.ContactCustomerService_FromUser: + rolestr = "from_user" + case consts.ContactCustomerService_FromSupportor: + rolestr = "from_sup" + } + return fmt.Sprintf("%s%s_unread_count_%d", consts.RedisContactCustomerServicePrefix, rolestr, sessionId) +} diff --git a/app/mix/service/service.go b/app/mix/service/service.go index e8ef56e2..84cd459d 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -3085,6 +3085,15 @@ func (s *Service) OpCreateContactCustomerService(ctx *gin.Context, req *contact_ ec = errcode.ErrCodeContactCustomerServiceSessionSrvFail return } + + // 更新redis缓存 + _, err := redis.GetRedisClient().Incr(logic.GetCreateContactCustomerServiceCountIdForRedis(req.ContactCustomerService.GetSessionId(), consts.ContactCustomerService_FromSupportor)) + if err != nil { + logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationCountRedisCacheInvalid + return + } + return } @@ -3106,6 +3115,33 @@ func (s *Service) OpUpdateContactCustomerServiceByIds(ctx *gin.Context, req *con ec = errcode.ErrCodeContactCustomerServiceSrvFail return } + + // 若更新为已读,则将缓存的这些对话来自用户的未读消息总数去掉对应总量的值 + isRead := util.DerefInt64(req.ContactCustomerService.IsRead) + if isRead == consts.ContactCustomerService_Read { + mp, err := _DefaultContactCustomerService.GetSessionCountMapByIds(ctx, req.Ids) + if err != nil { + logger.Error("GetSessionCountMapByIds fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceSrvFail + return + } + for sessionId, count := range mp { + key := logic.GetCreateContactCustomerServiceCountIdForRedis(sessionId, consts.ContactCustomerService_FromUser) + _, err = redis.GetRedisClient().DecrBy(key, count) + if err != nil { + logger.Error("Redis DecrBy fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + } + // 去掉总量 + _, err = redis.GetRedisClient().DecrBy(consts.RedisContactCustomerServicePrefix+"sup_total_unread_count", int64(len(req.Ids))) + if err != nil { + logger.Error("Redis DecrBy fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid + return + } + } return } @@ -4963,6 +4999,8 @@ func (s *Service) OpGetSingleDistributeHisList(ctx *gin.Context, req *single_dis // Notification func (s *Service) OpCreateNotification(ctx *gin.Context, req *notificationproto.OpCreateReq) (ec errcode.ErrCode) { ec = errcode.ErrCodeNotificationSrvOk + + req.Status = goproto.Int64(consts.NotificationStatus_Created) err := _DefaultNotification.OpCreate(ctx, req) if err != nil { logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err) diff --git a/dbstruct/contact_customer_service.go b/dbstruct/contact_customer_service.go index 6b029f76..e931a00a 100644 --- a/dbstruct/contact_customer_service.go +++ b/dbstruct/contact_customer_service.go @@ -11,3 +11,10 @@ type ContactCustomerService struct { DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记 } + +func (p *ContactCustomerService) GetSessionId() int64 { + if p == nil || p.SessionId == nil { + return -1 + } + return *p.SessionId +} diff --git a/dbstruct/contact_customer_service_session.go b/dbstruct/contact_customer_service_session.go index fbb2da69..64530700 100644 --- a/dbstruct/contact_customer_service_session.go +++ b/dbstruct/contact_customer_service_session.go @@ -8,5 +8,11 @@ type ContactCustomerServiceSession struct { Ct *int64 `json:"ct" bson:"ct"` // 创建时间 Ut *int64 `json:"ut" bson:"ut"` // 更新时间 DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记 - +} + +func (p *ContactCustomerServiceSession) GetId() int64 { + if p == nil || p.Id == nil { + return -1 + } + return *p.Id } diff --git a/dbstruct/notification.go b/dbstruct/notification.go index b83be294..910c5e85 100644 --- a/dbstruct/notification.go +++ b/dbstruct/notification.go @@ -9,6 +9,10 @@ type Notification struct { Message *string `json:"message" bson:"message"` // 消息内容 Thumbnail *MediaComponent `json:"thumbnail" bson:"thumbnail"` // 缩略图 LinkText *string `json:"link_text" bson:"link_text"` // 链接文案 + Action *string `json:"action" bson:"action"` // 行为 + Params *string `json:"params" bson:"params"` // 参数 + PushTime *int64 `json:"push_time" bson:"push_time"` // 推送时间 + Status *int64 `json:"status" bson:"status"` // 推送状态 IsRead *int64 `json:"is_read" bson:"is_read"` // 是否已读 Ct *int64 `json:"ct" bson:"ct"` // 创建时间 Ut *int64 `json:"ut" bson:"ut"` // 更新时间