From 009969820c77795733b935767648b242938c5320 Mon Sep 17 00:00:00 2001 From: hujiebin Date: Tue, 20 Jun 2023 18:38:32 +0800 Subject: [PATCH] Feature/user detail --- _const/enum/country_e/enum.go | 25 ++ _const/enum/groupPower_e/enum.go | 60 ++++ _const/enum/group_e/enum.go | 101 ++++++ _const/enum/user_e/user.go | 48 ++- _const/redis_key/group_k/keys.go | 8 + _const/redis_key/user_k/keys.go | 8 + cv/user_cv/user.go | 185 +++++++++-- domain/model/country_m/country_mgr.go | 40 +++ domain/model/groupPower_m/groupPower.go | 84 +++++ domain/model/group_m/groupInfo.go | 109 +++++++ domain/model/group_m/role.go | 80 +++++ domain/model/group_m/room.go | 58 ++++ domain/model/tim_m/user.go | 27 ++ domain/model/user_m/count.go | 19 ++ domain/model/user_m/like.go | 104 +++++++ domain/model/user_m/relation.go | 121 ++++++++ domain/model/user_m/superManager.go | 24 +- domain/model/user_m/userBindInfo.go | 38 +++ domain/model/user_m/userOauth.go | 35 +++ domain/model/user_m/user_trade_union.go | 44 +++ domain/model/visit_m/repo.go | 7 + domain/model/visit_m/visit.go | 36 +++ domain/service/cp_s/cp.go | 83 +++++ domain/service/user_s/user.go | 396 ++++++++++++++++++++++++ domain/service/user_s/util.go | 98 ++++++ route/router.go | 2 + route/user_r/user.go | 108 +++++++ 27 files changed, 1914 insertions(+), 34 deletions(-) create mode 100644 _const/enum/country_e/enum.go create mode 100644 _const/enum/groupPower_e/enum.go create mode 100644 _const/enum/group_e/enum.go create mode 100644 _const/redis_key/group_k/keys.go create mode 100644 domain/model/country_m/country_mgr.go create mode 100644 domain/model/groupPower_m/groupPower.go create mode 100644 domain/model/group_m/groupInfo.go create mode 100644 domain/model/group_m/role.go create mode 100644 domain/model/group_m/room.go create mode 100644 domain/model/tim_m/user.go create mode 100644 domain/model/user_m/count.go create mode 100644 domain/model/user_m/like.go create mode 100644 domain/model/user_m/relation.go create mode 100644 domain/model/user_m/userBindInfo.go create mode 100644 domain/model/user_m/userOauth.go create mode 100644 domain/model/user_m/user_trade_union.go create mode 100644 domain/model/visit_m/repo.go create mode 100644 domain/model/visit_m/visit.go create mode 100644 domain/service/cp_s/cp.go create mode 100644 domain/service/user_s/user.go create mode 100644 domain/service/user_s/util.go create mode 100644 route/user_r/user.go diff --git a/_const/enum/country_e/enum.go b/_const/enum/country_e/enum.go new file mode 100644 index 0000000..1f09c39 --- /dev/null +++ b/_const/enum/country_e/enum.go @@ -0,0 +1,25 @@ +package country_e + +import "git.hilo.cn/hilo-common/resource/mysql" + +// 国家角色 +type CountryMgrRole mysql.Type + +const ( + // 国家管理员 + CountryMgrManager CountryMgrRole = 1 + // 国家助理 + CountryMgrAssistant CountryMgrRole = 2 +) + +// 角色权限 +type ManagerPrivilegeItem mysql.Type + +const ( + // 重置用户头像 + ManagerPrivilegeItemResetAvatar ManagerPrivilegeItem = 1 + // 重置群组头像 + ManagerPrivilegeItemResetFaceUrl ManagerPrivilegeItem = 2 + // 删除广播 + ManagerPrivilegeItemDeleteGlobalBroadcast ManagerPrivilegeItem = 3 +) diff --git a/_const/enum/groupPower_e/enum.go b/_const/enum/groupPower_e/enum.go new file mode 100644 index 0000000..12a90f4 --- /dev/null +++ b/_const/enum/groupPower_e/enum.go @@ -0,0 +1,60 @@ +package groupPower_e + +import "git.hilo.cn/hilo-common/resource/mysql" + +//国家势力状态 +type GroupPowerStatus = mysql.Type + +const ( + //上架 + GroupPowerUserHas GroupPowerStatus = 1 + //未上架 + GroupPowerUserNo GroupPowerStatus = 2 + //解散 + GroupPowerDissolve GroupPowerStatus = 3 +) + +//国家势力用户角色 +type GroupPowerUserRole = mysql.Type + +const ( + // 普通用户 + GroupPowerUserRoleUser GroupPowerUserRole = 1 + // 势力主 + GroupPowerUserRoleMgr GroupPowerUserRole = 2 + // 管理员 + GroupPowerUserRoleAdmin GroupPowerUserRole = 3 +) + +//国家势力日志操作类型 +type GroupPowerUserLogType = mysql.Type + +const ( + //加入 + GroupPowerUserLogTypeUserJoin GroupPowerUserLogType = 1 + //用户自己离开 + GroupPowerUserLogTypeUserLeave GroupPowerUserLogType = 2 + //运营平台赋予管理者 + GroupPowerUserLogTypeOwerJoin GroupPowerUserLogType = 3 + //管理人让用户离开 + GroupPowerUserLogTypeMgrLeave GroupPowerUserLogType = 4 + //管理人解散 + GroupPowerUserLogDissolve GroupPowerUserLogType = 5 +) + +type GroupPowerDiamondLogType = mysql.Type + +const ( + //群组原因加入 + GroupPowerDiamondLogTypeByGroup GroupPowerDiamondLogType = 1 + //群主原因加入 + GroupPowerDiamondLogTypeByGroupOwer GroupPowerDiamondLogType = 2 +) + +type PowerSupportAwardState = uint + +const ( + PowerSuppportNo PowerSupportAwardState = 0 // 未达到要求 + PowerSuppportAwarded PowerSupportAwardState = 1 // 已经领取 + PowerSuppportWaiting PowerSupportAwardState = 2 // 待领取 +) diff --git a/_const/enum/group_e/enum.go b/_const/enum/group_e/enum.go new file mode 100644 index 0000000..437696a --- /dev/null +++ b/_const/enum/group_e/enum.go @@ -0,0 +1,101 @@ +package group_e + +import "git.hilo.cn/hilo-common/resource/mysql" + +type MsgStatusGroupUser = mysql.Type + +const ( + //正常: 灰点+震动 + NormalMsgStatusGroupUser MsgStatusGroupUser = 0 + //静音:灰点 + MuteMsgStatusGroupUser MsgStatusGroupUser = 1 + //免打扰:什么也没有 + DoNotDisturbMsgStatusGroupUser MsgStatusGroupUser = 2 + + OverseaRoom = 1 + LocalRoom = 2 +) + +// 公屏消息 +type TypePublicScreenMsg = mysql.Type + +const ( + UserJoinPublicScreenMsg TypePublicScreenMsg = 1 // 加入群组 + UserKickPublicScreenMsg TypePublicScreenMsg = 2 // 踢出房间 + UserBannedPublicScreenMsg TypePublicScreenMsg = 3 // 拉黑用户 + RoleAssignedPublicScreenMsg TypePublicScreenMsg = 4 // 添加角色 + RoleRemovedPublicScreenMsg TypePublicScreenMsg = 5 // 移除角色 + ClientSendMsgLocal TypePublicScreenMsg = 6 // 客户端占用 + RollDiceMsg TypePublicScreenMsg = 7 // 掷骰子结果 + GroupGiftMsg TypePublicScreenMsg = 8 //全服礼物 + GroupSupportH5 TypePublicScreenMsg = 9 //群组支持H5 + JumpMessage TypePublicScreenMsg = 10 // 可跳转的公屏消息 + RocketAwardMsg TypePublicScreenMsg = 11 // 火箭获奖消息 + LockyboxAwardMsg TypePublicScreenMsg = 12 // 幸运盒子公屏中奖 + FruitMachineAwardMsg TypePublicScreenMsg = 13 // 水果机中奖 + EnterRoomMsg TypePublicScreenMsg = 14 // 用户进入房间 +) + +// 信令消息(不显示公屏工,不记入消息历史,不影响未读数) +type TypeSignalMsg = mysql.Type + +const ( + GroupEditProfileSignal TypeSignalMsg = 1 + GroupRoleChangeSignal TypeSignalMsg = 2 + GroupMicChangeSignal TypeSignalMsg = 3 //保留 + GroupMsgBannedSignal TypeSignalMsg = 4 + GroupMemberRemoveSignal TypeSignalMsg = 5 + GroupGiftSignal TypeSignalMsg = 6 //礼物 + GroupMicInSignal TypeSignalMsg = 7 + GroupMicOutSignal TypeSignalMsg = 8 + GroupMicLockSignal TypeSignalMsg = 9 + GroupMicUnLockSignal TypeSignalMsg = 10 + GroupMicSpeechOpenSignal TypeSignalMsg = 11 + GroupMicSpeechCloseSignal TypeSignalMsg = 12 + GroupKickOut TypeSignalMsg = 13 //保留 + GroupSocketMicOutSignal TypeSignalMsg = 14 //保留 + GroupInviteMicInSignal TypeSignalMsg = 15 //邀请上麦保留 + GroupInSignal TypeSignalMsg = 16 //进入房间,进房特效 + GroupMicEmoji TypeSignalMsg = 17 //麦上表情 + GroupLuckyWheel TypeSignalMsg = 18 //转盘的通知信令 + GroupOutSignal TypeSignalMsg = 19 //离开房间 + GroupRocketState TypeSignalMsg = 20 //火箭状态变化 + GroupOnlineUser TypeSignalMsg = 21 //房间在线用户信息 + GroupMicChange TypeSignalMsg = 22 //房间麦位上的变量 + GroupMemberInvite TypeSignalMsg = 23 //房间-邀请用户成为会员 + GroupRoleChange TypeSignalMsg = 24 //房间-用户群组身份变化 + GroupClearScreen TypeSignalMsg = 25 //房间-清理公屏 + GroupRoomGiftSignal TypeSignalMsg = 26 //全房间送礼物 +) + +//群组麦位数量类型 +type GroupMicNumType = mysql.Type + +const ( + OneMicNumType GroupMicNumType = 5 + TwoMicNumType GroupMicNumType = 10 + ThreeMicNumType GroupMicNumType = 3 + FourMicNumType GroupMicNumType = 4 + SixMicNumType GroupMicNumType = 6 + SevenMicNumType GroupMicNumType = 7 + EightMicNumType GroupMicNumType = 8 + NineMicNumType GroupMicNumType = 9 + ElevenMicNumType GroupMicNumType = 11 + TwelveMicNumType GroupMicNumType = 12 + ThirteenMicNumType GroupMicNumType = 13 + FourteenMicNumType GroupMicNumType = 14 + FifteenMicNumType GroupMicNumType = 15 + SixteenMicNumType GroupMicNumType = 16 + SeventeenMicNumType GroupMicNumType = 17 + EighteenMicNumType GroupMicNumType = 18 + NineteenMicNumType GroupMicNumType = 19 + TwentyMicNumType GroupMicNumType = 20 + //5个麦位 + FiveMicNumType GroupMicNumType = 1 + //10个麦位 + TenMicNumType GroupMicNumType = 2 + // + + SUPPORT_LEVEL_BOUNDARY_HOUR = 0 + SUPPORT_LEVEL_PERIOD_DAY = 7 +) diff --git a/_const/enum/user_e/user.go b/_const/enum/user_e/user.go index 971af4d..c745240 100755 --- a/_const/enum/user_e/user.go +++ b/_const/enum/user_e/user.go @@ -1,6 +1,8 @@ package user_e -import "git.hilo.cn/hilo-common/resource/mysql" +import ( + "git.hilo.cn/hilo-common/resource/mysql" +) type ThirdPartyType = mysql.Type @@ -12,6 +14,17 @@ const ( WeChat ThirdPartyType = 5 ) +type CountType mysql.Type + +const ( + //我喜欢的数量 + CountTypeLike CountType = 1 + //我拉黑的数量 + CountTypeBlock CountType = 2 + //我被喜欢的次数 + CountTypeLikeMe CountType = 3 +) + type UserStatus mysql.Type const ( @@ -24,8 +37,33 @@ const ( type UserVipType = mysql.Type const ( - // 男 - UserMan = 1 - // 女 - UserWomen = 2 + //购买 + UserVipTypeBuy UserVipType = 1 + //赠送 + UserVipTypeGive UserVipType = 2 ) + +type UserLikeOperateType = mysql.Type + +const ( + //增加喜欢 + LikeAdd UserLikeOperateType = 1 + //取消喜欢 + LikeCancel UserLikeOperateType = 2 +) + +type UserLikeSceneType = mysql.Type + +const ( + Match UserLikeSceneType = 1 + Video UserLikeSceneType = 2 +) + +type InteractionType = mysql.Type + +const ( + InteractPrivateGift InteractionType = 1 + InteractVideo InteractionType = 2 +) + + diff --git a/_const/redis_key/group_k/keys.go b/_const/redis_key/group_k/keys.go new file mode 100644 index 0000000..7007daa --- /dev/null +++ b/_const/redis_key/group_k/keys.go @@ -0,0 +1,8 @@ +package group_k + +//在房间的人 +const groupRoomLiving = "group_room_living" + +func GetPrefixGroupRoomLiving() string { + return groupRoomLiving +} diff --git a/_const/redis_key/user_k/keys.go b/_const/redis_key/user_k/keys.go index c8af465..4792bb2 100755 --- a/_const/redis_key/user_k/keys.go +++ b/_const/redis_key/user_k/keys.go @@ -4,6 +4,8 @@ import ( "fmt" "git.hilo.cn/hilo-common/resource/mysql" "hilo-user/_const/redis_key" + "strconv" + "strings" ) const ( @@ -28,3 +30,9 @@ func GetExternalIdToUidKey(externalId mysql.Str) string { func GetCodeToUidKey(code mysql.Str) string { return redis_key.ReplaceKey(UserCodeToUIdStr, code) } + +const syncTimHiloLock = "sync_tim_hilo_{userId}" + +func GetKeySyncTimHilo(userId uint64) string { + return strings.Replace(syncTimHiloLock, "{userId}", strconv.FormatUint(userId, 10), -1) +} diff --git a/cv/user_cv/user.go b/cv/user_cv/user.go index 419988e..1d535ee 100644 --- a/cv/user_cv/user.go +++ b/cv/user_cv/user.go @@ -1,11 +1,14 @@ package user_cv import ( + "git.hilo.cn/hilo-common/_const/common" "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" "gorm.io/gorm" + "hilo-user/_const/enum/country_e" + "hilo-user/_const/enum/cp_e" "hilo-user/cv/headwear_cv" "hilo-user/cv/medal_cv" "hilo-user/cv/noble_cv" @@ -101,6 +104,7 @@ type CvUserBase struct { Headwear *headwear_cv.CvHeadwear `json:"headwear"` // 当前使用的头饰 Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾 Noble noble_cv.CvNoble `json:"noble"` // 当前的 + GroupRole common.GroupRoleType `json:"groupRole"` // 在群组的角色 } //批量获取用户基本信息 @@ -156,7 +160,7 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) return nil, err } - superManagerMap, err := GetSuperManagerMap(userIds) + superManagerMap, err := user_m.GetSuperManagerMap(userIds) if err != nil { return nil, err } @@ -223,6 +227,87 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) return cvUserBases, nil } +// 获取cp另一半基本信息 +func GetUserBaseForCpMap(userIds []mysql.ID) (map[mysql.ID]*CvUserBase, error) { + var res = make(map[mysql.ID]*CvUserBase) + users, err := GetUserBasesForCp(userIds) + if err != nil { + return nil, err + } + for i, v := range users { + if v.Id != nil { + res[*v.Id] = users[i] + } + } + return res, nil +} + +// 批量获取cp另一半基本信息 +func GetUserBasesForCp(userIds []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 { + mylogrus.MyLog.Errorf("MGetUserSvip fail:%v", err) + } + + headwearMap, err := headwear_cv.BatchGetCvHeadwears(userIds) + if err != nil { + return nil, err + } + + nobles, err := noble_m.BatchGetActiveNoble(domain.CreateModelNil(), userIds) + if err != nil { + return nil, err + } + + var cvUserBases []*CvUserBase + for i := 0; i < len(users); i++ { + user := users[i] + invisible := IfLogout(user.LogoutTime) + invisibleAvatar := "" + invisibleNick := user.Code + 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, + 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) + } + cvUserBase.Svip = svips[user.ID] + + cvUserBases = append(cvUserBases, cvUserBase) + } + return cvUserBases, nil +} + func getMedalInfoMap(db *gorm.DB, medals map[uint64][]uint32) (map[uint64][]uint32, map[uint64][]medal_cv.CvMedal, error) { resMedals, err := res_m.MedalGetAllMap(db) if err != nil { @@ -309,25 +394,6 @@ func GetPropertyAll(db *gorm.DB) (map[uint64]property_cv.CvProperty, error) { return result, nil } -func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) { - if len(userIds) == 0 { - return map[uint64]bool{}, nil - } - var superManagers []user_m.SuperManager - if err := mysql.Db.Model(&user_m.SuperManager{}).Where("user_id in (?)", userIds).Find(&superManagers).Error; err != nil { - return nil, myerr.WrapErr(err) - } - //转换成map - rs := map[uint64]bool{} - for i, _ := range userIds { - rs[userIds[i]] = false - } - for i, _ := range superManagers { - rs[superManagers[i].UserId] = true - } - return rs, nil -} - func GetUserBaseMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUserBase, error) { userBases, err := GetUserBases(userIds, myUserId) if err != nil { @@ -355,3 +421,82 @@ type CvUserTiny struct { //生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示 Birthday *uint64 `json:"birthday"` } + +//用户详细信息 +type CvUserDetail struct { + CvUserBase + //统计:我喜欢多少人 + ILikeCount *uint32 `json:"iLikeCount"` + //统计:多少人喜欢你, (本才才有数据,不是本人,数据为nil) + LikeCount *uint32 `json:"likeCount"` + //统计:多少人访问你 + VisitCount *uint32 `json:"visitCount"` + //消息提醒, 1:开启,2:关闭 + IsPush *uint8 `json:"isPush"` + //钻石数量(本人才有数据,不是本人,数据为nil) + DiamondNum *uint32 `json:"diamondNum"` + //粉钻数量(本人才有数据,不是本人,数据为nil) + PinkDiamondNum *uint32 `json:"pinkDiamondNum"` + //是否喜欢(本人没有数据,//20210205 已废弃nil,产品说:可以自己喜欢自己) + IsLike *bool `json:"isLike"` + //ID + //ID *mysql.ID `json:"id,omitempty"` + //是否工会成员, 只有是自己查自己,这个才有值,其它全为nil + //IsTradeUnion *bool `json:"isTradeUnion"` + //工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值, + //IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"` + //是否可以免费通话,自己本人没有数据 + //IsVideoFreeCan *bool `json:"isVideoCanFree"` + //别人是否喜欢我,自己本人没有数据 (20210205 已废弃nil,产品说:可以自己喜欢自己) + IsLikeMe *bool `json:"isLikeMe"` + HeartValue uint32 `json:"heartValue"` // 与我之间永恒之心的值 + HeartValueMax uint32 `json:"heartValueMax"` // 与我之间永恒之心的最大值(0代表没有永恒之心,即没有相互关注) + MeetDays uint `json:"meetDays"` // 成长关系建立的时间(天数) + WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级 + CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级 + ActivityUserGrade uint32 `json:"activityUserGrade"` //活跃等级 + CurrentRoom string `json:"currentRoom"` // 当前用户所在房间(产品叫“群组”) + MyGroupPower uint64 `json:"myGroupPower"` // 当前用户所在势力 + MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称 + GroupPower rpc.CvGroupPowerInfo `json:"groupPower"` // 家族 + GroupId string `json:"groupId"` // 当前用户拥有的群组id(产品叫“群组”),如果没有则为空,拥有多个,返回第一个 + PhoneInfo *user_m.UserPhoneInfo `json:"phoneInfo"` // 用户绑定的手机信息 + ThirdList []int8 `json:"thirdList"` // 用户绑定的第三方平台列表;类型 1:phone, 2:google, 3:facebook 4:apple 5:wechat" Enums(1,2,3,4,5) + CountryManager *CVCountryManager `json:"countryManager,omitempty"` // 国家管理员 + Cp *CvCp `json:"cp,omitempty"` // cp信息 +} + +// cv国家管理人员 +type CVCountryManager struct { + Country string `json:"country"` // 国家name + Role country_e.CountryMgrRole `json:"role" swaggertype:"integer"` // 角色 1:国家管理员 2:国家助理 +} + +// cp信息 +type CvCp struct { + CpUserInfo *CvUserBase `json:"cpUserInfo"` // cp用户信息 + CpLevel CvCpLevel `json:"cpLevel"` // cp等级 + MyPrivilegeList []CvPrivilege `json:"myPrivilegeList"` // 等级特权 + CreatedUnix int64 `json:"createdUnix"` // cp创建时间 + CpDays int `json:"cpDays"` // cp天数 +} + +// cp关系 +type CvCpRelation struct { + CpId uint64 `json:"cpId"` + UserId uint64 `json:"userId"` + CpUserId uint64 `json:"cpUserId"` + CpUserAvatar string `json:"cpUserAvatar,omitempty"` +} + +// cp等级 +type CvCpLevel struct { + Level cp_e.CpLevel `json:"level"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP + Points uint32 `json:"points"` // CP值 + Title string `json:"title,omitempty"` // 称号翻译 +} + +// 特权信息 +type CvPrivilege struct { + Type cp_e.CpPrivilege `json:"type"` // 特权id 1:空间 2:横幅 3:等级勋章 4:证书 5:进场特效 6:头像头饰 7:动态资料卡 8:麦位特效 +} diff --git a/domain/model/country_m/country_mgr.go b/domain/model/country_m/country_mgr.go new file mode 100644 index 0000000..d568e97 --- /dev/null +++ b/domain/model/country_m/country_mgr.go @@ -0,0 +1,40 @@ +package country_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/_const/enum/country_e" + "hilo-user/myerr" +) + +type CountryMgrUser struct { + mysql.Entity + Country string + UserId mysql.ID + Role country_e.CountryMgrRole +} + +// 获取国家管理人员 +func GetCountryMgr(model *domain.Model, userId mysql.ID) (*CountryMgrUser, error) { + cmu := new(CountryMgrUser) + if err := model.Db.WithContext(model.MyContext.Context).Where("user_id = ?", userId).First(&cmu).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return cmu, nil +} + +// 更新国家管理人员 +func (cmu *CountryMgrUser) UpdateCountryMgr(userId mysql.ID, role country_e.CountryMgrRole, country string) *CountryMgrUser { + cmu.UserId, cmu.Role, cmu.Country = userId, role, country + return cmu +} + +// 删除国家管理人员 +func (cmu *CountryMgrUser) DeleteCountryMgr() { + cmu.SetDel() +} diff --git a/domain/model/groupPower_m/groupPower.go b/domain/model/groupPower_m/groupPower.go new file mode 100644 index 0000000..054d4d1 --- /dev/null +++ b/domain/model/groupPower_m/groupPower.go @@ -0,0 +1,84 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/_const/enum/groupPower_e" + "hilo-user/domain/model/group_m" + "hilo-user/myerr" +) + +type GroupPowerUser struct { + mysql.Entity + *domain.Model `gorm:"-"` + GroupPowerId mysql.ID + UserId mysql.ID + Role groupPower_e.GroupPowerUserRole +} + +type GroupPower struct { + mysql.Entity + *domain.Model `gorm:"-"` + GroupUid mysql.Str + Name mysql.Str + Status groupPower_e.GroupPowerStatus +} + +// 查询用户加入的国家势力ID及名称(势力绑定的群组的名称) +func GetUserGroupPower(model *domain.Model, userId uint64) (uint64, string, error) { + gpu, err := GetGroupPowerUserOrNil(model, userId) + if err != nil { + return 0, "", err + } + if gpu == nil || gpu.GroupPowerId == 0 { + return 0, "", nil + } + gp, err := GetGroupPowerOrErr(model, gpu.GroupPowerId) + if err != nil { + return 0, "", err + } + + powerName := "" + if gp != nil && len(gp.GroupUid) > 0 { + gi, err := group_m.GetGroupInfo(model, gp.GroupUid) + if err != nil { + return 0, "", err + } + if gi != nil { + // 只要前15个字 + s := []rune(gi.Name) + if len(s) <= 15 { + powerName = string(s) + } else { + powerName = string(s[0:15]) + } + } + } + return gpu.GroupPowerId, powerName, nil +} + +//获取用户所在的国家势力信息,不存在则为nil +func GetGroupPowerUserOrNil(model *domain.Model, userId mysql.ID) (*GroupPowerUser, error) { + groupPowerUser := GroupPowerUser{} + if err := model.Db.Where(&GroupPowerUser{ + UserId: userId, + }).First(&groupPowerUser).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + groupPowerUser.Model = model + return &groupPowerUser, nil +} + +func GetGroupPowerOrErr(model *domain.Model, id uint64) (*GroupPower, error) { + groupPower := GroupPower{} + if err := model.Db.Model(&GroupPower{}).First(&groupPower, id).Error; err != nil { + return nil, myerr.WrapErr(err) + } + groupPower.Model = model + return &groupPower, nil +} diff --git a/domain/model/group_m/groupInfo.go b/domain/model/group_m/groupInfo.go new file mode 100644 index 0000000..cf0c798 --- /dev/null +++ b/domain/model/group_m/groupInfo.go @@ -0,0 +1,109 @@ +package group_m + +import ( + "git.hilo.cn/hilo-common/domain" + "gorm.io/gorm" + "hilo-user/_const/enum/group_e" + "hilo-user/myerr/bizerr" + "time" +) + +type GroupInfo struct { + Id int64 + ImGroupId string + TxGroupId string + Type uint16 + Code string + OriginCode string + Owner uint64 + Name string + Introduction string + Notification string + FaceUrl string + Country string + ChannelId string + Password string + EntryLevel uint32 // obsolete + MicOn bool + LoadHistory bool + ThemeId int16 + MicNumType group_e.GroupMicNumType + TouristMic uint8 // 游客是否能上麦1是2否 + TouristSendMsg uint8 // 游客是否能发消息1是2否 + TouristSendPic uint8 // 游客是否能发图片1是2否 + MemberFee uint64 // 加入会员需要黄钻数 + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +func GetGroupInfo(model *domain.Model, groupId string) (*GroupInfo, error) { + if len(groupId) <= 0 { + return nil, bizerr.GroupNotFound + } + r := GroupInfo{} + err := model.Db.Where(&GroupInfo{ImGroupId: groupId}).First(&r).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, err + } + } + return &r, nil +} + +func FindGroupByOwner(model *domain.Model, ownerId uint64) ([]GroupInfo, error) { + rows := make([]GroupInfo, 0) + err := model.Db.Where(&GroupInfo{Owner: ownerId}).Find(&rows).Error + if err != nil { + return nil, err + } + return rows, nil +} + +func ToTxGroupId(model *domain.Model, imGroupId string) (string, error) { + if len(imGroupId) <= 0 { + return "", nil + } + + gi, err := GetGroupInfo(model, imGroupId) + if err != nil { + return "", err + } + if gi == nil { + return "", bizerr.GroupNotFound + } + return gi.TxGroupId, nil +} + +func ToImGroupId(model *domain.Model, txGroupId string) (string, error) { + if len(txGroupId) <= 0 { + return "", nil + } + + gi, err := GetInfoByTxGroupId(model, txGroupId) + if err != nil { + return "", err + } + if gi == nil { + return "", bizerr.GroupNotFound + } + return gi.ImGroupId, nil +} + +func GetInfoByTxGroupId(model *domain.Model, txGroupId string) (*GroupInfo, error) { + if len(txGroupId) <= 0 { + return nil, bizerr.GroupNotFound + } + + r := GroupInfo{} + err := model.Db.Where(&GroupInfo{TxGroupId: txGroupId}).First(&r).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, err + } + } + return &r, nil +} diff --git a/domain/model/group_m/role.go b/domain/model/group_m/role.go new file mode 100644 index 0000000..bd0bf77 --- /dev/null +++ b/domain/model/group_m/role.go @@ -0,0 +1,80 @@ +package group_m + +import ( + "git.hilo.cn/hilo-common/_const/common" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" +) + +type GroupRoles struct { + mysql.Entity + UserId uint64 + ImGroupId string + Role common.GroupRoleType +} + +type GroupMember struct { + GroupId string + UserId uint64 +} + +func (gm *GroupMember) Find(db *gorm.DB) ([]GroupMember, error) { + rows := make([]GroupMember, 0) + if err := db.Where(gm).Order("created_time DESC").Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil +} + +func GetGroupRoleById(model *domain.Model, imGroupId string, userId uint64) (role common.GroupRoleType, err error) { + role = common.GROUP_VISITOR + roles, _, err := GetRolesInGroup(model, imGroupId) + if err != nil { + return + } + for u, r := range roles { + if u == userId { + role = r + return + } + } + + isGroupMember, err := IsGroupMember(model.Db, imGroupId, userId) + if err != nil { + return + } + if isGroupMember { + role = common.GROUP_MEMBER + } + return +} + +// 查询群组中所有有角色的成员,由级别高到低、创建时间由早到晚排列 +func GetRolesInGroup(model *domain.Model, groupId string) (map[uint64]uint16, []uint64, error) { + data := make([]GroupRoles, 0) + err := model.Db.Where(&GroupRoles{ImGroupId: groupId}).Order("role DESC, created_time").Find(&data).Error + if err != nil { + return nil, nil, err + } + + result := make(map[uint64]uint16, 0) + orders := make([]uint64, 0) + for _, i := range data { + orders = append(orders, i.UserId) + result[i.UserId] = i.Role + } + return result, orders, nil +} + +func IsGroupMember(db *gorm.DB, groupId string, userId uint64) (bool, error) { + gm := GroupMember{ + GroupId: groupId, + UserId: userId, + } + rows, err := gm.Find(db) + if err != nil { + return false, err + } + return len(rows) > 0, nil +} diff --git a/domain/model/group_m/room.go b/domain/model/group_m/room.go new file mode 100644 index 0000000..12319ad --- /dev/null +++ b/domain/model/group_m/room.go @@ -0,0 +1,58 @@ +package group_m + +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/resource/redisCli" + "hilo-user/_const/redis_key/group_k" + "hilo-user/myerr" + "strconv" + "strings" + "time" +) + +const expireMinute = 60 * 60 * 12 + +//获取在房间的用户 返回值:map,key:userId, value:groupUuid +func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]string, error) { + userIdSet := map[mysql.ID]struct{}{} + for i, _ := range userIds { + userIdSet[userIds[i]] = struct{}{} + } + key := group_k.GetPrefixGroupRoomLiving() + if err := ClearExpired(model, key, expireMinute); err != nil { + return nil, myerr.WrapErr(err) + } + + groupUserIdstrs, err := redisCli.GetRedis().ZRange(model, key, 0, -1).Result() + if err != nil { + return nil, myerr.WrapErr(err) + } + + resultUserSet := map[mysql.ID]string{} + for i, _ := range groupUserIdstrs { + tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) + mylogrus.MyLog.Debugf("RoomLivingUserIdFilter, analysisMemberStr %s, %d", tempGroupUid, userId) + + if _, flag := userIdSet[userId]; flag { + resultUserSet[userId] = tempGroupUid + } + } + return resultUserSet, nil +} + +func ClearExpired(model *domain.Model, key string, expireSec int64) error { + return model.Redis.ZRemRangeByScore(model, key, + "0", strconv.FormatInt(time.Now().Unix()-expireSec, 10)).Err() +} + +func analysisMemberStr(memberStr string) (string, uint64) { + strs := strings.Split(memberStr, "_") + groupUid := strs[0] + userId, err := strconv.ParseUint(strs[1], 10, 64) + if err != nil { + mylogrus.MyLog.Errorf("analysisMemberStr memberStr:%v err:%+v", memberStr, err) + } + return groupUid, userId +} diff --git a/domain/model/tim_m/user.go b/domain/model/tim_m/user.go new file mode 100644 index 0000000..f26b72d --- /dev/null +++ b/domain/model/tim_m/user.go @@ -0,0 +1,27 @@ +package tim_m + +import ( + "encoding/json" + "git.hilo.cn/hilo-common/sdk/tencentyun" +) + +type TimHiloInfo struct { + IsVip bool `json:"isVip"` + IsPretty bool `json:"isPretty"` + Medals []uint32 `json:"medals"` + PowerName string `json:"powerName"` // 用户加入的国家势力的绑定群组的名称 + NobleLevel uint16 `json:"nobleLevel"` +} + +func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, groupPowerName string, nobleLevel uint16) error { + info := TimHiloInfo{IsVip: isVip, IsPretty: isPrettyCode, Medals: medals, PowerName: groupPowerName, NobleLevel: nobleLevel} + buf, err := json.Marshal(info) + if err != nil { + return err + } + + if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil { + return err + } + return nil +} diff --git a/domain/model/user_m/count.go b/domain/model/user_m/count.go new file mode 100644 index 0000000..766ac6f --- /dev/null +++ b/domain/model/user_m/count.go @@ -0,0 +1,19 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-user/_const/enum/user_e" +) + +//用户统计 +type UserCount struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + Type user_e.CountType + Num mysql.Num + isAdd bool `gorm:"-"` + isReduce bool `gorm:"-"` + addReduceNum mysql.Num `gorm:"-"` +} diff --git a/domain/model/user_m/like.go b/domain/model/user_m/like.go new file mode 100644 index 0000000..27b4500 --- /dev/null +++ b/domain/model/user_m/like.go @@ -0,0 +1,104 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/_const/enum/user_e" + "hilo-user/myerr" +) + +//用户喜欢 +type UserLike struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + LikeUserId mysql.ID + SceneType user_e.UserLikeSceneType +} + +type UserLikeOperate struct { + mysql.Entity + UserId mysql.ID + LikeUserId mysql.ID + Type user_e.UserLikeOperateType + SceneType user_e.UserLikeSceneType +} + +func AddUserLikeOperate(model *domain.Model, userId mysql.ID, likeUserId mysql.ID, t user_e.UserLikeOperateType, sceneType user_e.UserLikeSceneType) (mysql.ID, error) { + userLikeOperate := UserLikeOperate{ + UserId: userId, + LikeUserId: likeUserId, + Type: t, + SceneType: sceneType, + } + if err := model.Db.Create(&userLikeOperate).Error; err != nil { + return 0, myerr.WrapErr(err) + } else { + return userLikeOperate.ID, nil + } +} + +func initUserLike(model *domain.Model, userId mysql.ID) *UserLike { + return &UserLike{ + Model: model, + UserId: userId, + } +} + +/*func GetUserLike(model *domain.Model, userId mysql.ID, likeUserId mysql.ID) (*UserLike, error) { + var userLike UserLike + err := model.Db.Where(&UserLike{ + UserId: userId, + LikeUserId: likeUserId, + }).First(&userLike).Error + if err == nil { + return &userLike, nil + } else if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } +}*/ + +//喜欢 +func (userLike *UserLike) like(likeUserId mysql.ID, sceneType user_e.UserLikeSceneType) (*UserLike, mysql.ID, error) { + err := userLike.Db.Where(&UserLike{ + UserId: userLike.UserId, + LikeUserId: likeUserId, + }).First(userLike).Error + //已经喜欢 + if err == nil { + return nil, 0, myerr.NewWaring("已经标记喜欢") + } else if err == gorm.ErrRecordNotFound { + userLikeOperateId, err := AddUserLikeOperate(userLike.Model, userLike.UserId, likeUserId, user_e.LikeAdd, sceneType) + if err != nil { + return nil, 0, err + } + userLike.LikeUserId = likeUserId + userLike.SceneType = sceneType + return userLike, userLikeOperateId, nil + } else { + return nil, 0, myerr.WrapErr(err) + } +} + +//取消喜欢 +func (userLike *UserLike) likeCancel(likeUserId mysql.ID) (*UserLike, error) { + err := userLike.Db.Where(&UserLike{ + UserId: userLike.UserId, + LikeUserId: likeUserId, + }).First(userLike).Error + // + if err == nil { + if _, err := AddUserLikeOperate(userLike.Model, userLike.UserId, likeUserId, user_e.LikeCancel, userLike.SceneType); err != nil { + return nil, err + } + userLike.SetDel() + return userLike, nil + } else if err == gorm.ErrRecordNotFound { + return nil, myerr.NewWaring("没有喜欢的记录") + } else { + return nil, myerr.WrapErr(err) + } +} diff --git a/domain/model/user_m/relation.go b/domain/model/user_m/relation.go new file mode 100644 index 0000000..df8e78d --- /dev/null +++ b/domain/model/user_m/relation.go @@ -0,0 +1,121 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/_const/common" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/myerr" + "time" +) + +type Relation struct { + // 永恒之心值 + HeartValue uint32 `json:"heartValue"` + // 永恒之心的最大值(0代表没有永恒之心,即没有相互关注) + HeartValueMax uint32 `json:"heartValueMax"` + // 成长关系建立的时间(天数) + MeetDays uint `json:"meetDays"` +} + +//用户成长关系 +type UserRelation struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId_1 mysql.ID + UserId_2 mysql.ID + HeartValue uint32 +} + +// 查询成长关系 +func GetRelation(model *domain.Model, userId1, userId2 mysql.ID) (Relation, error) { + result := Relation{0, 0, 0} + if userId1 == userId2 { + return result, nil + } + // 保证uid小的在前面 + if userId1 > userId2 { + userId1, userId2 = userId2, userId1 + } + rel := UserRelation{UserId_1: userId1, UserId_2: userId2, HeartValue: 0} + if err := model.DB().Model(&UserRelation{}).Where(&UserRelation{ + UserId_1: userId1, + UserId_2: userId2, + }).First(&rel).Error; err != nil { + if err == gorm.ErrRecordNotFound { + // 没有成长关系的情况 + return result, nil + } else { + return result, myerr.WrapErr(err) + } + } + result.HeartValueMax = common.HEART_VALUE_MAX + + result.HeartValue = rel.HeartValue + if result.HeartValue > common.HEART_VALUE_MAX { + result.HeartValue = common.HEART_VALUE_MAX + } + d := uint(time.Since(rel.CreatedTime).Hours() / 24) + if d < 0 { + d = 0 + } + result.MeetDays = d + + return result, nil +} + +// 批量查询成长关系 +func BatchGetRelations(model *domain.Model, userId mysql.ID, others []mysql.ID) (map[mysql.ID]Relation, error) { + smaller := make([]mysql.ID, 0) + greater := make([]mysql.ID, 0) + for _, i := range others { + if i < userId { + smaller = append(smaller, i) + } else if i > userId { + greater = append(greater, i) + } + } + rows := make([]UserRelation, 0) + result := make(map[mysql.ID]Relation, 0) + var err error + if len(greater) > 0 { + if err = model.DB().Model(&UserRelation{}).Where("user_id_1 = ? AND user_id_2 IN ?", userId, greater).Find(&rows).Error; err != nil { + return result, err + } + } + + for _, i := range rows { + if i.HeartValue > common.HEART_VALUE_MAX { + i.HeartValue = common.HEART_VALUE_MAX + } + d := uint(time.Since(i.CreatedTime).Hours() / 24) + if d < 0 { + d = 0 + } + result[i.UserId_2] = Relation{HeartValue: i.HeartValue, HeartValueMax: common.HEART_VALUE_MAX, MeetDays: d} + } + + rows = make([]UserRelation, 0) + if len(smaller) > 0 { + if err = model.DB().Model(&UserRelation{}).Where("user_id_1 IN ? AND user_id_2 = ?", smaller, userId).Find(&rows).Error; err != nil { + return result, err + } + } + for _, i := range rows { + if i.HeartValue > common.HEART_VALUE_MAX { + i.HeartValue = common.HEART_VALUE_MAX + } + d := uint(time.Since(i.CreatedTime).Hours() / 24) + if d < 0 { + d = 0 + } + result[i.UserId_1] = Relation{HeartValue: i.HeartValue, HeartValueMax: common.HEART_VALUE_MAX, MeetDays: d} + } + // 补上没有成长关系的人 + for _, u := range others { + if _, exists := result[u]; !exists { + result[u] = Relation{0, 0, 0} + } + } + return result, err +} diff --git a/domain/model/user_m/superManager.go b/domain/model/user_m/superManager.go index 12e4483..e558088 100644 --- a/domain/model/user_m/superManager.go +++ b/domain/model/user_m/superManager.go @@ -65,15 +65,21 @@ func GetSuperManagerAll(model *domain.Model) ([]uint64, error) { return userIds, nil } -/* -func GetSuperManagerMap(model *domain.Model) (map[uint64]struct{}, error) { - userIds, err := GetSuperManagerAll(model) - if err != nil { - return nil, err +func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) { + if len(userIds) == 0 { + return map[uint64]bool{}, nil + } + var superManagers []SuperManager + if err := mysql.Db.Model(&SuperManager{}).Where("user_id in (?)", userIds).Find(&superManagers).Error; err != nil { + return nil, myerr.WrapErr(err) } - userIdMap := map[uint64]struct{}{} + //转换成map + rs := map[uint64]bool{} for i, _ := range userIds { - userIdMap[userIds[i]] = struct{}{} + rs[userIds[i]] = false } - return userIdMap, nil -}*/ + for i, _ := range superManagers { + rs[superManagers[i].UserId] = true + } + return rs, nil +} diff --git a/domain/model/user_m/userBindInfo.go b/domain/model/user_m/userBindInfo.go new file mode 100644 index 0000000..41cc2df --- /dev/null +++ b/domain/model/user_m/userBindInfo.go @@ -0,0 +1,38 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/domain" + "time" +) + +type UserBindInfo struct { + UserId uint64 `json:"user_id"` + Phone string `json:"phone"` + PhoneCountry string `json:"phone_country"` + Pwd string `json:"pwd"` + AreaCode string `json:"area_code"` + Icon string `json:"icon"` + CreateAt time.Time `json:"create_at"` + UpdateAt time.Time `json:"update_at"` +} + +func (*UserBindInfo) TableName() string { + return "user_bind_info" +} + +type UserPhoneInfo struct { + Phone string `json:"phone"` + PhoneCountry string `json:"phoneCountry"` + AreaCode string `json:"areaCode"` + Icon string `json:"icon"` +} + +// 获取用户手机号绑定信息 +func GetUserBindInfoByUserId(model *domain.Model, userId uint64) (*UserBindInfo, error) { + res := new(UserBindInfo) + err := model.DB().Where(&UserBindInfo{UserId: userId}).First(&res).Error + if err != nil { + return nil, err + } + return res, nil +} diff --git a/domain/model/user_m/userOauth.go b/domain/model/user_m/userOauth.go new file mode 100644 index 0000000..d1769f0 --- /dev/null +++ b/domain/model/user_m/userOauth.go @@ -0,0 +1,35 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/domain" + "gorm.io/gorm" + "hilo-user/myerr" +) + +type UserOauth struct { + UserId uint64 `json:"user_id"` + ThirdPartyId string `json:"third_party_id"` + ThirdPartyType int8 `json:"third_party_type"` +} + +func (*UserOauth) TableName() string { + return "user_oauth" +} + +// 根据id获取第三方登录信息 +func GetUserOauthByUserId(model *domain.Model, userId uint64, thirdType uint8) ([]*UserOauth, error) { + res := make([]*UserOauth, 0) + db := model.DB().Where(&UserOauth{UserId: userId}) + if thirdType > 0 { + db = db.Where(&UserOauth{ThirdPartyType: int8(thirdType)}) + } + err := db.Find(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return res, nil +} diff --git a/domain/model/user_m/user_trade_union.go b/domain/model/user_m/user_trade_union.go new file mode 100644 index 0000000..df3d697 --- /dev/null +++ b/domain/model/user_m/user_trade_union.go @@ -0,0 +1,44 @@ +package user_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/myerr" +) + +type UserTradeUnion struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + MatchNotification mysql.OpenClose + AgentId mysql.ID + StarchatId mysql.ID + Avatar string +} + +func GetUserTradeUnion(userId mysql.ID) (*UserTradeUnion, error) { + var userTradeUnion UserTradeUnion + if err := mysql.Db.Where(UserTradeUnion{ + UserId: userId, + }).First(&userTradeUnion).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return &userTradeUnion, nil +} + +type AgentMgr struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + AgentId mysql.ID +} + +func IsAgent(userId uint64) bool { + data := AgentMgr{} + return mysql.Db.Where(&AgentMgr{UserId: userId}).First(&data).Error == nil +} diff --git a/domain/model/visit_m/repo.go b/domain/model/visit_m/repo.go new file mode 100644 index 0000000..d677ea5 --- /dev/null +++ b/domain/model/visit_m/repo.go @@ -0,0 +1,7 @@ +package visit_m + +import "hilo-user/domain/model" + +func (userVisit *UserVisit) Persistent() error { + return model.Persistent(userVisit.Db, userVisit) +} diff --git a/domain/model/visit_m/visit.go b/domain/model/visit_m/visit.go new file mode 100644 index 0000000..a38f38b --- /dev/null +++ b/domain/model/visit_m/visit.go @@ -0,0 +1,36 @@ +package visit_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-user/myerr" +) + +type UserVisit struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + VisitUserId mysql.ID + N mysql.Num +} + +func GetVisitInstanceOrInit(model *domain.Model, userId mysql.ID, visitUserId mysql.ID) (*UserVisit, error) { + var userVisit UserVisit + if err := model.Db.Where(&UserVisit{ + UserId: userId, + VisitUserId: visitUserId, + }).FirstOrInit(&userVisit, UserVisit{ + UserId: userId, + VisitUserId: visitUserId, + N: 0, + }).Error; err != nil { + return nil, myerr.WrapErr(err) + } + userVisit.Model = model + return &userVisit, nil +} + +func (userVisit *UserVisit) UserVisitAdd() *UserVisit { + userVisit.N = userVisit.N + 1 + return userVisit +} diff --git a/domain/service/cp_s/cp.go b/domain/service/cp_s/cp.go new file mode 100644 index 0000000..09a9874 --- /dev/null +++ b/domain/service/cp_s/cp.go @@ -0,0 +1,83 @@ +package cp_s + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "hilo-user/_const/enum/cp_e" + "hilo-user/cv/cp_cv" + "hilo-user/cv/user_cv" + "hilo-user/domain/model/cp_m" + "time" +) + +type CpService struct { + svc *domain.Service +} + +func NewCpService(myContext *mycontext.MyContext) *CpService { + svc := domain.CreateService(myContext) + return &CpService{svc} +} + +// 获取用户cp信息 +func (s *CpService) GetUserCp(userId uint64, lang string) (*user_cv.CvCp, error) { + var model = domain.CreateModelContext(s.svc.MyContext) + cpLevel := cp_e.CpLevel0 + cpRelation, exists := cp_m.GetCpRelation(model, userId) + if !exists { + return nil, nil + } + var myPrivilegeList []user_cv.CvPrivilege + level := cp_m.GetCpLevel(model, cpRelation.Id) + if level.ExpireAt.Before(time.Now()) { + level.ExpireAt = time.Now().AddDate(0, 1, 0) + } + cpLevel = level.Level + cpUserId := cpRelation.UserId2 + if cpUserId == userId { + cpUserId = cpRelation.UserId1 + } + userPrivileges, err := cp_m.MGetUserSvipPrivilege(model, []uint64{userId}) + if err != nil { + return nil, err + } + privilegeList := cp_cv.CopyCpLevelPrivilegeList(level.Level, "en") + for i, v := range privilegeList { + if v.CanSwitch { + privilegeList[i].UserSwitch = userPrivileges[userId][v.Type] + } + } + // 我的特权,有开关并且打开才返回 + for _, v := range privilegeList { + if !v.CanSwitch { + myPrivilegeList = append(myPrivilegeList, user_cv.CvPrivilege{Type: v.Type}) + } else if v.UserSwitch { + myPrivilegeList = append(myPrivilegeList, user_cv.CvPrivilege{Type: v.Type}) + } + } + userBases, err := user_cv.GetUserBaseForCpMap([]uint64{cpUserId}) + if err != nil { + return nil, err + } + // 返回值 + title := cp_cv.GetTranslate(237, lang) + if msgId, ok := cp_e.CpLevelTitle[level.Level]; ok { + title = cp_cv.GetTranslate(msgId, lang) + } + var oldScore uint32 + if oldCp, _ := cp_m.GetOldConnectCp(model, cpRelation.UserId1, cpRelation.UserId2); oldCp != nil { + oldScore = uint32(oldCp.Score) + } + response := &user_cv.CvCp{ + CpUserInfo: userBases[cpUserId], + CpLevel: user_cv.CvCpLevel{ + Level: cpLevel, + Points: oldScore + cp_m.SumCpPoints(model, cpRelation.Id), // 历史分数 + Title: title, + }, + MyPrivilegeList: myPrivilegeList, + CpDays: int(time.Now().Sub(cpRelation.CreatedTime).Hours()/24) + 1, + CreatedUnix: cpRelation.CreatedTime.Unix(), + } + return response, nil +} diff --git a/domain/service/user_s/user.go b/domain/service/user_s/user.go new file mode 100644 index 0000000..f76cd74 --- /dev/null +++ b/domain/service/user_s/user.go @@ -0,0 +1,396 @@ +package user_s + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/rpc" + "gorm.io/gorm" + "hilo-user/_const/enum/user_e" + "hilo-user/cv/headwear_cv" + "hilo-user/cv/medal_cv" + "hilo-user/cv/noble_cv" + "hilo-user/cv/property_cv" + "hilo-user/cv/user_cv" + "hilo-user/domain/model/country_m" + "hilo-user/domain/model/diamond_m" + "hilo-user/domain/model/groupPower_m" + "hilo-user/domain/model/group_m" + "hilo-user/domain/model/noble_m" + "hilo-user/domain/model/user_m" + "hilo-user/domain/model/visit_m" + "hilo-user/domain/service/cp_s" + "hilo-user/myerr" +) + +type UserService struct { + svc *domain.Service +} + +func NewUserService(myContext *mycontext.MyContext) *UserService { + svc := domain.CreateService(myContext) + return &UserService{svc} +} + +//用户基本信息 +func (s *UserService) GetUserDetail(userId mysql.ID, myUserId mysql.ID, lang string) (*user_cv.CvUserDetail, error) { + model := domain.CreateModelContext(s.svc.MyContext) + model.Log.Infof("GetUserDetail %d begin", userId) + var user user_m.User + var err error + if err = model.DB().First(&user, userId).Error; err != nil { + return nil, myerr.WrapErr(err) + } + + //统计喜欢 + var likeN int64 + if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{ + UserId: myUserId, + LikeUserId: userId, + }).Count(&likeN).Error; err != nil { + return nil, myerr.WrapErr(err) + } + + var likeMe int64 + if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{ + UserId: userId, + LikeUserId: myUserId, + }).Count(&likeMe).Error; err != nil { + return nil, myerr.WrapErr(err) + } + + rel := make(map[mysql.ID]user_m.Relation, 1) + rel[userId], _ = user_m.GetRelation(model, myUserId, userId) + + var wealthUserScore user_m.MatchWealthUserScore + if err := model.DB().Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil { + if err != nil { + if err == gorm.ErrRecordNotFound { + wealthUserScore = user_m.MatchWealthUserScore{ + UserId: userId, + Score: 0, + Grade: 0, + } + } else { + return nil, myerr.WrapErr(err) + } + } + } + + var charmUserScore user_m.MatchCharmUserScore + if err := model.DB().Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{ + UserId: userId, + }).First(&charmUserScore).Error; err != nil { + if err != nil { + if err == gorm.ErrRecordNotFound { + charmUserScore = user_m.MatchCharmUserScore{ + UserId: userId, + Score: 0, + Grade: 0, + } + } else { + return nil, myerr.WrapErr(err) + } + } + } + + var activityUserScore user_m.MatchActityUserScore + if err := model.DB().Model(&user_m.MatchActityUserScore{}).Where(&user_m.MatchActityUserScore{ + UserId: userId, + }).First(&activityUserScore).Error; err != nil { + if err != nil { + if err == gorm.ErrRecordNotFound { + activityUserScore = user_m.MatchActityUserScore{ + UserId: userId, + Score: 0, + Grade: 0, + } + } else { + return nil, myerr.WrapErr(err) + } + } + } + isVip, expireTime, err := user_m.IsVip(userId) + if err != nil { + return nil, myerr.WrapErr(err) + } + svip, err := rpc.GetUserSvip(model, userId) + if err != nil { + return nil, myerr.WrapErr(err) + } + + headwear, err := headwear_cv.GetCvHeadwear(userId) + if err != nil { + return nil, err + } + + medals := make(map[uint64][]uint32, 0) + medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId) + if err != nil { + return nil, err + } + + medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals) + if err != nil { + return nil, err + } + + rooms, err := group_m.RoomLivingUserIdFilter(model, []uint64{userId}) + if err != nil { + return nil, err + } + // 2022-05-13 个人详情页:当用户在加锁的房间时,不显示进入房间的图标 + if g, ok := rooms[userId]; ok { + gi, err := group_m.GetGroupInfo(model, g) + if err != nil { + return nil, err + } + if gi != nil && len(gi.Password) > 0 { + rooms[userId] = "" + } + } + cp, err := cp_s.NewCpService(s.svc.MyContext).GetUserCp(userId, lang) + if err != nil { + return nil, err + } else if cp != nil && cp.CpUserInfo != nil { + headwear.HeadwearIcon = *cp.CpUserInfo.Avatar + } + + groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId) + if err != nil { + return nil, err + } + powers := map[mysql.ID]uint64{userId: groupPowerId} + powerNames := map[mysql.ID]string{userId: groupPowerName} + groupPower, _ := rpc.GetGroupPower(model, groupPowerId) + + up := user_m.UserProperty{} + rides, err := up.BatchGet(mysql.Db, []uint64{userId}) + 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 + } + ride := property_cv.CvProperty{ + Id: rides[user.ID], + PicUrl: properties[rides[user.ID]].PicUrl, + EffectUrl: properties[rides[user.ID]].EffectUrl, + SenderAvatar: properties[rides[user.ID]].SenderAvatar, + ReceiverAvatar: properties[rides[user.ID]].ReceiverAvatar, + Using: true, + } + noble, err := noble_m.FindActiveNoble(mysql.Db, userId) + if err != nil { + return nil, err + } + + //判断是不是工会 + userTradeUnion, err := user_m.GetUserTradeUnion(myUserId) + if err != nil { + return nil, err + } + + superManagerMap, err := user_m.GetSuperManagerMap([]uint64{userId}) + if err != nil { + return nil, err + } + + // 群组信息 + myGroups, err := group_m.FindGroupByOwner(model, userId) + if err != nil { + return nil, err + } + + // 手机绑定信息 + // 第三方账号绑定信息 + phoneInfo := new(user_m.UserPhoneInfo) + var thirdList []int8 + if userId == myUserId { + thirdList = make([]int8, 0, 5) + // 手机绑定信息 + bindInfo, err := user_m.GetUserBindInfoByUserId(model, userId) + if err != nil && err != gorm.ErrRecordNotFound { + return nil, err + } + if bindInfo != nil { + if len(bindInfo.Phone) > 2 { + phoneInfo.Phone = bindInfo.Phone[:2] + "****" + bindInfo.Phone[len(bindInfo.Phone)-2:] + } + phoneInfo.PhoneCountry = bindInfo.PhoneCountry + phoneInfo.AreaCode = bindInfo.AreaCode + phoneInfo.Icon = bindInfo.Icon + thirdList = append(thirdList, 1) + } + // 第三方账号绑定信息 + thirdInfoList, err := user_m.GetUserOauthByUserId(model, userId, 0) + if err != nil { + return nil, err + } + if thirdInfoList != nil { + for _, v := range thirdInfoList { + thirdList = append(thirdList, v.ThirdPartyType) + } + } + } + // 国家管理员 + countryManager, err := country_m.GetCountryMgr(model, userId) + if err != nil { + return nil, err + } + var cvCountryManager *user_cv.CVCountryManager + if countryManager != nil { + cvCountryManager = &user_cv.CVCountryManager{ + Country: countryManager.Country, + Role: countryManager.Role, + } + } + + return userToDetailOne(model, &user, myUserId, userTradeUnion, likeN > 0, likeMe > 0, + rel, isVip, expireTime, svip, headwear, ride, wealthUserScore.Grade, charmUserScore.Grade, + activityUserScore.Grade, medals[userId], medalInfo[userId], rooms[userId], powers[userId], powerNames[userId], groupPower, + noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager, cp) +} + +// 单用户版,简化参数 +func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]user_m.Relation, + isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32, + medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, groupPower rpc.CvGroupPowerInfo, noble *noble_m.UserNoble, isOfficialStaff bool, + myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *user_cv.CVCountryManager, cp *user_cv.CvCp) (*user_cv.CvUserDetail, error) { + + room, err := group_m.ToTxGroupId(model, room) + if err != nil { + model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err) + room = "" + } + + cvUserDetail := &user_cv.CvUserDetail{ + CvUserBase: user_cv.CvUserBase{ + Id: &user.ID, + Avatar: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Avatar)), + DefaultAvatar: &user.DefaultAvatar, + ExternalId: StrToString(&user.ExternalId), + Nick: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), user.Code, user.Nick)), + Description: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Description)), + Sex: TypeToUint8(&user.Sex), + Country: StrNil(user.Country), + CountryIcon: StrNil(user.CountryIcon), + Code: StrToString(&user.Code), + IsPrettyCode: user.IsPrettyCode(), + IsVip: isVip, + IsOfficialStaff: isOfficialStaff, + VipExpireTime: vipExpireTime, + Svip: svip, + MedalInfo: IfLogoutMedalInfo(IfLogout(user.LogoutTime), []medal_cv.CvMedal{}, medalInfo), + Headwear: IfLogoutHeadwear(IfLogout(user.LogoutTime), nil, headwear), + Ride: IfLogoutRide(IfLogout(user.LogoutTime), property_cv.CvProperty{}, ride), + }, + IsPush: TypeToUint8(&user.IsPush), + IsLike: &isLike, + IsLikeMe: &likeMe, + WealthUserGrade: wealthGrade, + CharmUserGrade: charmGrade, + ActivityUserGrade: activityGrade, + CurrentRoom: room, + MyGroupPower: power, + MyGroupPowerName: powerName, + GroupPower: groupPower, + PhoneInfo: phoneInfo, + ThirdList: thirdList, + CountryManager: countryManager, + Cp: cp, + } + if noble != nil { + cvUserDetail.Noble = noble_cv.CvNoble{ + Level: noble.Level, + EndTime: noble.EndTime.Unix(), + } + } + + //本人,计算,喜欢统计,钻石数量 + if user.ID == myUserId { + cvUserDetail.IsShowAge = TypeToUint8((*mysql.Type)(&user.IsShowAge)) + cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday) + + //喜欢统计 + var userCount user_m.UserCount + err := model.DB().Where(&user_m.UserCount{ + UserId: myUserId, + Type: user_e.CountTypeLikeMe, + }).First(&userCount).Error + if err != nil && err != gorm.ErrRecordNotFound { + return nil, myerr.WrapErr(err) + } + cvUserDetail.LikeCount = NumToUint32(&userCount.Num) + + //我喜欢统计 + var userILikeCount user_m.UserCount + err = mysql.Db.Where(&user_m.UserCount{ + UserId: myUserId, + Type: user_e.CountTypeLike, + }).First(&userILikeCount).Error + if err != nil && err != gorm.ErrRecordNotFound { + return nil, myerr.WrapErr(err) + } + cvUserDetail.ILikeCount = NumToUint32(&userILikeCount.Num) + + //访问统计 + var visitCount int64 + err = mysql.Db.Model(&visit_m.UserVisit{}).Where(&visit_m.UserVisit{ + VisitUserId: myUserId, + }).Count(&visitCount).Error + if err != nil && err != gorm.ErrRecordNotFound { + return nil, myerr.WrapErr(err) + } + vc := uint32(visitCount) + cvUserDetail.VisitCount = NumToUint32((*mysql.Num)(&vc)) + + //钻石数量 + cvDiamond, err := diamond_m.GetDiamondAccountByUserId(model, myUserId) + if err != nil { + return nil, err + } + cvUserDetail.DiamondNum = &cvDiamond.DiamondNum + cvUserDetail.PinkDiamondNum = &cvDiamond.PinkDiamondNum + + isAgent := user_m.IsAgent(myUserId) + cvUserDetail.IsAgentMgr = &isAgent + } else { + //不是本人 + if user.IsShowAge == mysql.OPEN { + cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday) + } + } + + if userTradeUnion == nil { + isTradeUnionFlag := false + cvUserDetail.IsTradeUnion = &isTradeUnionFlag + cvUserDetail.IsTradeUnionMatchNotification = nil + } else { + isTradeUnionFlag := true + cvUserDetail.IsTradeUnion = &isTradeUnionFlag + isTradeUnionMatchNotificationFlag := userTradeUnion.MatchNotification == mysql.OPEN + cvUserDetail.IsTradeUnionMatchNotification = &isTradeUnionMatchNotificationFlag + } + + // 永恒之心的值 + hv, ok := hvMap[user.ID] + if ok { + cvUserDetail.HeartValue = hv.HeartValue + cvUserDetail.HeartValueMax = hv.HeartValueMax + cvUserDetail.MeetDays = hv.MeetDays + } else { + cvUserDetail.HeartValueMax = 0 + } + + // 拥有的群组id + if len(myGroups) > 0 { + cvUserDetail.GroupId = myGroups[0].TxGroupId + } + + return cvUserDetail, nil +} diff --git a/domain/service/user_s/util.go b/domain/service/user_s/util.go new file mode 100644 index 0000000..7ff0777 --- /dev/null +++ b/domain/service/user_s/util.go @@ -0,0 +1,98 @@ +package user_s + +import ( + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-user/cv/headwear_cv" + "hilo-user/cv/medal_cv" + "hilo-user/cv/property_cv" + "time" +) + +//空字符串转成nil +func StrNil(msg string) *string { + if msg == "" { + return nil + } + return &msg +} + +func TypeToUint8(t *mysql.Type) *uint8 { + if *t == 0 { + return nil + } else { + return (*uint8)(t) + } +} + +func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 { + if *birthday == 0 { + return nil + } + return (*uint64)(birthday) +} + +func NumToUint32(num *mysql.Num) *uint32 { + return (*uint32)(num) +} + +func TimeToUint64(t *time.Time) *uint64 { + a := uint64(t.Unix()) + return &a +} + +func StrToString(str *mysql.Str) *string { + return (*string)(str) +} + +func IndexToUint16(i *mysql.Index) *uint16 { + return (*uint16)(i) +} + +func IdToUint64(id *mysql.ID) *uint64 { + return (*uint64)(id) +} + +func IfLogout(logoutTime int64) bool { + return logoutTime > 0 && time.Now().Unix() > logoutTime +} +func IfLogoutMedals(condition bool, trueVal, falseVal []uint32) []uint32 { + if condition { + return trueVal + } + return falseVal +} + +func IfLogoutMedalInfo(condition bool, trueVal, falseVal []medal_cv.CvMedal) []medal_cv.CvMedal { + if condition { + return trueVal + } + return falseVal +} + +func IfLogoutHeadwear(condition bool, trueVal, falseVal *headwear_cv.CvHeadwear) *headwear_cv.CvHeadwear { + if condition { + return trueVal + } + return falseVal +} + +func IfLogoutRide(condition bool, trueVal, falseVal property_cv.CvProperty) property_cv.CvProperty { + if condition { + return trueVal + } + return falseVal +} + +func IfLogoutStr(condition bool, trueVal, falseVal string) string { + if condition { + return trueVal + } + return falseVal +} + +func IfLogoutNick(condition bool, code string, nick string) string { + if condition { + return "Hilo No." + code + } + return nick +} diff --git a/route/router.go b/route/router.go index dfda755..60311fe 100755 --- a/route/router.go +++ b/route/router.go @@ -28,6 +28,8 @@ func InitRouter() *gin.Engine { { user.GET("/nameplate", wrapper(user_r.UserNameplate)) user.GET("/bag/:resType", wrapper(user_r.UserBag)) + user.GET("/detail", wrapper(user_r.UserDetail)) + user.GET("/detail/:userExternalId", wrapper(user_r.UserDetailByExternalId)) } cp := v2.Group("/cp") { diff --git a/route/user_r/user.go b/route/user_r/user.go new file mode 100644 index 0000000..a21243d --- /dev/null +++ b/route/user_r/user.go @@ -0,0 +1,108 @@ +package user_r + +import ( + "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" + "github.com/gin-gonic/gin" + "hilo-user/_const/redis_key/user_k" + "hilo-user/domain/model/group_m" + "hilo-user/domain/model/tim_m" + "hilo-user/domain/service/user_s" + "hilo-user/req" + "hilo-user/resp" + "time" +) + +// @Tags 用户 +// @Summary 获取用户详细信息 +// @Param token header string true "token" +// @Param timestamp header string true "时间戳" +// @Param nonce header string true "随机数字" +// @Param signature header string true "sha1加密结果" +// @Param deviceType header string true "系统类型 ios android" +// @Param deviceVersion header string true "系统版本" +// @Success 200 {object} user_cv.CvUserDetail +// @Router /v1/user/detail [get] +func UserDetail(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, lang, err := req.GetUserIdLang(c, myContext) + if err != nil { + return myContext, err + } + + cvUserDetail, err := user_s.NewUserService(myContext).GetUserDetail(userId, userId, lang) + if err != nil { + return myContext, err + } + resp.ResponseOk(c, cvUserDetail) + return myContext, nil +} + +// @Tags 用户 +// @Summary 获取用户详细信息 +// @Param token header string true "token" +// @Param timestamp header string true "时间戳" +// @Param nonce header string true "随机数字" +// @Param signature header string true "sha1加密结果" +// @Param deviceType header string true "系统类型 ios android" +// @Param deviceVersion header string true "系统版本" +// @Param userExternalId path string true "userExternalId" +// @Param groupId query string false "群组id,当传了该id,则返回该用户在该群组的身份" +// @Success 200 {object} user_cv.CvUserDetail +// @Router /v1/user/detail/{userExternalId} [get] +func UserDetailByExternalId(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, lang, err := req.GetUserIdLang(c, myContext) + if err != nil { + return myContext, err + } + otherUserId, err := req.ToUserId(myContext, mysql.Str(c.Param("userExternalId"))) + if err != nil { + return nil, err + } + model := domain.CreateModelContext(myContext) + + imGroupId := c.Query("groupId") + if imGroupId != "" { + imGroupId, err = group_m.ToImGroupId(model, imGroupId) + if err != nil { + return myContext, err + } + } + + cvUserDetail, err := user_s.NewUserService(myContext).GetUserDetail(otherUserId, userId, lang) + if err != nil { + return myContext, err + } + if imGroupId != "" { + cvUserDetail.GroupRole, err = group_m.GetGroupRoleById(model, imGroupId, otherUserId) + if err != nil { + return myContext, err + } + } + + if cvUserDetail != nil { + // 检查是否需要同步 + if n, err := redisCli.GetRedis().Exists(model, user_k.GetKeySyncTimHilo(userId)).Result(); err == nil { + if n == 0 { + // FIXME:转异步执行 + err = tim_m.FlushHiloInfo(*cvUserDetail.ExternalId, cvUserDetail.IsVip, cvUserDetail.IsPrettyCode, + nil, cvUserDetail.MyGroupPowerName, cvUserDetail.Noble.Level) + if err == nil { + redisCli.GetRedis().Set(model, user_k.GetKeySyncTimHilo(userId), "1", time.Minute) + } else { + model.Log.Info("UserBaseByExternalId, FlushHiloInfo failed: ", err) + } + } else { + model.Log.Info("UserDetailByExternalId, no need to sync yet: ", userId) + } + } else { + model.Log.Info("UserDetailByExternalId, check KeySyncTimHilo failed", err) + } + } + + resp.ResponseOk(c, cvUserDetail) + return myContext, nil +} -- 2.22.0