From 328264a40fc3f98e0006622f631424d21aaeeac7 Mon Sep 17 00:00:00 2001 From: hujiebin Date: Mon, 6 Mar 2023 10:17:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=B6=E6=97=8F=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _const/enum/msg_e/msg.go | 133 ++++ cv/group_power_cv/groupPower.go | 641 ++++++++++++++++ cv/group_power_cv/group_power.go | 31 - cv/user_cv/user.go | 138 +++- domain/event/group_power_ev/groupPowerJoin.go | 29 + .../event/group_power_ev/groupPowerLeave.go | 29 + domain/model/msg_m/msg.go | 54 ++ domain/model/msg_m/repo.go | 13 + domain/service/event_s/event_init.go | 73 ++ domain/service/group_power_s/group_power.go | 68 ++ go.mod | 2 + go.sum | 12 + main.go | 3 +- myerr/bizerr/bizCode.go | 1 + route/group_power_r/group_power.go | 694 ++++++++++++++++++ route/router.go | 12 + 16 files changed, 1899 insertions(+), 34 deletions(-) create mode 100644 cv/group_power_cv/groupPower.go delete mode 100644 cv/group_power_cv/group_power.go create mode 100644 domain/event/group_power_ev/groupPowerJoin.go create mode 100644 domain/event/group_power_ev/groupPowerLeave.go create mode 100644 domain/model/msg_m/msg.go create mode 100644 domain/model/msg_m/repo.go create mode 100644 domain/service/event_s/event_init.go create mode 100644 domain/service/group_power_s/group_power.go create mode 100644 route/group_power_r/group_power.go diff --git a/_const/enum/msg_e/msg.go b/_const/enum/msg_e/msg.go index da53218..a6ed59d 100644 --- a/_const/enum/msg_e/msg.go +++ b/_const/enum/msg_e/msg.go @@ -1,5 +1,7 @@ package msg_e +import "git.hilo.cn/hilo-common/resource/mysql" + type MsgIdType = uint const ( @@ -17,3 +19,134 @@ const ( MSG_ID_USER_TRANSFER MsgIdType = 114 MSG_ID_NO_POWER_TO_SVIP6 MsgIdType = 115 // 不能对svip6做某些动作 ) + +//消息发送类型,消息接收者是谁 1:通知 2:官网 3:被喜欢通知 (注意:MsgReceiveType 同 MsgUserRecordType 不是树形关系s) +//MsgReceive 结构体服务 +type MsgReceiveType = mysql.Type + +const ( + //小助手的通知 + UserMsgReceiveType MsgReceiveType = 1 + //系统的通知 + SysMsgReceiveType MsgReceiveType = 2 + //喜欢消息 + LikeMeReceiveType MsgReceiveType = 3 + //工会用户通知 + TradeUnionReceiveType MsgReceiveType = 4 + //用户召回 + UserRecall MsgReceiveType = 5 + //video请求 + VideoSend MsgReceiveType = 6 + //访问 + VisitReceiveType MsgReceiveType = 7 + //拉黑 + BlockReceiveType MsgReceiveType = 8 + //短信验证码 + SmsCode MsgReceiveType = 9 +) + +//跳转类型 0:无调整 1:网页跳转 2:app跳转 3:跳转到钻石 4:跳转到背包 +type ActionType = uint16 + +const ( + NonActionType ActionType = 0 + WebActionType ActionType = 1 + AppActionType ActionType = 2 +) + +//消息记录类型(设计的不好,应该是根据消息样式类型设计,而不是业务类型,渣渣) +type MsgUserRecordType = mysql.Type + +const ( + //新用户 + //NewUserType MsgUserRecordType = 1 + //举报 + ReportType MsgUserRecordType = 2 + //喜欢我 + //LikeMeType MsgUserRecordType = 3 + //重置图片 + ResetAvatarType MsgUserRecordType = 4 + // + //喜欢我 + LikeMeType MsgUserRecordType = 5 + //访问 + VisitType MsgUserRecordType = 6 + //新匹配记录 + MatchHistoryType MsgUserRecordType = 7 + //互相喜欢 + LikeEachType MsgUserRecordType = 8 + //你获得s%钻石的礼物收益! + DiamondIncome MsgUserRecordType = 9 + //榜单结果 + ActivityBillboardResult MsgUserRecordType = 10 + //榜单钻石收益 + ActivityBillboardDiamond MsgUserRecordType = 11 + //榜单坐骑收益 + ActivityBillboardProperty MsgUserRecordType = 12 + //通过收礼物获得豆子 + ActivityBeanProperty MsgUserRecordType = 13 + //管理人送钻石 + MgrSendDiamondProperty MsgUserRecordType = 14 + //群组榜单钻石收益 + ActivityGroupBillboardDiamond MsgUserRecordType = 15 + //群组榜单坐骑收益 + ActivityGroupBillboardProperty MsgUserRecordType = 16 + //群组支持收益 + GroupSupport MsgUserRecordType = 17 + //群组支持提醒结果 + GroupSupportResult MsgUserRecordType = 18 + //管理人送座驾 + MgrSendProperty MsgUserRecordType = 19 + //送道具(座驾,头饰都属于道具) + AddProps MsgUserRecordType = 20 + //MISS活动获胜 + ActivityBillboardBeLikeResult = 21 + //CP活动获胜 + ActivityBillboardCpResult = 22 + //加入势力主 + GroupPowerUserJoin = 23 + //离开势力主 + GroupPowerUserLeave = 24 + //贵族 + AddNoble = 25 + //日充值活动通知 + ActivityTriggerDayPay = 26 + //也门活动通知 + ActivityTriggerYemen = 27 + //月充值活动通知 + ActivityTriggerMonthPay = 28 + FruitTycoonAward = 29 // 水果大亨获奖 + LuckyboxRecycle = 30 //幸运盒子回收 + HlTemp1 = 31 //产品黄蕾,2022/06/29 临时要求发给某人的小助手消息 + HLTemp2 = 32 //问卷调查 + NewUserInviteAuditPassed = 33 // 新用户奖励活动审核通过 + NewUserInviteAuditFailed = 34 // 新用户奖励活动审核不通过 + NewUserInviterAward = 35 // 新用户奖励活动邀请成功数达标 + PowerSupportSalary = 36 // 势力扶持工资领取 提醒 + CountryStarOrdinaryAward = 37 // 国家之星瓜分奖提醒 + GroupActivityRewardMsg = 38 // 群组活动钻石奖励提醒 + TemplateActAwardMsg = 39 // 通用模板活动奖励提醒 + TemplateSmsCode = 40 // 通用模板活动奖励提醒 + NewUserRegisterPush1 = 44 // 首次充值免费获得永久充值勋章!累积充值$50可申请特殊ID:ABBABB! + NewUserRegisterPush2 = 45 // 邀请朋友来Hilo,最高获得100,000钻石奖励! + NewUserRegisterPush3 = 46 // 举办首个活动,领取10,000钻石和35%奖杯奖励! + ActFruitPutRankAward = 47 // 水果机投入排行榜提醒领奖 +) + +type MsgSysUserType = mysql.Type + +const ( + //系统消息 + SysType MsgSysUserType = 1 + //小助手消息 + AssistantType MsgSysUserType = 2 +) + +//resMsgTransalte 中 msg_type 同 type, msg_type是属于一级类型 type属于二级类型。 msg_type 对应MsgReceiveType type:部分对应MsgUserRecordType MsgUserRecordType(应该是小助手的类型) +type MsgSysRecordType = mysql.Type + +const ( + //这个值木有意义, + SysMsgSysRecordType1 MsgSysRecordType = 1 + SysMsgSysRecordType2 MsgSysRecordType = 2 +) diff --git a/cv/group_power_cv/groupPower.go b/cv/group_power_cv/groupPower.go new file mode 100644 index 0000000..6953f63 --- /dev/null +++ b/cv/group_power_cv/groupPower.go @@ -0,0 +1,641 @@ +package group_power_cv + +import ( + "context" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/mylogrus" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/resource/redisCli" + "git.hilo.cn/hilo-common/utils" + "gorm.io/gorm" + "hilo-group/_const/enum/groupPower_e" + "hilo-group/_const/enum/group_e" + "hilo-group/_const/enum/res_e" + "hilo-group/_const/redis_key" + "hilo-group/cv/user_cv" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/group_m" + "hilo-group/myerr" + "sort" + "strconv" + "time" +) + +type CvGroupPowerTeam struct { + //上一周 + LastWeek CvGroupPowerSupportCount `json:"lastWeek"` + //这一周 + ThisWeek CvGroupPowerSupportCount `json:"thisWeek"` + //拥有者 userBase, 一般只有一个, + Owers []*user_cv.CvUserDetail `json:"owers"` + //助手 userBase + Assistants []*user_cv.CvUserDetail `json:"assistants"` +} + +func GetGroupPower(groupPowerId mysql.ID) (string, error) { + groupPower := groupPower_m.GroupPower{} + if err := mysql.Db.Model(&groupPower_m.GroupPower{}).First(&groupPower, &groupPowerId).Error; err != nil { + return "", myerr.WrapErr(err) + } + return groupPower.GroupUid, nil +} + +func GetGroupPowerGroupUids(groupPowerIds []mysql.ID) ([]string, error) { + groupPowers := []groupPower_m.GroupPower{} + if err := mysql.Db.Model(&groupPower_m.GroupPower{}).Where("id in (?)", groupPowerIds).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + groupUids := make([]string, 0, len(groupPowers)) + for i, _ := range groupPowers { + groupUids = append(groupUids, groupPowers[i].GroupUid) + } + + return groupUids, nil +} + +func GetCvGroupPowerTeam(myContext *mycontext.MyContext, groupPowerId mysql.ID, myUserId mysql.ID) (CvGroupPowerTeam, error) { + cvGroupPowerTeam := CvGroupPowerTeam{} + adminUserIds, err := GetCvGroupPowerAdmins(groupPowerId) + if err != nil { + return CvGroupPowerTeam{}, err + } + if owers, err := user_cv.GetUserDetailByIds(adminUserIds, myUserId); err != nil { + return CvGroupPowerTeam{}, err + } else { + cvGroupPowerTeam.Owers = owers + } + groupUid, err := GetGroupPower(groupPowerId) + if err != nil { + return CvGroupPowerTeam{}, err + } + assistantIds, err := group_m.FindRolesInGroup(mysql.Db, groupUid, group_e.GROUP_ADMIN) + if err != nil { + return CvGroupPowerTeam{}, err + } + if assistants, err := user_cv.GetUserDetailByIds(assistantIds, myUserId); err != nil { + return CvGroupPowerTeam{}, err + } else { + cvGroupPowerTeam.Assistants = assistants + } + + now := time.Now() + beginTime, endTime, _ := group_m.GetSupportLevelTime(now) + + //所有人 + //userIds, err := GetCvGroupPowerAllUsers(groupPowerId) + userIds, err := GetCvGroupPowerUsers(groupPowerId) + if err != nil { + return CvGroupPowerTeam{}, err + } + myContext.Log.Infof("GetCvGroupPowerTeam %d, this week users: %v", groupPowerId, userIds) + + // fixme: 2.18后,不需要这个了 thisWeek + if thisWeek, err := GetCvGroupPowerSupportCount(userIds, beginTime.Format(utils.DATE_FORMAT), endTime.Format(utils.DATE_FORMAT)); err != nil { + return CvGroupPowerTeam{}, err + } else { + cvGroupPowerTeam.ThisWeek = thisWeek + } + + //lastWeek + lastWeekUserIds, err := GetLastWeekGroupPowerUsers(groupPowerId) + myContext.Log.Infof("GetCvGroupPowerTeam %d, last week users: %v", groupPowerId, lastWeekUserIds) + + beginTime, endTime, _ = group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY)) + if lastWeek, err := GetCvGroupPowerSupportCount(lastWeekUserIds, beginTime.Format(utils.DATE_FORMAT), endTime.Format(utils.DATE_FORMAT)); err != nil { + return CvGroupPowerTeam{}, err + } else { + cvGroupPowerTeam.LastWeek = lastWeek + } + return cvGroupPowerTeam, nil +} + +//国家势力下,群组支持等级 +type CvGroupPowerSupportCount struct { + O uint `json:"o"` + N uint `json:"n"` + M uint `json:"m"` + L uint `json:"l"` + K uint `json:"k"` + J uint `json:"j"` + I uint `json:"i"` + H uint `json:"h"` + G uint `json:"g"` + F uint `json:"f"` + E uint `json:"e"` + D uint `json:"d"` + C uint `json:"c"` + B uint `json:"b"` + A uint `json:"a"` +} + +type CvGroupSupportGrade struct { + GroupUid string + Grade uint8 +} + +func GetCvGroupPowerSupportCount(groupOwnerId []mysql.ID, beginDate string, endDate string) (CvGroupPowerSupportCount, error) { + groupSupportGrades := []CvGroupSupportGrade{} + if err := mysql.Db.Table("group_support_result AS r").Select("r.group_uid, MAX(r.grade) AS grade"). + Joins("INNER JOIN group_info i ON i.im_group_id = r.group_uid"). + Where("i.`owner` IN ? AND r.period > ? AND r.period <= ?", groupOwnerId, beginDate, endDate). + Group("r.group_uid").Find(&groupSupportGrades).Error; err != nil { + return CvGroupPowerSupportCount{}, myerr.WrapErr(err) + } + + cvGroupPowerSupportCount := CvGroupPowerSupportCount{} + for _, r := range groupSupportGrades { + switch r.Grade { + case res_e.Agrade: + cvGroupPowerSupportCount.A = cvGroupPowerSupportCount.A + 1 + case res_e.Bgrade: + cvGroupPowerSupportCount.B = cvGroupPowerSupportCount.B + 1 + case res_e.Cgrade: + cvGroupPowerSupportCount.C = cvGroupPowerSupportCount.C + 1 + case res_e.Dgrade: + cvGroupPowerSupportCount.D = cvGroupPowerSupportCount.D + 1 + case res_e.Egrade: + cvGroupPowerSupportCount.E = cvGroupPowerSupportCount.E + 1 + case res_e.Fgrade: + cvGroupPowerSupportCount.F = cvGroupPowerSupportCount.F + 1 + case res_e.Ggrade: + cvGroupPowerSupportCount.G = cvGroupPowerSupportCount.G + 1 + case res_e.Hgrade: + cvGroupPowerSupportCount.H = cvGroupPowerSupportCount.H + 1 + case res_e.Igrade: + cvGroupPowerSupportCount.I = cvGroupPowerSupportCount.I + 1 + case res_e.Jgrade: + cvGroupPowerSupportCount.J = cvGroupPowerSupportCount.J + 1 + case res_e.Kgrade: + cvGroupPowerSupportCount.K = cvGroupPowerSupportCount.K + 1 + case res_e.Lgrade: + cvGroupPowerSupportCount.L = cvGroupPowerSupportCount.L + 1 + case res_e.Mgrade: + cvGroupPowerSupportCount.M = cvGroupPowerSupportCount.M + 1 + case res_e.Ngrade: + cvGroupPowerSupportCount.N = cvGroupPowerSupportCount.N + 1 + case res_e.Ograde: + cvGroupPowerSupportCount.O = cvGroupPowerSupportCount.O + 1 + } + } + return cvGroupPowerSupportCount, nil +} + +//获取国家势力的所有管理人 +func GetCvGroupPowerAdmins(groupPowerId uint64) ([]mysql.ID, error) { + groupPowers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + Role: groupPower_e.GroupPowerUserRoleMgr, + }).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + usreIds := make([]mysql.ID, 0, len(groupPowers)) + for i, _ := range groupPowers { + usreIds = append(usreIds, groupPowers[i].UserId) + } + return usreIds, nil +} + +//获取国家势力的所有用户(角色,用户) +func GetCvGroupPowerAllUsers(groupPowerId uint64) ([]mysql.ID, error) { + groupPowers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + }).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + usreIds := make([]mysql.ID, 0, len(groupPowers)) + for i, _ := range groupPowers { + usreIds = append(usreIds, groupPowers[i].UserId) + } + return usreIds, nil +} + +//获取国家势力的所有用户(角色,用户) +func GetCvGroupPowerUsers(groupPowerId uint64) ([]mysql.ID, error) { + groupPowers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + Role: groupPower_e.GroupPowerUserRoleUser, + }).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + usreIds := make([]mysql.ID, 0, len(groupPowers)) + for i, _ := range groupPowers { + usreIds = append(usreIds, groupPowers[i].UserId) + } + return usreIds, nil +} + +func BatchGetGroupPower(db *gorm.DB, userIds []uint64) (map[uint64]uint64, map[uint64]string, error) { + if len(userIds) <= 0 { + return nil, nil, nil + } + groupPowers, err := groupPower_m.GetGroupPowerMap(db, userIds) + if err != nil { + return nil, nil, err + } + + gpIds := make([]uint64, 0) + for _, i := range groupPowers { + gpIds = append(gpIds, i) + } + powerNames, err := groupPower_m.GetGroupPowerNames(db, gpIds) + if err != nil { + return nil, nil, err + } + groupPowerNames := make(map[mysql.ID]string, 0) + for i, g := range groupPowers { + groupPowerNames[i] = powerNames[g] + } + return groupPowers, groupPowerNames, nil +} + +//获取国家势力的所有用户数量 +func GetCvGroupPowerUserN(groupPowerId uint64) (int64, error) { + var count int64 + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + }).Count(&count).Error; err != nil { + return 0, myerr.WrapErr(err) + } + return count, nil +} + +//获取国家势力的所有用户数量 +func GetCvGroupPowerUserMapN(groupPowerIds []uint64) (map[uint64]uint64, error) { + + type GroupPowerUser struct { + GroupPowerId uint64 + N uint64 + } + groupPowerUsers := []GroupPowerUser{} + if err := mysql.Db.Raw("SELECT u.group_power_id, COUNT(1) as n from group_power_user u where u.group_power_id in (?) GROUP BY u.group_power_id", groupPowerIds).Scan(&groupPowerUsers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + + userN := map[uint64]uint64{} + + for _, r := range groupPowerUsers { + userN[r.GroupPowerId] = r.N + } + + return userN, nil +} + +// 查询上周国家势力的所有用户(角色:用户),当前名单+时间倒序还原 +func GetLastWeekGroupPowerUsers(groupPowerId uint64) ([]mysql.ID, error) { + groupPowers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + Role: groupPower_e.GroupPowerUserRoleUser, + }).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + users := make(map[mysql.ID]time.Time, 0) + for _, i := range groupPowers { + users[i.UserId] = i.CreatedTime + } + beginTime := utils.GetZeroTime(utils.GetMonday(time.Now())) + records, err := groupPower_m.GetGroupPowerUserLog(mysql.Db, groupPowerId, beginTime) + if err != nil { + return nil, err + } + userLogs := make(map[mysql.ID]string, 0) + for _, i := range records { + mylogrus.MyLog.Debugf("GetLastWeekGroupPowerUsers %d, user %d, %s, opType = %d", groupPowerId, i.UserId, i.CreatedTime.String(), i.OperateType) + if i.OperateType == groupPower_e.GroupPowerUserLogTypeUserJoin || i.OperateType == groupPower_e.GroupPowerUserLogTypeOwerJoin { + delete(users, i.UserId) + userLogs[i.UserId] += "-" + i.CreatedTime.String() + " " + } else if i.OperateType == groupPower_e.GroupPowerUserLogTypeUserLeave || i.OperateType == groupPower_e.GroupPowerUserLogTypeMgrLeave { + users[i.UserId] = i.CreatedTime + userLogs[i.UserId] += "+" + i.CreatedTime.String() + " " + } + } + mylogrus.MyLog.Infof("GetLastWeekGroupPowerUsers %d : %v", groupPowerId, userLogs) + + userIds := make([]mysql.ID, 0) + for u, _ := range users { + userIds = append(userIds, u) + } + return userIds, nil +} + +//分页获取国家势力的用户 +func GetCvGroupPowerUser(groupPowerId uint64, pageSize int, pageIndex int) ([]mysql.ID, error) { + groupPowers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{ + GroupPowerId: groupPowerId, + Role: groupPower_e.GroupPowerUserRoleUser, + }).Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&groupPowers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + // + usreIds := make([]mysql.ID, 0, len(groupPowers)) + for i, _ := range groupPowers { + usreIds = append(usreIds, groupPowers[i].UserId) + } + return usreIds, nil +} + +type CvGroupPowerDiamondTotal struct { + //势力ID + GroupPowerId mysql.ID `json:"groupPowerId"` + //名字 + Name string `json:"name"` + //头像 + FaceUrl string `json:"faceUrl"` + //钻石数量 + DiamondNum uint `json:"diamondNum"` + //用户数量 + UserN uint64 `json:"userN"` +} + +func GetCvGroupPowerDiamondTotalList(weekBeginTime time.Time, endTime time.Time, pageSize int, pageIndex int) ([]CvGroupPowerDiamondTotal, error) { + /* cvGroupPowerDiamondTotals := []CvGroupPowerDiamondTotal{} + if err := mysql.Db.Raw("SELECT t1.*, t2.diamond_num from (SELECT p.id as group_power_id, i.`name`, i.face_url from group_power p, group_info i where p.status = ? and p.group_uid = i.im_group_id) t1 LEFT JOIN (SELECT l.group_power_id, SUM(l.diamond_num) as diamond_num from group_power_diamond_log l where l.created_time >= ? AND l.created_time < ? GROUP BY l.group_power_id) t2 on t1.group_power_id = t2.group_power_id order by t2.diamond_num DESC, t1.group_power_id desc LIMIT ?, ?", groupPower_m2.GroupPowerUserHas, beginTime, endTime, (pageIndex-1)*pageSize, pageSize).Scan(&cvGroupPowerDiamondTotals).Error; err != nil { + return nil, myerr.WrapErr(err) + } + return cvGroupPowerDiamondTotals, nil*/ + + //用缓存 + rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(weekBeginTime.Format(utils.COMPACT_DATE_FORMAT)), 0, -1).Result() + if err != nil { + return nil, myerr.WrapErr(err) + } + groupPowerIds := make([]uint64, 0, len(rows)) + groupPowerDiamondMap := map[uint64]uint{} + for i, _ := range rows { + groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64) + if err != nil { + return nil, myerr.WrapErr(err) + } + groupPowerIds = append(groupPowerIds, groupPowerId) + groupPowerDiamondMap[groupPowerId] = uint(rows[i].Score) + } + //搜集所有的群组 + cvGroupPowerDiamondTotals := []CvGroupPowerDiamondTotal{} + if err := mysql.Db.Raw("SELECT p.id as group_power_id, i.`name`, i.face_url from group_power p, group_info i where p.status = ? and p.group_uid = i.im_group_id AND p.id in (?)", groupPower_e.GroupPowerUserHas, groupPowerIds).Scan(&cvGroupPowerDiamondTotals).Error; err != nil { + return nil, myerr.WrapErr(err) + } + //将分数放进去 + for i, r := range cvGroupPowerDiamondTotals { + cvGroupPowerDiamondTotals[i].DiamondNum = groupPowerDiamondMap[r.GroupPowerId] + } + //排序 + //从高到低排序 + sort.Slice(cvGroupPowerDiamondTotals, func(i, j int) bool { + return cvGroupPowerDiamondTotals[i].DiamondNum > cvGroupPowerDiamondTotals[j].DiamondNum + }) + + //总长度 + l := len(cvGroupPowerDiamondTotals) + if (pageIndex-1)*pageSize >= l { + return []CvGroupPowerDiamondTotal{}, nil + } else if pageIndex*pageSize > l { + //分页切片 + newGroupPowerDiamondTotal := cvGroupPowerDiamondTotals[(pageIndex-1)*pageSize : l] + return newGroupPowerDiamondTotal, nil + } else { + //分页切片 + newGroupPowerDiamondTotal := cvGroupPowerDiamondTotals[(pageIndex-1)*pageSize : pageIndex*pageSize] + return newGroupPowerDiamondTotal, nil + } + +} + +type powerInfoRec struct { + GroupPowerId uint64 + Name string + FaceUrl string +} + +func getPowerGroupMap(db *gorm.DB) (map[uint64]powerInfoRec, error) { + rows := make([]powerInfoRec, 0) + err := db.Model(&groupPower_m.GroupPower{}).Select("p.id AS group_power_id, i.name, i.face_url"). + Joins("AS p INNER JOIN group_info AS i ON p.group_uid = i.im_group_id"). + Where("p.status = ?", 1). // STATUS_IN_USE = 1;STATUS_UNUSED = 2 + Find(&rows).Error + if err != nil { + return nil, err + } + + powerInfo := make(map[uint64]powerInfoRec, 0) + for _, i := range rows { + powerInfo[i.GroupPowerId] = i + } + return powerInfo, nil +} + +type GroupPowerDiamondLog struct { + GroupPowerId uint64 + DiamondNum uint +} + +// 按时间范围计算势力流水 +/*func getPowerDiamondLogByRange(db *gorm.DB, beginTime, endTime time.Time) ([]GroupPowerDiamondLog, error) { + rows := make([]GroupPowerDiamondLog, 0) + err := db.Model(&GroupPowerDiamondLog{}).Select("group_power_id, SUM(diamond_num) as diamond_num"). + Where("created_time BETWEEN ? AND ?", beginTime, endTime). + Group("group_power_id").Order("diamond_num DESC").Find(&rows).Error + if err != nil { + return nil, err + } + return rows, nil +}*/ + +func getPowerDiamondLogByRange(weekBeginDate time.Time) ([]GroupPowerDiamondLog, error) { + rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(weekBeginDate.Format(utils.COMPACT_DATE_FORMAT)), 0, 3).Result() + if err != nil { + return nil, myerr.WrapErr(err) + } + logs := []GroupPowerDiamondLog{} + for i, _ := range rows { + groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64) + if err != nil { + return nil, myerr.WrapErr(err) + } + logs = append(logs, GroupPowerDiamondLog{ + GroupPowerId: groupPowerId, + DiamondNum: uint(rows[i].Score), + }) + } + return logs, err +} + +type GroupPowerTop struct { + ThisWeek []CvGroupPowerDiamondTotal `json:"thisWeek"` + LastWeek []CvGroupPowerDiamondTotal `json:"lastWeek"` +} + +func buildGroupPowerTop3(powerInfo map[uint64]powerInfoRec, diamonds []GroupPowerDiamondLog) []CvGroupPowerDiamondTotal { + // Disgusting: 按groupPowerId从大到小排序,以防diamond>0的势力不足3个的情况 + gpIds := make([]uint64, 0) + for _, i := range powerInfo { + gpIds = append(gpIds, i.GroupPowerId) + } + sort.Slice(gpIds, func(i, j int) bool { + return gpIds[i] > gpIds[j] + }) + + used := make(map[uint64]struct{}, 0) + result := make([]CvGroupPowerDiamondTotal, 0) + for _, i := range diamonds { + if e, ok := powerInfo[i.GroupPowerId]; ok { + result = append(result, CvGroupPowerDiamondTotal{ + GroupPowerId: i.GroupPowerId, + Name: e.Name, + FaceUrl: e.FaceUrl, + DiamondNum: i.DiamondNum, + }) + used[i.GroupPowerId] = struct{}{} + if len(result) >= 3 { + break + } + } + } + if len(result) < 3 { + for _, i := range gpIds { + if _, exists := used[i]; !exists { + if gi, ok := powerInfo[i]; ok { + result = append(result, CvGroupPowerDiamondTotal{ + GroupPowerId: i, + Name: gi.Name, + FaceUrl: gi.FaceUrl, + DiamondNum: 0, + }) + if len(result) >= 3 { + break + } + } + } + } + } + return result +} + +func GetGroupPowerTop3(model *domain.Model) (GroupPowerTop, error) { + result := GroupPowerTop{} + powerInfo, err := getPowerGroupMap(model.Db) + if err != nil { + return result, err + } + model.Log.Infof("GetGroupPowerTop3, powerInfo: %v", powerInfo) + + beginDate, endDate, err := GetWeekByNow() + if err != nil { + return result, err + } + + //diamonds, err := getPowerDiamondLogByRange(model.Db, beginDate, endDate) + diamonds, err := getPowerDiamondLogByRange(beginDate) + if err != nil { + return result, err + } + + result.ThisWeek = buildGroupPowerTop3(powerInfo, diamonds) + + endDate = beginDate + beginDate = endDate.AddDate(0, 0, -7) + + diamonds, err = getPowerDiamond(model, beginDate, endDate) + if err != nil { + return result, err + } + result.LastWeek = buildGroupPowerTop3(powerInfo, diamonds) + + return result, nil +} + +//当前日期的自然周 +func GetWeekByNow() (time.Time, time.Time, error) { + now := time.Now() + nowTime, err := time.ParseInLocation(utils.DATE_FORMAT, now.Format(utils.DATE_FORMAT), time.Local) + if err != nil { + return time.Time{}, time.Time{}, myerr.WrapErr(err) + } + beginDate := utils.GetMonday(nowTime) + return beginDate, now, nil +} + +func getPowerDiamond(model *domain.Model, beginTime, endTime time.Time) ([]GroupPowerDiamondLog, error) { + period := beginTime.Format(utils.DATE_FORMAT) + values, err := GetAllPowerDiamond(period) + + if err != nil { + return nil, err + } + model.Log.Infof("GetPowerDiamond, GET %s: %v", period, values) + + diamonds := make(map[uint64]uint, 0) + result := make([]GroupPowerDiamondLog, 0) + if len(values) > 0 { + powerIds := make([]uint64, 0) + for k, v := range values { + d, err := strconv.ParseUint(v, 10, 32) + if err == nil { + p, err := strconv.ParseUint(k, 10, 64) + if err == nil { + diamonds[p] = uint(d) + powerIds = append(powerIds, p) + } + } + } + // 排序 + sort.Slice(powerIds, func(i, j int) bool { + return diamonds[powerIds[i]] > diamonds[powerIds[j]] + }) + for _, i := range powerIds { + result = append(result, GroupPowerDiamondLog{ + GroupPowerId: i, + DiamondNum: diamonds[i], + }) + } + } else { + //d, err := getPowerDiamondLogByRange(model.Db, beginTime, endTime) + d, err := getPowerDiamondLogByRange(beginTime) + for _, i := range d { + diamonds[i.GroupPowerId] = i.DiamondNum + result = append(result, GroupPowerDiamondLog{ + GroupPowerId: i.GroupPowerId, + DiamondNum: i.DiamondNum, + }) + } + + ret, err := SaveAllPowerDiamond(period, diamonds) + model.Log.Infof("GetPowerDiamond SAVE ret = %d, err: %v", ret, err) + } + model.Log.Infof("GetPowerDiamond for %s, %v", period, result) + return result, nil +} + +func SaveAllPowerDiamond(period string, diamonds map[uint64]uint) (int64, error) { + values := make(map[string]interface{}, 0) + for p, d := range diamonds { + if d > 0 { + values[strconv.FormatUint(p, 10)] = d + } + } + if len(values) <= 0 { + return 0, nil + } + key := redis_key.GetPrefixGroupPowerDiamond(period) + ret, err := redisCli.GetRedis().HSet(context.Background(), key, values).Result() + + if err == nil { + // 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的 + redisCli.GetRedis().Expire(context.Background(), key, time.Hour) + } + return ret, err +} + +func GetAllPowerDiamond(period string) (map[string]string, error) { + key := redis_key.GetPrefixGroupPowerDiamond(period) + return redisCli.GetRedis().HGetAll(context.Background(), key).Result() +} diff --git a/cv/group_power_cv/group_power.go b/cv/group_power_cv/group_power.go deleted file mode 100644 index e17e00f..0000000 --- a/cv/group_power_cv/group_power.go +++ /dev/null @@ -1,31 +0,0 @@ -package group_power_cv - -import ( - "git.hilo.cn/hilo-common/resource/mysql" - "gorm.io/gorm" - "hilo-group/domain/model/groupPower_m" -) - -func BatchGetGroupPower(db *gorm.DB, userIds []uint64) (map[uint64]uint64, map[uint64]string, error) { - if len(userIds) <= 0 { - return nil, nil, nil - } - groupPowers, err := groupPower_m.GetGroupPowerMap(db, userIds) - if err != nil { - return nil, nil, err - } - - gpIds := make([]uint64, 0) - for _, i := range groupPowers { - gpIds = append(gpIds, i) - } - powerNames, err := groupPower_m.GetGroupPowerNames(db, gpIds) - if err != nil { - return nil, nil, err - } - groupPowerNames := make(map[mysql.ID]string, 0) - for i, g := range groupPowers { - groupPowerNames[i] = powerNames[g] - } - return groupPowers, groupPowerNames, nil -} diff --git a/cv/user_cv/user.go b/cv/user_cv/user.go index df3cbb2..4a6525d 100644 --- a/cv/user_cv/user.go +++ b/cv/user_cv/user.go @@ -2,6 +2,7 @@ package user_cv import ( "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/rpc" . "git.hilo.cn/hilo-common/utils" @@ -183,7 +184,7 @@ func GetUserTinyBy(user user_m.User) CvUserTiny { } func GetUserDetailMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUserDetail, error) { - cvUserDetails, err := getUserDetailByIds(userIds, myUserId) + cvUserDetails, err := GetUserDetailByIds(userIds, myUserId) if err != nil { return map[mysql.ID]*CvUserDetail{}, err } @@ -195,7 +196,7 @@ func GetUserDetailMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUs return mapIdUser, nil } -func getUserDetailByIds(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserDetail, error) { +func GetUserDetailByIds(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserDetail, error) { if len(userIds) == 0 { return nil, nil } @@ -899,3 +900,136 @@ func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, return cvUserDetail, nil } + +func GetUserBaseMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUserBase, error) { + userBases, err := GetUserBases(userIds, myUserId) + if err != nil { + return nil, err + } + //转换成map + mapIdUser := map[mysql.ID]*CvUserBase{} + for i := 0; i < len(userBases); i++ { + mapIdUser[*userBases[i].Id] = userBases[i] + } + return mapIdUser, nil +} + +//批量获取用户基本信息 +func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) { + if len(userIds) == 0 { + return []*CvUserBase{}, nil + } + var users []user_m.User + if err := mysql.Db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil { + return nil, myerr.WrapErr(err) + } + vips, err := user_m.BatchGetVips(userIds) + if err != nil { + return nil, myerr.WrapErr(err) + } + svips, err := rpc.MGetUserSvip(domain.CreateModelNil(), userIds) + if err != nil { + return nil, myerr.WrapErr(err) + } + + headwearMap, err := headwear_cv.BatchGetCvHeadwears(userIds) + if err != nil { + return nil, err + } + + logger := mylogrus.MyLog.WithField("func", "GetUserBases") + medals, err := user_m.BatchGetUserMedalMerge(logger, mysql.Db, userIds) + if err != nil { + return nil, err + } + + medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals) + if err != nil { + return nil, err + } + + up := user_m.UserProperty{} + rides, err := up.BatchGet(mysql.Db, userIds) + if err != nil { + return nil, err + } + + //rp := res_m.ResProperty{} + //properties, err := rp.GetAll(mysql.Db) + properties, err := property_cv.GetPropertyAll(mysql.Db) + if err != nil { + return nil, err + } + + nobles, err := noble_m.BatchGetActiveNoble(mysql.Db, userIds) + if err != nil { + return nil, err + } + + superManagerMap, err := user_m.GetSuperManagerMap(userIds) + if err != nil { + return nil, err + } + + cvUserBases := []*CvUserBase{} + for i := 0; i < len(users); i++ { + user := users[i] + invisible := IfLogout(user.LogoutTime) + invisibleAvatar := "" + invisibleNick := user.Code + //for _, p := range svips[user.ID].Privileges { + // if p.Type == 17 && p.UserSwitch { // 神秘人特权 + // invisible = true + // invisibleAvatar, invisibleNick = rpc.ReplaceSvipAvatarNick(invisibleAvatar, invisibleNick, svips[user.ID].Privileges) + // } + //} + cvUserBase := &CvUserBase{ + Id: &user.ID, + Avatar: StrNil(IfLogoutStr(invisible, invisibleAvatar, user.Avatar)), + DefaultAvatar: &user.DefaultAvatar, + ExternalId: StrToString(&user.ExternalId), + Nick: StrNil(IfLogoutNick(invisible, invisibleNick, user.Nick)), + Description: StrNil(IfLogoutStr(invisible, "", user.Description)), + Sex: TypeToUint8(&user.Sex), + Country: StrNil(user.Country), + CountryIcon: StrNil(user.CountryIcon), + Code: StrToString(&user.Code), + IsPrettyCode: user.IsPrettyCode(), + IsVip: vips[user.ID] != nil, + IsOfficialStaff: superManagerMap[user.ID], + Medals: IfLogoutMedals(invisible, []uint32{}, medals[user.ID]), + MedalInfo: IfLogoutMedalInfo(invisible, []medal_cv.CvMedal{}, medalInfo[user.ID]), + Ride: IfLogoutRide(IfLogout(user.LogoutTime), property_cv.CvProperty{}, property_cv.CvProperty{ + Id: rides[user.ID], + PicUrl: properties[rides[user.ID]].PicUrl, + EffectUrl: properties[rides[user.ID]].EffectUrl, + Using: true, + SenderAvatar: properties[rides[user.ID]].SenderAvatar, + ReceiverAvatar: properties[rides[user.ID]].ReceiverAvatar, + }), + Noble: noble_cv.CvNoble{ + Level: nobles[user.ID].Level, + EndTime: nobles[user.ID].EndTime.Unix(), + }, + } + if cvUserBase.Noble.Level <= 0 { + cvUserBase.Noble.EndTime = 0 + } + // + if headwear, flag := headwearMap[user.ID]; flag { + cvUserBase.Headwear = IfLogoutHeadwear(IfLogout(user.LogoutTime), nil, &headwear) + } + + if user.ID == myUserId { + cvUserBase.VipExpireTime = vips[user.ID] + cvUserBase.IsShowAge = TypeToUint8(&user.IsShowAge) + cvUserBase.Birthday = BirthdayToUint64(&user.Birthday) + } else if user.IsShowAge == mysql.OPEN { + cvUserBase.Birthday = BirthdayToUint64(&user.Birthday) + } + cvUserBase.Svip = svips[user.ID] + + cvUserBases = append(cvUserBases, cvUserBase) + } + return cvUserBases, nil +} diff --git a/domain/event/group_power_ev/groupPowerJoin.go b/domain/event/group_power_ev/groupPowerJoin.go new file mode 100644 index 0000000..56c53c5 --- /dev/null +++ b/domain/event/group_power_ev/groupPowerJoin.go @@ -0,0 +1,29 @@ +package group_power_ev + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" +) + +//注册监听 +var groupPowerJoinListen = new(domain.EventBase) + +type GroupPowerJoinEvent struct { + UserId mysql.ID + GroupPowerId mysql.ID +} + +//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。 +func AddGroupPowerJoinSync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventSync(groupPowerJoinListen, callback) +} + +//加入到异步操作中 +func AddGroupPowerJoinAsync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventAsync(groupPowerJoinListen, callback) +} + +//领域事件发布 +func PublishGroupPowerJoin(model *domain.Model, event interface{}) error { + return domain.PublishEvent(groupPowerJoinListen, model, event) +} diff --git a/domain/event/group_power_ev/groupPowerLeave.go b/domain/event/group_power_ev/groupPowerLeave.go new file mode 100644 index 0000000..fcad492 --- /dev/null +++ b/domain/event/group_power_ev/groupPowerLeave.go @@ -0,0 +1,29 @@ +package group_power_ev + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" +) + +type GroupPowerLeaveEvent struct { + UserId mysql.ID + GroupPowerId mysql.ID +} + +//注册监听 +var groupPowerLeaveListen = new(domain.EventBase) + +//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。 +func AddGroupPowerLeaveSync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventSync(groupPowerLeaveListen, callback) +} + +//加入到异步操作中 +func AddGroupPowerLeaveAsync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventAsync(groupPowerLeaveListen, callback) +} + +//领域事件发布 +func PublishGroupPowerLeave(model *domain.Model, event interface{}) error { + return domain.PublishEvent(groupPowerLeaveListen, model, event) +} diff --git a/domain/model/msg_m/msg.go b/domain/model/msg_m/msg.go new file mode 100644 index 0000000..b46c9a8 --- /dev/null +++ b/domain/model/msg_m/msg.go @@ -0,0 +1,54 @@ +package msg_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/sdk/emas" + "git.hilo.cn/hilo-common/utils" + "hilo-group/_const/enum/msg_e" +) + +type MsgUserRecord struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + Type msg_e.MsgUserRecordType + Nick mysql.Str + NickUserId mysql.ID //用户的别名 + DiamondIncome mysql.Str + DayNum mysql.Str //多少天 + PropertyUrl mysql.Str //道具地址 + BeanNum mysql.Str //多少豆子 + GroupCode mysql.Str //群组code +} + +type MsgReceive struct { + Type msg_e.MsgReceiveType `json:"type"` +} + +func NewUserRecord(model *domain.Model, userId mysql.ID, t msg_e.MsgUserRecordType, nick mysql.Str, nickUserId mysql.ID, diamondIncome mysql.Str, dayNum mysql.Str, propertyUrl mysql.Str, beanNum mysql.Str, groupCode mysql.Str) *MsgUserRecord { + return &MsgUserRecord{ + Model: model, + UserId: userId, + Type: t, + Nick: nick, + NickUserId: nickUserId, + DiamondIncome: diamondIncome, + DayNum: dayNum, + PropertyUrl: propertyUrl, + BeanNum: beanNum, + GroupCode: groupCode, + } +} + +//发给小助手的消息, 不需要抛出错误 +func SendEmasMsgAssistant(model *domain.Model, externalId string, deviceType string) error { + str, _ := utils.ToString(MsgReceive{ + Type: msg_e.UserMsgReceiveType, + }) + err := emas.SendMsg(externalId, deviceType, str) + if err != nil { + model.Log.Errorf("emas.SendMsg err:%v", err) + } + return nil +} diff --git a/domain/model/msg_m/repo.go b/domain/model/msg_m/repo.go new file mode 100644 index 0000000..b022833 --- /dev/null +++ b/domain/model/msg_m/repo.go @@ -0,0 +1,13 @@ +package msg_m + +import ( + "hilo-group/domain/model" + "hilo-group/myerr" +) + +func (msgUserRecord *MsgUserRecord) Persistent() error { + if err := model.Persistent(msgUserRecord.Db, msgUserRecord); err != nil { + return myerr.WrapErr(err) + } + return nil +} diff --git a/domain/service/event_s/event_init.go b/domain/service/event_s/event_init.go new file mode 100644 index 0000000..4e90774 --- /dev/null +++ b/domain/service/event_s/event_init.go @@ -0,0 +1,73 @@ +package event_s + +import ( + "git.hilo.cn/hilo-common/domain" + "hilo-group/_const/enum/msg_e" + "hilo-group/domain/event/group_power_ev" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/msg_m" + "hilo-group/domain/model/user_m" +) + +func EventInit() { + GroupPowerEvents() +} + +func GroupPowerEvents() { + //加入势力 + group_power_ev.AddGroupPowerJoinAsync(func(model *domain.Model, e interface{}) error { + event, ok := e.(*group_power_ev.GroupPowerJoinEvent) + if !ok { + model.Log.Errorf("AddGroupPowerJoinAsync event type err") + return nil + } + model.Log.Infof("msg AddGroupPowerJoinAsync UserId:%v, GroupPowerId:%v", event.UserId, event.GroupPowerId) + //获取势力主 + mgrUserId, err := groupPower_m.GetGroupPowerMgr(model, event.GroupPowerId) + if err != nil { + return err + } + mgrUser, err := user_m.GetUser(model, mgrUserId) + if err != nil { + return err + } + joinUser, err := user_m.GetUser(model, event.UserId) + if err != nil { + return err + } + if err := msg_m.NewUserRecord(model, mgrUser.ID, msg_e.GroupPowerUserJoin, joinUser.Nick, joinUser.ID, "", "", "", "", "").Persistent(); err != nil { + model.Log.Errorf("msg AddGroupPowerJoinAsync NewUserRecord err:%v", err) + return nil + } + msg_m.SendEmasMsgAssistant(model, mgrUser.ExternalId, mgrUser.DeviceType) + return nil + }) + //离开势力 + group_power_ev.AddGroupPowerLeaveAsync(func(model *domain.Model, e interface{}) error { + event, ok := e.(*group_power_ev.GroupPowerLeaveEvent) + if !ok { + model.Log.Errorf("AddGroupPowerLeaveAsync event type err") + return nil + } + model.Log.Infof("msg AddGroupPowerLeaveAsync UserId:%v, GroupPowerId:%v", event.UserId, event.GroupPowerId) + //获取势力主 + mgrUserId, err := groupPower_m.GetGroupPowerMgr(model, event.GroupPowerId) + if err != nil { + return err + } + mgrUser, err := user_m.GetUser(model, mgrUserId) + if err != nil { + return err + } + joinUser, err := user_m.GetUser(model, event.UserId) + if err != nil { + return err + } + if err := msg_m.NewUserRecord(model, mgrUser.ID, msg_e.GroupPowerUserLeave, joinUser.Nick, joinUser.ID, "", "", "", "", "").Persistent(); err != nil { + model.Log.Errorf("msg AddGroupPowerLeaveAsync NewUserRecord err:%v", err) + return nil + } + msg_m.SendEmasMsgAssistant(model, mgrUser.ExternalId, mgrUser.DeviceType) + return nil + }) +} diff --git a/domain/service/group_power_s/group_power.go b/domain/service/group_power_s/group_power.go new file mode 100644 index 0000000..63800af --- /dev/null +++ b/domain/service/group_power_s/group_power.go @@ -0,0 +1,68 @@ +package group_power_s + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-group/domain/event/group_power_ev" + "hilo-group/domain/model/groupPower_m" +) + +type GroupPowerService struct { + svc *domain.Service +} + +func NewGroupPowerService(myContext *mycontext.MyContext) *GroupPowerService { + svc := domain.CreateService(myContext) + return &GroupPowerService{svc} +} + +//用户加入国家势力 +func (s *GroupPowerService) GroupPowerUserJoin(groupPowerId mysql.ID, userId mysql.ID) error { + return s.svc.Transactional(func() error { + model := domain.CreateModelContext(s.svc.MyContext) + groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId) + if err != nil { + return err + } + groupPowerUser, err := groupPower.UserJoin(userId) + if err != nil { + return err + } + if err := groupPowerUser.Persistent(); err != nil { + return err + } + return group_power_ev.PublishGroupPowerJoin(model, &group_power_ev.GroupPowerJoinEvent{ + UserId: userId, + GroupPowerId: groupPowerId, + }) + }) +} + +//用户退出国家势力 +func (s *GroupPowerService) GroupPowerUserLeave(groupPowerId mysql.ID, userId mysql.ID) (int, error) { + remainSeconds := 0 + err := s.svc.Transactional(func() error { + model := domain.CreateModelContext(s.svc.MyContext) + groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId) + if err != nil { + return err + } + groupPowerUser, timeDiff, err := groupPower.UserLeave(userId) + if err != nil { + if timeDiff > 0 { + remainSeconds = int(timeDiff.Seconds()) + return err + } + return err + } + if err := groupPowerUser.Persistent(); err != nil { + return err + } + return group_power_ev.PublishGroupPowerLeave(model, &group_power_ev.GroupPowerLeaveEvent{ + UserId: userId, + GroupPowerId: groupPowerId, + }) + }) + return remainSeconds, err +} diff --git a/go.mod b/go.mod index af23d40..f2471da 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274 // indirect github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect github.com/bluele/gcache v0.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -40,6 +41,7 @@ require ( github.com/jinzhu/copier v0.3.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/joho/godotenv v1.3.0 // indirect github.com/json-iterator/go v1.1.9 // indirect github.com/leodido/go-urn v1.2.0 // indirect diff --git a/go.sum b/go.sum index 37fa49b..64bc2cc 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274 h1:u48e7I7h/BY5uDP8xiIFNaUkdTVk7hjj/Sucg8FrxNU= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= @@ -90,6 +92,7 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -115,6 +118,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.7.0 h1:tGs8Oep67r8CcA2Ycmb/8BLBcJ70St44mF2X10a/qPg= github.com/hashicorp/consul/api v1.7.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= @@ -151,12 +155,15 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -222,6 +229,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -316,6 +325,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b h1:/mJ+GKieZA6hFDQGdWZrjj4AXPl5ylY+5HusG80roy0= @@ -358,6 +368,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -368,6 +379,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.4.3 h1:/JhWJhO2v17d8hjApTltKNADm7K7YI2ogkR7avJUL3k= gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= diff --git a/main.go b/main.go index 942ad89..d91c471 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "git.hilo.cn/hilo-common/resource/consul" + "hilo-group/domain/service/event_s" "hilo-group/route" ) @@ -14,7 +15,7 @@ const ( func main() { //cron.Init() // 开启定时任务 - //event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) + event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) r := route.InitRouter() // 注册路由 consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册 r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务 diff --git a/myerr/bizerr/bizCode.go b/myerr/bizerr/bizCode.go index 31bf7dc..24cd93c 100644 --- a/myerr/bizerr/bizCode.go +++ b/myerr/bizerr/bizCode.go @@ -49,6 +49,7 @@ var ( GroupPowerHasJoinOther = myerr.NewBusinessCode(15001, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了其它国家势力 GroupPowerHasJoinMy = myerr.NewBusinessCode(15002, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了该国家势力 GroupPowerOwnerLeave = myerr.NewBusinessCode(15003, "power owner cannot exit", myerr.BusinessData{}) // 势力主不能退出 + GroupPowerNotExist = myerr.NewBusinessCode(15004, "国家势力不存在", myerr.BusinessData{}) // 国家势力不存在 GroupPowerNoOwner = myerr.NewBusinessCode(15005, "power owner not exits or unique", myerr.BusinessData{}) // 国家势力主不存在或不唯一 GroupPowerStayTooShort = myerr.NewBusinessCode(15006, "You joined this power not more than 10 days ago", myerr.BusinessData{}) // 加入国家势力不超过10天 diff --git a/route/group_power_r/group_power.go b/route/group_power_r/group_power.go new file mode 100644 index 0000000..1b3320d --- /dev/null +++ b/route/group_power_r/group_power.go @@ -0,0 +1,694 @@ +package group_power_r + +import ( + "context" + "fmt" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/resource/redisCli" + "git.hilo.cn/hilo-common/utils" + "github.com/gin-gonic/gin" + "hilo-group/_const/enum/groupPower_e" + "hilo-group/_const/enum/group_e" + "hilo-group/_const/enum/msg_e" + "hilo-group/_const/redis_key" + "hilo-group/cv/group_cv" + "hilo-group/cv/group_power_cv" + "hilo-group/cv/medal_cv" + "hilo-group/cv/user_cv" + "hilo-group/domain/cache/res_c" + "hilo-group/domain/model/game_m" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/group_m" + "hilo-group/domain/model/res_m" + "hilo-group/domain/model/rocket_m" + "hilo-group/domain/model/user_m" + "hilo-group/domain/service/group_power_s" + "hilo-group/domain/service/group_s" + "hilo-group/myerr" + "hilo-group/myerr/bizerr" + "hilo-group/req" + "hilo-group/resp" + "sort" + "strconv" + "strings" + "time" +) + +// @Tags 国家势力 +// @Summary 加入国家势力 +// @Accept application/x-www-form-urlencoded +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId formData int true "国家势力Id" +// @Success 200 +// @Router /v1/groupPower/user [post] +func GroupPowerJoin(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + groupPowerId, err := strconv.ParseUint(c.PostForm("groupPowerId"), 10, 64) + if err != nil { + return myContext, err + } + //获取用户 + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + if err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserJoin(groupPowerId, userId); err != nil { + return myContext, err + } + resp.ResponseOk(c, nil) + return myContext, nil +} + +// @Tags 国家势力 +// @Summary 退出国家势力 +// @Accept application/x-www-form-urlencoded +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId path int true "国家势力ID" +// @Success 200 +// @Router /v1/groupPower/user/{groupPowerId} [delete] +func GroupPowerLeave(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64) + if err != nil { + return myContext, err + } + //获取用户 + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + remainSeconds, err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserLeave(groupPowerId, userId) + if err != nil { + if remainSeconds == 0 { + return myContext, err + } + + model := domain.CreateModelContext(myContext) + + user, newErr := user_m.GetUser(model, userId) + if newErr != nil { + return myContext, newErr + } else if user == nil { + return myContext, err + } else { + text := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_LEAVE_POWER, Language: user.Language} + if text.Get(model.Db) == nil { + dayLimit := "0" + day, sTime := formatSeconds(remainSeconds) + sDay := fmt.Sprintf("%d", day) + errmsg := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(text.Content, "%d", dayLimit), "%s", sDay), "xx:xx:xx", sTime) + return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupPowerStayTooShort.GetCode(), errmsg, myerr.BusinessData{}) + } else { + return myContext, err + } + } + } + resp.ResponseOk(c, nil) + return myContext, nil +} + +func formatSeconds(seconds int) (int, string) { + sec := seconds % 60 + minute := seconds / 60 + hour := minute / 60 + minute %= 60 + day := hour / 24 + hour %= 24 + sTime := fmt.Sprintf("%02d:%02d:%02d", hour, minute, sec) + return day, sTime +} + +// @Tags 国家势力 +// @Summary 国家势力标题页 +// @Accept application/x-www-form-urlencoded +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId path int true "国家势力ID" +// @Success 200 {object} cv.GroupPowerTitle +// @Router /v1/groupPower/title/{groupPowerId} [get] +func GetGroupPowerTitle(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64) + if err != nil { + return myContext, err + } + + myUserId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + + model := domain.CreateModelContext(myContext) + + groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId) + if err != nil { + return myContext, err + } + + if groupPower == nil { + return myContext, bizerr.GroupPowerNotExist + } + + gi, err := group_m.GetGroupInfo(model, groupPower.GroupUid) + if err != nil { + return myContext, err + } + if gi == nil { + return myContext, bizerr.GroupNotFound + } + gpu := groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId} + count, err := gpu.GetCount(model.Db) + if err != nil { + return myContext, err + } + + gpu = groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId, Role: groupPower_e.GroupPowerUserRoleMgr} + records, err := gpu.Get(model.Db) + if err != nil { + return myContext, err + } + if len(records) != 1 { + return myContext, bizerr.GroupPowerNoOwner + } + owner := records[0].UserId + userIds := []uint64{owner} + + assistants, err := group_m.FindRolesInGroup(model.Db, groupPower.GroupUid, group_e.GROUP_ADMIN) + if err != nil { + return myContext, err + } + + userIds = append(userIds, assistants...) + users, err := user_cv.GetUserBaseMap(userIds, myUserId) + if err != nil { + return myContext, err + } + + result := group_cv.GroupPowerTitle{ + Id: groupPowerId, + Name: gi.Name, + GroupId: gi.TxGroupId, + Avatar: gi.FaceUrl, + MemberNum: count, + } + + if users[owner] != nil { + result.Owner = *users[owner] + } + + // FIXME:排序规则是什么? + for _, i := range assistants { + if users[i] != nil { + result.Assistants = append(result.Assistants, *users[i]) + } + } + + if len(result.Assistants) > 4 { + result.Assistants = result.Assistants[0:4] + } + + gp, err := groupPower_m.GetGroupPowerUserOrNil(model, myUserId) + if err != nil { + return myContext, err + } + if gp != nil && gp.GroupPowerId == groupPowerId { + result.IsMyGroupPower = true + } else { + result.IsMyGroupPower = false + } + + resp.ResponseOk(c, result) + return myContext, nil +} + +// @Tags 国家势力 +// @Summary 国家势力成员群组 +// @Accept application/x-www-form-urlencoded +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param pageSize query int false "分页大小 默认:10" default(10) +// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1) +// @Param groupPowerId path int true "国家势力ID" +// @Success 200 {object} cv.PopularGroupInfo +// @Router /v1/groupPower/group/{groupPowerId} [get] +func GetGroupPowerGroups(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + + myUserId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil || pageSize <= 0 { + pageSize = 10 + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil || pageIndex <= 0 { + pageIndex = 1 + } + + groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64) + if err != nil { + return myContext, err + } + + model := domain.CreateModelContext(myContext) + + groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId) + if err != nil { + return myContext, err + } + + if groupPower == nil { + return myContext, bizerr.GroupPowerNotExist + } + + gpu := groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId} + records, err := gpu.Get(model.Db) + if err != nil { + return myContext, err + } + members := make([]uint64, 0) + for _, i := range records { + members = append(members, i.UserId) + } + groupMap, err := group_m.FindGroupByOwners(model.Db, members) + if err != nil { + return myContext, err + } + + groupList := make([]*group_m.GroupInfo, 0) + groupIds := make([]string, 0) + visitCount := make(map[string]int64, 0) + for _, i := range members { + if g, ok := groupMap[i]; ok { + groupList = append(groupList, &g) + groupIds = append(groupIds, g.ImGroupId) + if count, err := group_m.GetRoomVisitCount(g.ImGroupId); err == nil { + visitCount[g.ImGroupId] = count + } + } + } + model.Log.Infof("GetGroupPowerGroups, members: %v, groupMap: %v, groupList %v", members, groupMap, groupList) + + // 获取麦上有人的所有群组 + micGroupList, err := group_m.GetMicHasInGroups() + if err != nil { + return myContext, err + } + micGroupMap := make(map[string]bool, 0) + for _, i := range micGroupList { + micGroupMap[i] = true + } + + supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap() + if err != nil { + return myContext, err + } + + roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) + if err != nil { + return myContext, err + } + model.Log.Infof("GetGroupPowerGroups, roomMicUserMap : %v", roomMicUserMap) + + sort.Slice(groupList, func(i, j int) bool { + gi := groupList[i].ImGroupId + gj := groupList[j].ImGroupId + if micGroupMap[gi] == true && micGroupMap[gj] == false { + return true + } else if micGroupMap[gi] == false && micGroupMap[gj] == true { + return false + } + if supportLevels[gi] > supportLevels[gj] { + return true + } else if supportLevels[gi] < supportLevels[gj] { + return false + } + if len(roomMicUserMap[gi]) > len(roomMicUserMap[gj]) { + return true + } else if len(roomMicUserMap[gi]) < len(roomMicUserMap[gj]) { + return false + } + if visitCount[gi] > visitCount[gj] { + return true + } else if visitCount[gi] < visitCount[gj] { + return false + } + + // * Final resort: 群组CODE,短号优先,然后按字母序 + return len(groupList[i].Code) < len(groupList[j].Code) || len(groupList[i].Code) == len(groupList[j].Code) && groupList[i].Code < groupList[j].Code + }) + + // for pretty log + // ^ 麦上有人 + //logstr := "" + //for _, i := range groupList { + //hotGroupList = append(hotGroupList, groups[i]) + //prefix := " " + //if len(roomMicUserMap[i.ImGroupId]) > 0 { + // prefix += "^" + //} + //logstr += prefix + i.ImGroupId + ":" + i.Code + ":" + strconv.Itoa(int(supportLevels[i.ImGroupId])) + + // ":" + strconv.Itoa(len(roomMicUserMap[i.ImGroupId])) + ":" + strconv.Itoa(int(visitCount[i.ImGroupId])) + //} + total := len(groupList) + model.Log.Infof("GetGroupPowerGroups: GroupList size = %d", total) + + result := make([]group_cv.PopularGroupInfo, 0) + + beginPos := pageSize * (pageIndex - 1) + endPos := pageSize * pageIndex + if beginPos < total { + if endPos > total { + endPos = total + } + + groupIds := make([]string, 0) + owners := make([]uint64, 0) + for _, i := range groupList[beginPos:endPos] { + groupIds = append(groupIds, i.ImGroupId) + owners = append(owners, i.Owner) + } + powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + if err != nil { + return myContext, err + } + groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds) + if err != nil { + return myContext, err + } + resMedal, err := res_m.MedalGetAllMap(model.Db) + if err != nil { + return myContext, err + } + + model.Log.Infof("GetGroupPowerGroups: final start = %d, end = %d, %v", beginPos, endPos, groupIds) + + /* txGroupInfoMap, err := cv.BatchGetGroupInfo(model, groupIds, false) + if err != nil { + return myContext, err + }*/ + + countryInfo, err := res_c.GetCountryIconMap(model) + if err != nil { + return myContext, err + } + + uids := make([]uint64, 0) + micUsersMap := make(map[string][]uint64, 0) + for _, i := range groupList[beginPos:endPos] { + // 规则:麦上够4个就全用;全空的话,用群主补 + u := roomMicUserMap[i.ImGroupId] + if len(u) >= 4 { + micUsersMap[i.ImGroupId] = u[0:4] + } else if len(u) > 0 { + micUsersMap[i.ImGroupId] = u + } else { + micUsersMap[i.ImGroupId] = []uint64{i.Owner} + } + uids = append(uids, micUsersMap[i.ImGroupId]...) + } + + uids = utils.UniqueSliceUInt64(uids) + userTiny, err := user_cv.GetUserTinyMap(uids) + if err != nil { + return myContext, err + } + + rr := rocket_m.RocketResult{} + maxStageMap, err := rr.GetMaxStage(mysql.Db, groupIds) + if err != nil { + return myContext, err + } + + roomCount, err := group_m.BatchGetRoomCount(model, groupIds) + if err != nil { + return nil, err + } + // 正在进行的游戏 + games := game_m.GetNotEndGamesMap(model) + + for _, i := range groupList[beginPos:endPos] { + micUsers := make([]user_cv.CvUserTiny, 0) + for _, j := range micUsersMap[i.ImGroupId] { + micUsers = append(micUsers, userTiny[j]) + } + + var maxStage *uint16 = nil + if s, ok := maxStageMap[i.ImGroupId]; ok { + maxStage = &s + } + + medals := make([]medal_cv.PicElement, 0) + if m, ok := groupMedals[i.ImGroupId]; ok { + for _, j := range m { + mId := uint32(j) + if e, ok := resMedal[mId]; ok { + medals = append(medals, medal_cv.PicElement{ + PicUrl: e.PicUrl, + }) + } + } + } + // 补上房间流水勋章 + var pe *medal_cv.PicElement + _, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId) + if err != nil { + model.Log.Infof("GetGroupPowerGroups: GetGroupConsumeMedal: %s", err.Error()) + } else if pe != nil { + medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl}) + } + + var password *string = nil + if len(i.Password) > 0 && i.Owner != myUserId { + emptyStr := "" + password = &emptyStr + } + + result = append(result, group_cv.PopularGroupInfo{ + GroupInfo: group_cv.GroupInfo{ + GroupBasicInfo: group_cv.GroupBasicInfo{ + GroupId: i.TxGroupId, + Name: i.Name, + Introduction: i.Introduction, + Notification: i.Notification, + FaceUrl: i.FaceUrl, + Code: i.Code, + CountryIcon: countryInfo[i.Country], + Password: password, + SupportLevel: supportLevels[i.ImGroupId], + GroupInUserDuration: visitCount[i.ImGroupId], + MicNumType: int(i.MicNumType), + GroupMedals: medals, + }, + HasOnMic: len(roomMicUserMap[i.ImGroupId]) > 0, + GroupPowerId: powerIds[i.Owner], + GroupPowerName: powerNames[i.Owner], + }, + MicUsers: micUsers, + RoomUserCount: uint(roomCount[i.ImGroupId]), + MaxStage: maxStage, + GameTypes: games[i.TxGroupId], + }) + } + } + + resp.ResponseOk(c, result) + return myContext, nil +} + +// @Tags 国家势力 +// @Summary 国家势力团队信息 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId query int true "国家势力ID" +// @Success 200 {object} cv.CvGroupPowerTeam +// @Router /v1/groupPower/team [get] +func GroupPowerTeam(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + groupPowerId, err := strconv.ParseUint(c.Query("groupPowerId"), 10, 64) + if err != nil { + return myContext, err + } + usreId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + cvGroupPowerTeam, err := group_power_cv.GetCvGroupPowerTeam(myContext, groupPowerId, usreId) + if err != nil { + return myContext, err + } + resp.ResponseOk(c, cvGroupPowerTeam) + return myContext, nil +} + +// @Tags 国家势力 +// @Summary 榜单排行榜,这周 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param type query int true "week:1:thisWeek 2:lastWeek" Enums(1,2) +// @Param pageSize query int true "分页大小 默认:10" default(10) +// @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1) +// @Success 200 {object} cv.CvGroupPowerDiamondTotal +// @Router /v1/groupPower/billboard/week [get] +func GroupPowerBillboardWeek(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil { + pageSize = 10 + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil { + pageIndex = 1 + } + t, err := strconv.ParseUint(c.Query("type"), 10, 64) + if err != nil { + return myContext, err + } + now := time.Now() + monday := utils.GetMonday(now) + midnight := time.Date(monday.Year(), monday.Month(), monday.Day(), 0, 0, 0, 0, time.Local) + var beginTime, endTime time.Time + if t == 1 { + endTime = now + beginTime = midnight + } else if t == 2 { + endTime = midnight + beginTime = midnight.AddDate(0, 0, -7) + } else { + return myContext, myerr.NewSysError("type 参数错误") + } + cvGroupPowerDiamondTotals, err := group_power_cv.GetCvGroupPowerDiamondTotalList(beginTime, endTime, pageSize, pageIndex) + if err != nil { + return myContext, err + } + + ids := make([]uint64, 0, len(cvGroupPowerDiamondTotals)) + for i, _ := range cvGroupPowerDiamondTotals { + ids = append(ids, cvGroupPowerDiamondTotals[i].GroupPowerId) + } + + userMap, err := group_power_cv.GetCvGroupPowerUserMapN(ids) + if err != nil { + return myContext, nil + } + + for i, _ := range cvGroupPowerDiamondTotals { + cvGroupPowerDiamondTotals[i].UserN = userMap[cvGroupPowerDiamondTotals[i].GroupPowerId] + } + + resp.ResponseOk(c, cvGroupPowerDiamondTotals) + return myContext, nil +} + +type ReturnGroupPowerBillboardOwnerWeek struct { + User user_cv.CvUserDetail `json:"user"` + Diamond uint `json:"diamond"` +} + +// @Tags 国家势力 +// @Summary 榜单排行榜,这周,上周,top3,势力主的信息 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param type query int true "week:1:thisWeek 2:lastWeek" Enums(1,2) +// @Success 200 {object} ReturnGroupPowerBillboardOwnerWeek +// @Router /v1/groupPower/billboard/owner/week [get] +func GroupPowerBillboardOwnerWeek(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + t, err := strconv.ParseUint(c.Query("type"), 10, 64) + if err != nil { + return myContext, err + } + now := time.Now() + monday := utils.GetMonday(now) + midnight := time.Date(monday.Year(), monday.Month(), monday.Day(), 0, 0, 0, 0, time.Local) + //var beginTime, endTime time.Time + var beginTime time.Time + if t == 1 { + //endTime = now + beginTime = midnight + } else if t == 2 { + //endTime = midnight + beginTime = midnight.AddDate(0, 0, -7) + } else { + return myContext, myerr.NewSysError("type 参数错误") + } + + type R struct { + DiamondNum uint + UserId uint64 + } + rs := []R{} + //fixme:解决性能问题. + /* if err := mysql.Db.Raw("SELECT SUM(l.diamond_num) AS diamond_num, (SELECT u.user_id from group_power_user u where u.group_power_id = l.group_power_id and u.role = ?) as user_id FROM group_power_diamond_log l, group_power p WHERE l.group_power_id = p.id and p.status = ? and l.created_time >= ? AND l.created_time < ? GROUP BY l.group_power_id ORDER BY diamond_num DESC LIMIT 3", groupPower_m2.GroupPowerUserRoleMgr, groupPower_m2.GroupPowerUserHas, beginTime, endTime).Scan(&rs).Error; err != nil { + return myContext, err + }*/ + //用缓存 + rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(beginTime.Format(utils.COMPACT_DATE_FORMAT)), 0, -1).Result() + if err != nil { + return nil, myerr.WrapErr(err) + } + groupPowerIds := make([]uint64, 0, len(rows)) + for i, _ := range rows { + groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64) + if err != nil { + return nil, myerr.WrapErr(err) + } + groupPowerIds = append(groupPowerIds, groupPowerId) + } + //搜集所有的群组(有效) + 群组管理人 + groupPowerUsers := []groupPower_m.GroupPowerUser{} + if err := mysql.Db.Raw("SELECT u.user_id, u.group_power_id FROM group_power_user u, group_power p WHERE u.group_power_id = p.id AND u.role = ? and p.status = ? and p.id in (?)", groupPower_e.GroupPowerUserRoleMgr, groupPower_e.GroupPowerUserHas, groupPowerIds).Scan(&groupPowerUsers).Error; err != nil { + return nil, myerr.WrapErr(err) + } + //转换成map + groupPowerIdUserIdMap := map[uint64]uint64{} + for _, r := range groupPowerUsers { + groupPowerIdUserIdMap[r.GroupPowerId] = r.UserId + } + //只需找到前3个 + for i, _ := range rows { + groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64) + if err != nil { + return nil, myerr.WrapErr(err) + } + if len(rs) >= 3 { + break + } else if userId, flag := groupPowerIdUserIdMap[groupPowerId]; flag { + rs = append(rs, R{ + DiamondNum: uint(rows[i].Score), + UserId: userId, + }) + } + } + + userIds := make([]uint64, 0, 64) + for i, _ := range rs { + userIds = append(userIds, rs[i].UserId) + } + + userMap, err := user_cv.GetUserDetailMap(userIds, userId) + if err != nil { + return myContext, err + } + + results := make([]ReturnGroupPowerBillboardOwnerWeek, 0, len(userIds)) + for i, _ := range rs { + results = append(results, ReturnGroupPowerBillboardOwnerWeek{ + User: *userMap[rs[i].UserId], + Diamond: rs[i].DiamondNum, + }) + } + resp.ResponseOk(c, results) + return myContext, nil +} diff --git a/route/router.go b/route/router.go index ba730e3..3c05428 100644 --- a/route/router.go +++ b/route/router.go @@ -5,6 +5,7 @@ import ( ginSwagger "github.com/swaggo/gin-swagger" "github.com/swaggo/gin-swagger/swaggerFiles" _ "hilo-group/docs" + "hilo-group/route/group_power_r" "hilo-group/route/group_r" ) @@ -110,5 +111,16 @@ func InitRouter() *gin.Engine { //imGroup.GET("/medal/all", wrapper(GroupMedalAll)) //imGroup.GET("/medal/room", wrapper(GetRoomMedal)) } + + groupPower := v1.Group("/groupPower") + { + groupPower.POST("/user", wrapper(group_power_r.GroupPowerJoin)) + groupPower.DELETE("/user/:groupPowerId", wrapper(group_power_r.GroupPowerLeave)) + groupPower.GET("/title/:groupPowerId", wrapper(group_power_r.GetGroupPowerTitle)) + groupPower.GET("/group/:groupPowerId", wrapper(group_power_r.GetGroupPowerGroups)) + groupPower.GET("/team", wrapper(group_power_r.GroupPowerTeam)) + groupPower.GET("/billboard/week", wrapper(group_power_r.GroupPowerBillboardWeek)) + groupPower.GET("/billboard/owner/week", wrapper(group_power_r.GroupPowerBillboardOwnerWeek)) + } return r } -- 2.22.0