package groupPower_m import ( "context" "encoding/json" "fmt" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/utils" "gorm.io/gorm" "gorm.io/gorm/clause" "hilo-group/_const/enum/groupPower_e" "hilo-group/_const/redis_key" "hilo-group/domain/model/group_m" "hilo-group/myerr" "hilo-group/myerr/bizerr" "runtime/debug" "strconv" "time" ) type GroupPower struct { mysql.Entity *domain.Model `gorm:"-"` GroupUid mysql.Str Name mysql.Str Status groupPower_e.GroupPowerStatus Nameplate mysql.Str // 铭牌 Declaration mysql.Str // 宣言 Icon mysql.Str // 头像 GradeName mysql.Str // 等级称号 GradeMedal mysql.Str // 等级勋章图片 Grade groupPower_e.GroupPowerGrade `gorm:"-"` ModifyNameplate mysql.YesNo } type GroupPowerUser struct { mysql.Entity *domain.Model `gorm:"-"` GroupPowerId mysql.ID UserId mysql.ID Role groupPower_e.GroupPowerUserRole } type ActFamilyMonthRankLog struct { Id uint64 `json:"id"` Period string `json:"period"` FamilyId uint64 `json:"family_id"` RankFamily int `json:"rank_family"` RankUser int `json:"rank_user"` UserId uint64 `json:"user_id"` Award string `json:"award"` } func (gpu *GroupPowerUser) Get(db *gorm.DB) ([]GroupPowerUser, error) { rows := make([]GroupPowerUser, 0) err := db.Where(gpu).Find(&rows).Error if err != nil { return nil, err } return rows, nil } func GetPowerOwner(db *gorm.DB, powerId uint64) (uint64, error) { gpu := GroupPowerUser{GroupPowerId: powerId, Role: groupPower_e.GroupPowerUserRoleMgr} records, err := gpu.Get(db) if err != nil { return 0, err } if len(records) != 1 { return 0, bizerr.GroupPowerNoOwner } return records[0].UserId, nil } func GetPowerOwnerMap(model *domain.Model, powerIds []uint64) (map[uint64]uint64, error) { rows := make([]GroupPowerUser, 0) if len(powerIds) > 0 { if err := model.DB().Model(&GroupPowerUser{}). Where("group_power_id IN ? and role = ?", powerIds, groupPower_e.GroupPowerUserRoleMgr). Find(&rows).Error; err != nil { return nil, err } } result := make(map[uint64]uint64, 0) for _, i := range rows { result[i.GroupPowerId] = i.UserId } return result, nil } func GetMyPowerId(db *gorm.DB, userId uint64) (uint64, error) { gpu := GroupPowerUser{UserId: userId, Role: groupPower_e.GroupPowerUserRoleMgr} records, err := gpu.Get(db) if err != nil { return 0, err } if len(records) > 0 { return records[0].GroupPowerId, nil } return 0, nil } func (gpu *GroupPowerUser) GetCount(db *gorm.DB) (uint, error) { var count int64 = 0 err := db.Model(&GroupPowerUser{}).Where(gpu).Count(&count).Error if err != nil { return 0, err } return uint(count), nil } type GroupPowerUserLog struct { mysql.Entity GroupPowerId mysql.ID UserId mysql.ID OperateType groupPower_e.GroupPowerUserLogType Remark mysql.Str } //记录日志 func addGroupPowerUserLog(model *domain.Model, groupPowerId mysql.ID, userId mysql.ID, operateType groupPower_e.GroupPowerUserLogType, remark string) error { if err := model.Db.Create(&GroupPowerUserLog{ GroupPowerId: groupPowerId, UserId: userId, OperateType: operateType, Remark: remark, }).Error; err != nil { return myerr.WrapErr(err) } return nil } func GetGroupPowerUserLog(db *gorm.DB, groupPowerId mysql.ID, beginTime time.Time) ([]GroupPowerUserLog, error) { rows := make([]GroupPowerUserLog, 0) gpu := GroupPowerUserLog{GroupPowerId: groupPowerId} if err := db.Where(gpu).Where("created_time BETWEEN ? AND NOW()", beginTime).Order("id DESC").Find(&rows).Error; err != nil { return nil, err } return rows, nil } type GroupPowerDiamondLog struct { mysql.Entity GroupPowerId mysql.ID SendUserId mysql.ID SendGroupId mysql.Str ReceiveUserId mysql.ID DiamondNum mysql.Num GiftId mysql.ID GiftNum mysql.Num GiftOperateId mysql.ID Type groupPower_e.GroupPowerDiamondLogType } func (*GroupPowerDiamondLog) TableName() string { month := time.Now().Format("200601") return fmt.Sprintf("group_power_diamond_log_%s", month) } func addGroupPowerDiamondLog(model *domain.Model, groupPowerId mysql.ID, sendUserId mysql.ID, sendGroupId mysql.Str, receiveUserId mysql.ID, diamondNum mysql.Num, giftId mysql.ID, giftNum mysql.Num, giftOperateId mysql.ID, t groupPower_e.GroupPowerDiamondLogType) error { if err := model.Db.Table((&GroupPowerDiamondLog{}).TableName()).Create(&GroupPowerDiamondLog{ GroupPowerId: groupPowerId, SendUserId: sendUserId, SendGroupId: sendGroupId, ReceiveUserId: receiveUserId, DiamondNum: diamondNum, GiftId: giftId, GiftNum: giftNum, GiftOperateId: giftOperateId, Type: t, }).Error; err != nil { return myerr.WrapErr(err) } go func() { defer func() { if r := recover(); r != nil { //打印错误堆栈信息 model.Log.Errorf("GroupPowerDiamondLog Persistent SYSTEM ACTION PANIC: %v, stack: %v", r, string(debug.Stack())) } }() //增加到缓存,不要处理错误,接受缓存失败 now := time.Now() nowTime, err := time.ParseInLocation(utils.DATE_FORMAT, now.Format(utils.DATE_FORMAT), time.Local) if err != nil { model.Log.Infof("addGroupPowerDiamondLog ZIncrBy err:%v", err) } beginDate := utils.GetMonday(nowTime) key := redis_key.GetGroupPowerDiamondLogWeek(beginDate.Format(utils.COMPACT_DATE_FORMAT)) if err := redisCli.GetRedis().ZIncrBy(context.Background(), key, float64(diamondNum), strconv.FormatUint(groupPowerId, 10)).Err(); err != nil { model.Log.Infof("addGroupPowerDiamondLog ZIncrBy err:%v", err) } if ttl, err := redisCli.GetRedis().TTL(context.Background(), key).Result(); err != nil { model.Log.Errorf("addGroupPowerDiamondLog ZIncrBy TTL err:%v, key:%v", err, key) } else { if ttl < 0 { //延长到30天,避免数据丢失 redisCli.GetRedis().ExpireAt(context.Background(), key, time.Now().AddDate(0, 0, 30)) } } }() return nil } type GroupPowerWeekDiamond struct { Week string PowerId mysql.ID GroupId mysql.Str Diamond uint64 } func (gpwd *GroupPowerWeekDiamond) AddDiamond(db *gorm.DB) error { return db.Clauses(clause.OnConflict{ DoUpdates: clause.Assignments(map[string]interface{}{ "diamond": gorm.Expr("diamond + ?", gpwd.Diamond)}), }).Create(gpwd).Error } func GetPowerWeekDiamond(db *gorm.DB, week string, powerId mysql.ID) (uint32, error) { gpwd := GroupPowerWeekDiamond{Week: week, PowerId: powerId} type summary struct { Sum uint32 } row := summary{} if err := db.Model(&GroupPowerWeekDiamond{}). Select("SUM(diamond) AS sum").Where(&gpwd).First(&row).Error; err != nil { return 0, err } return row.Sum, nil } func GetAllPowerWeekDiamond(db *gorm.DB, week string) (map[uint64]uint32, error) { gpwd := GroupPowerWeekDiamond{Week: week} type summary struct { PowerId uint64 Sum uint32 } rows := make([]summary, 0) if err := db.Model(&GroupPowerWeekDiamond{}). Select("power_id, SUM(diamond) AS sum").Where(&gpwd).Group("power_id").Find(&rows).Error; err != nil { return nil, err } result := make(map[uint64]uint32, 0) for _, i := range rows { result[i.PowerId] = i.Sum } return result, nil } type PowerSupportAward struct { mysql.Entity Week string PowerId mysql.ID Diamond uint32 Level string Owner mysql.ID OwnerSalary uint32 Assistant_1 mysql.ID Assistant_2 mysql.ID Assistant_3 mysql.ID Assistant_Salary uint32 } func (psa *PowerSupportAward) Create(db *gorm.DB) (int64, error) { result := db.Clauses(clause.OnConflict{DoNothing: true}). Create(psa) return result.RowsAffected, result.Error } func (psa *PowerSupportAward) Find(db *gorm.DB) (*PowerSupportAward, error) { rows := make([]PowerSupportAward, 0) if err := db.Where(psa).Find(&rows).Error; err != nil { return nil, err } if len(rows) <= 0 { return nil, nil } return &rows[0], nil } func (psa *PowerSupportAward) FindAll(db *gorm.DB) ([]PowerSupportAward, error) { rows := make([]PowerSupportAward, 0) if err := db.Where(psa).Find(&rows).Error; err != nil { return nil, err } return rows, nil } func GetGroupPowerByUserId(model *domain.Model, userId uint64) (*GroupPower, error) { if groupPowerUser, err := GetGroupPowerUserOrNil(model, userId); err != nil { return nil, err } else if groupPowerUser == nil { return nil, nil } else { return GetGroupPowerOrErr(model, groupPowerUser.GroupPowerId) } } 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 } func InitGroupPower(model *domain.Model, groupUuid string, name string, owerUserId mysql.ID) (*GroupPower, *GroupPowerUser, error) { //检查改用户是否已经加入了别的势力 /* var n int64 if err := model.Db.Model(&GroupPowerUser{}).Where(&GroupPowerUser{ UserId: owerUserId, }).Count(&n).Error; err != nil { return nil, nil, myerr.NewSysErrorF("用户已经加入了别的势力") }*/ if flag, _, err := CheckGroupPowerUser(model, owerUserId); err != nil { return nil, nil, err } else if flag { return nil, nil, myerr.NewSysErrorF("用户已经加入了别的势力") } return &GroupPower{ Model: model, GroupUid: groupUuid, Name: name, Status: groupPower_e.GroupPowerUserHas, }, &GroupPowerUser{ Model: model, GroupPowerId: 0, UserId: owerUserId, Role: groupPower_e.GroupPowerUserRoleMgr, }, 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 GetGroupPowerByGroupOrNil(model *domain.Model, groupUid string) (*GroupPower, error) { groupPower := GroupPower{} if err := model.Db.Where(&GroupPower{ GroupUid: groupUid, }).First(&groupPower).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } else { return nil, myerr.WrapErr(err) } } groupPower.Model = model return &groupPower, nil } // 某个势力的势力主是否是代理 func IsGroupPowerHasMgrDealer(model *domain.Model, groupId mysql.ID) (bool, error) { var num int64 if err := model.Db.Raw("select count(1) from (select * from diamond_dealer where user_id in "+ "(select user_id from group_power_user where group_power_id = ? and role = ?)) a", groupId, groupPower_e.GroupPowerUserRoleMgr). Scan(&num).Error; err != nil { return false, myerr.WrapErr(err) } if num > 0 { return true, nil } return false, nil } // 某个家族是否有家族代理 func IsGroupPowerHasFamilyAgent(model *domain.Model, groupId mysql.ID) (bool, error) { var num int64 if err := model.Db.Raw("select count(1) from diamond_dealer where status=1 and is_family_agent=1 and user_id in "+ "(select user_id from group_power_user where group_power_id = ?)", groupId). Scan(&num).Error; err != nil { return false, myerr.WrapErr(err) } if num > 0 { return true, nil } return false, nil } func GetGroupPowerMap(db *gorm.DB, userIds []mysql.ID) (map[mysql.ID]uint64, error) { rows := make([]GroupPowerUser, 0) if len(userIds) > 0 { if err := db.Model(&GroupPowerUser{}).Where("user_id IN ?", userIds).Find(&rows).Error; err != nil { return nil, err } } result := make(map[mysql.ID]uint64, 0) for _, i := range rows { result[i.UserId] = i.GroupPowerId } return result, nil } // return func GetGroupPowerNames(db *gorm.DB, ids []mysql.ID) (map[mysql.ID]string, map[mysql.ID]string, error) { type record struct { Id mysql.ID Name string Nameplate string } rows := make([]record, 0) result := make(map[mysql.ID]string, 0) result2 := make(map[mysql.ID]string, 0) if len(ids) > 0 { if err := db.Model(&GroupPower{}).Select("p.id, i.name,p.nameplate"). Joins("AS p INNER JOIN group_info AS i ON p.group_uid = i.im_group_id"). Where("p.id IN ?", ids).Find(&rows).Error; err != nil { return result, result2, err } } for _, i := range rows { result[i.Id] = i.Name result2[i.Id] = i.Nameplate } return result, result2, nil } func GetGroupPower(model *domain.Model, id mysql.ID) (*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 } // 判断势力是否合法 func IsGroupPowerActive(model *domain.Model, id mysql.ID) (bool, error) { gp, err := GetGroupPower(model, id) if err != nil { if err == gorm.ErrRecordNotFound { return false, nil } else { return false, err } } if gp == nil || gp.Status != groupPower_e.GroupPowerUserHas { return false, nil } return true, nil } func getGroupPowerUser(model *domain.Model, groupPowerId mysql.ID, userId mysql.ID) (*GroupPowerUser, error) { groupPowerUser := GroupPowerUser{} if err := model.Db.Where(&GroupPowerUser{ GroupPowerId: groupPowerId, UserId: userId, }).First(&groupPowerUser).Error; err != nil { return nil, myerr.WrapErr(err) } groupPowerUser.Model = model return &groupPowerUser, nil } //false:不存在, true:存在 func CheckGroupPowerUser(model *domain.Model, userId mysql.ID) (bool, mysql.ID, error) { groupPowerUser := GroupPowerUser{} if err := model.Db.Where(&GroupPowerUser{ UserId: userId, }).First(&groupPowerUser).Error; err != nil { if err == gorm.ErrRecordNotFound { return false, 0, nil } else { return false, 0, myerr.WrapErr(err) } } return true, groupPowerUser.GroupPowerId, nil } //获取势力主 func GetGroupPowerMgr(model *domain.Model, groupPowerId mysql.ID) (mysql.ID, error) { groupPowerUser := GroupPowerUser{} if err := model.Db.Where(&GroupPowerUser{ GroupPowerId: groupPowerId, Role: groupPower_e.GroupPowerUserRoleMgr, }).First(&groupPowerUser).Error; err != nil { return 0, myerr.WrapErr(err) } return groupPowerUser.UserId, nil } //获取势力主和管理员 func GetGroupPowerMgrList(model *domain.Model, groupPowerId mysql.ID) ([]mysql.ID, error) { res := make([]mysql.ID, 0) err := model.Db.Model(GroupPowerUser{}).Select("user_id").Where("group_power_id = ? and role in (2,3)", groupPowerId).Scan(&res).Error if err != nil { return res, myerr.WrapErr(err) } return res, nil } //运营平台让用户离开 func (groupPower *GroupPower) MgrUserLeave(userId mysql.ID) (*GroupPowerUser, error) { // groupPowerUser, err := getGroupPowerUser(groupPower.Model, groupPower.ID, userId) if err != nil { return nil, err } if groupPowerUser.Role == groupPower_e.GroupPowerUserRoleMgr { return nil, bizerr.GroupPowerOwnerLeave } if err := addGroupPowerUserLog(groupPower.Model, groupPower.ID, userId, groupPower_e.GroupPowerUserLogTypeMgrLeave, ""); err != nil { return nil, err } groupPowerUser.SetDel() return groupPowerUser, nil } //正常 func (groupPower *GroupPower) MgrNormal() *GroupPower { groupPower.Status = groupPower_e.GroupPowerUserHas return groupPower } //冻结 func (groupPower *GroupPower) MgrFrozen() *GroupPower { groupPower.Status = groupPower_e.GroupPowerUserNo return groupPower } //解散。移除所有信息 func (groupPower *GroupPower) MgrDissolve() (*GroupPower, error) { //对比查询的数量 == 删除的数量,不一致,则不能删除 if groupPower.ID == 0 { return groupPower, myerr.NewSysErrorF("groupPower dissolve groupPowerId = 0") } groupPowerUsers := []GroupPowerUser{} if err := groupPower.Db.Model(&GroupPowerUser{}).Where(&GroupPowerUser{ GroupPowerId: groupPower.ID, }).Find(&groupPowerUsers).Error; err != nil { return nil, myerr.WrapErr(err) } if len(groupPowerUsers) == 0 { return nil, myerr.NewSysErrorF("groupPower dissolve user.num == 0") } //删除groupPowerUser中信息 delN := groupPower.Db.Model(&GroupPowerUser{}).Where(&GroupPowerUser{ GroupPowerId: groupPower.ID, }).Delete(&GroupPowerUser{ GroupPowerId: groupPower.ID, }).RowsAffected if int64(len(groupPowerUsers)) != delN { return nil, myerr.NewSysErrorF("groupPower dissolve delN != selectN") } groupPowerUserStr, err := json.Marshal(groupPowerUsers) if err != nil { return nil, myerr.WrapErr(err) } //增加删除日志 if err := addGroupPowerUserLog(groupPower.Model, groupPower.ID, 0, groupPower_e.GroupPowerUserLogDissolve, string(groupPowerUserStr)); err != nil { return nil, myerr.WrapErr(err) } // groupPower.Status = groupPower_e.GroupPowerDissolve groupPower.GroupUid = groupPower.GroupUid + "_" + "del" + "_" + time.Now().Format(utils.COMPACT_MONTH_FORMAT) return groupPower, nil } //修改名字 func (groupPower *GroupPower) EditName(name string) *GroupPower { groupPower.Name = name return groupPower } //修改群组 func (groupPower *GroupPower) EditGroupUid(groupUid string) *GroupPower { groupPower.GroupUid = groupUid return groupPower } func (groupPower *GroupPower) EditPowerOwer(owerUserId mysql.ID) (*GroupPower, *GroupPowerUser, *GroupPowerUser, error) { oldGroupPowerUser := GroupPowerUser{} if err := groupPower.Db.Where(&GroupPowerUser{ GroupPowerId: groupPower.ID, Role: groupPower_e.GroupPowerUserRoleMgr, }).First(&oldGroupPowerUser).Error; err != nil { return nil, nil, nil, myerr.WrapErr(err) } //势力主离开, if oldGroupPowerUser.UserId == owerUserId { //势力主没有变化,无需修改 return groupPower, nil, nil, nil } else { oldGroupPowerUser.Model = groupPower.Model oldGroupPowerUser.SetDel() if err := addGroupPowerUserLog(groupPower.Model, groupPower.ID, oldGroupPowerUser.UserId, groupPower_e.GroupPowerUserLogTypeMgrLeave, ""); err != nil { return nil, nil, nil, err } } // return groupPower, &oldGroupPowerUser, &GroupPowerUser{ Model: groupPower.Model, GroupPowerId: groupPower.ID, UserId: owerUserId, Role: groupPower_e.GroupPowerUserRoleMgr, }, nil } //增加普通用户 func (groupPower *GroupPower) UserJoin(userId mysql.ID) (*GroupPowerUser, error) { //判断是否已经加入了国家势力 if flag, groupPowerId, err := CheckGroupPowerUser(groupPower.Model, userId); err != nil { return nil, err } else if flag == true { if groupPowerId == groupPower.ID { return nil, bizerr.GroupPowerHasJoinMy } else { return nil, bizerr.GroupPowerHasJoinOther } } if err := addGroupPowerUserLog(groupPower.Model, groupPower.ID, userId, groupPower_e.GroupPowerUserLogTypeUserJoin, ""); err != nil { return nil, err } return &GroupPowerUser{ Model: groupPower.Model, GroupPowerId: groupPower.ID, UserId: userId, Role: groupPower_e.GroupPowerUserRoleUser, }, nil } // 离开国家势前至少要多少小时 const GROUP_POWER_LEAVE_LIMIT = 3 //用户退出国家势力 func (groupPower *GroupPower) UserLeave(userId mysql.ID) (*GroupPowerUser, time.Duration, error) { groupPowerUser, err := getGroupPowerUser(groupPower.Model, groupPower.ID, userId) if err != nil { return nil, 0, err } if groupPowerUser.Role == groupPower_e.GroupPowerUserRoleMgr { return nil, 0, bizerr.GroupPowerOwnerLeave } // 2022-02-14产品增加限制:加入势力10天内不能退出;2022-02-28:调整为15天;2022-06-20调整为3小时 now := time.Now() endTime := groupPowerUser.CreatedTime.Add(time.Hour * GROUP_POWER_LEAVE_LIMIT) if now.Before(endTime) { diff := endTime.Sub(now) return nil, diff, bizerr.GroupPowerStayTooShort } if err := addGroupPowerUserLog(groupPower.Model, groupPower.ID, userId, groupPower_e.GroupPowerUserLogTypeUserLeave, ""); err != nil { return nil, 0, err } groupPowerUser.SetDel() return groupPowerUser, 0, nil } // 查询用户加入的国家势力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 } // 获取势力下的所有群组 func GetGroupPowerGroups(model *domain.Model, groupPowerId mysql.ID) ([]*group_m.GroupInfo, error) { var res []*group_m.GroupInfo var ownerIds []mysql.ID if err := model.DB().Model(GroupPowerUser{}).Select("user_id").Where("group_power_id = ?", groupPowerId).Scan(&ownerIds).Error; err != nil { model.Log.Errorf("GetGroupPowerGroups fail:%v", err) return nil, err } if len(ownerIds) <= 0 { return res, nil } if err := model.DB().Model(group_m.GroupInfo{}).Where("owner in ?", ownerIds).Find(&res).Error; err != nil { model.Log.Errorf("GetGroupPowerGroups fail:%v", err) return nil, err } return res, nil } // 批量获取势力用户 // return userId->GroupPowerUser func BatchGetGroupPowerUser(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]GroupPowerUser, error) { var rows []GroupPowerUser res := make(map[mysql.ID]GroupPowerUser) if err := model.Db.Model(GroupPowerUser{}).Where("user_id in ?", userIds).Find(&rows).Error; err != nil { model.Log.Errorf("BatchGetGroupPowerUser fail:%v", err) return res, err } for i, v := range rows { res[v.UserId] = rows[i] } return res, nil } func CreateActFamilyMonthRankLog(model *domain.Model, list []*ActFamilyMonthRankLog) error { return model.DB().CreateInBatches(&list, 50).Error }