diff --git a/call/config.go b/call/config.go index 99c0b5a..cea43c9 100644 --- a/call/config.go +++ b/call/config.go @@ -82,6 +82,12 @@ var ( configPopUp []*common.ConfigPopUp configPdd *common.ConfigPdd configLuckyWheel *common.ConfigLuckyWheel + + configShareBanner []*common.ConfigShareBanner + configShareTaskNew []*common.ConfigShareTaskNew + configShareLimitTask []*common.ConfigShareLimitTask + configShareWithdrawProducts []*common.ConfigShareWithdrawProducts + ConfigWithdrawChannels []*common.ConfigWithdrawChannels ) var ( @@ -1029,35 +1035,79 @@ func GetConfigAppSpin() []*common.ConfigAppSpin { } func LoadConfigShare() (err error) { - one := []*common.ConfigShare{} - if _, err = db.Mysql().QueryAll("", "level", &common.ConfigShare{}, &one); err != nil { + list := []*common.ConfigShare{} + if _, err = db.Mysql().QueryAll("open = 1", "level asc", &common.ConfigShare{}, &list); err != nil { log.Error("err:%v", err) return err } - configShare = one + for _, v := range list { + if v.InviteReward != "" { + err := json.Unmarshal([]byte(v.InviteReward), &v.SubInviteReward) + if err != nil { + log.Error("err:%v", err) + return err + } + } + if v.NewReward != "" { + err := json.Unmarshal([]byte(v.NewReward), &v.SubNewReward) + if err != nil { + log.Error("err:%v", err) + return err + } + } + if v.RewardTiers != "" { + err := json.Unmarshal([]byte(v.RewardTiers), &v.SubRewardTiers) + if err != nil { + log.Error("err:%v", err) + return err + } + } + } + configShare = list return nil } -func GetConfigShare() []*common.ConfigShare { - return configShare +func GetConfigShare(level, channel int) *common.ConfigShare { + for _, v := range configShare { + if v.Level != level { + continue + } + if v.Channel == channel || v.Channel == channel-10000 { + return v + } + } + return nil } -func GetConfigShareLevelByBet(bet int64) *common.ConfigShare { - for i := len(configShare) - 1; i >= 0; i-- { - if bet >= configShare[i].Bet { - return configShare[i] +func GetConfigShareByExp(channel int, exp int64) (ret *common.ConfigShare) { + cons := GetConfigShares(channel) + if len(cons) == 0 { + return + } + for i, v := range cons { + if v.Exp < 0 { + continue + } + if exp == v.Exp { + return v + } + if exp < v.Exp && i > 0 { + return cons[i-1] } } - return nil + ret = cons[len(cons)-1] + return } -func GetConfigShareByLevel(level int) *common.ConfigShare { +func GetConfigShares(channel int) []*common.ConfigShare { + var result []*common.ConfigShare for _, v := range configShare { - if level == v.Level { - return v + if v.Channel == channel || v.Channel == channel-10000 { + result = append(result, v) + continue } } - return nil + return result } // LoadConfigShareSys 分享系统配置 @@ -2110,3 +2160,102 @@ func GetConfigLuckyWheel() *common.ConfigLuckyWheel { } return configLuckyWheel } + +func LoadConfigShareBanner() (err error) { + list := []*common.ConfigShareBanner{} + if _, err = db.Mysql().QueryAll("", "sort asc", &common.ConfigShareBanner{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configShareBanner = list + return nil +} + +func GetConfigShareBanner(channel int) []*common.ConfigShareBanner { + var result []*common.ConfigShareBanner + for _, v := range configShareBanner { + if v.Channel == channel || v.Channel == channel-10000 { + result = append(result, v) + continue + } + } + return result +} + +func LoadConfigShareTaskNew() (err error) { + list := []*common.ConfigShareTaskNew{} + if _, err = db.Mysql().QueryAll("", "task_id asc", &common.ConfigShareTaskNew{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configShareTaskNew = list + return nil +} + +func GetConfigShareTaskNew() []*common.ConfigShareTaskNew { + return configShareTaskNew +} + +func LoadConfigShareLimitTask() (err error) { + list := []*common.ConfigShareLimitTask{} + if _, err = db.Mysql().QueryAll("", "level asc", &common.ConfigShareLimitTask{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configShareLimitTask = list + return nil +} + +func GetConfigShareLimitTask(level, channel int) *common.ConfigShareLimitTask { + for _, v := range configShareLimitTask { + if v.Level != level { + continue + } + if v.Channel == channel || v.Channel == channel-10000 { + return v + } + } + return nil +} + +func LoadConfigShareWithdrawProducts() (err error) { + list := []*common.ConfigShareWithdrawProducts{} + if _, err = db.Mysql().QueryAll("", "amount asc", &common.ConfigShareWithdrawProducts{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configShareWithdrawProducts = list + return nil +} + +func GetConfigShareWithdrawProducts(channel int) []*common.ConfigShareWithdrawProducts { + var result []*common.ConfigShareWithdrawProducts + for _, v := range configShareWithdrawProducts { + if v.Channel == channel || v.Channel == channel-10000 { + result = append(result, v) + continue + } + } + return result +} + +func GetShareWithdrawInfo(uid int) *common.ShareWithdrawInfo { + info := &common.ShareWithdrawInfo{UID: uid} + db.Mysql().Get(info) + now := time.Now().Unix() + if info.ID == 0 { + info.DayTime = now + db.Mysql().Create(info) + } + info.SubRecord = map[int64]int{} + if info.Record != "" { + json.Unmarshal([]byte(info.Record), &info.SubRecord) + } + if !util.IsSameDayTimeStamp(now, info.DayTime) { + info.DayCount = 0 + } + if info.DayCount < 0 { + info.DayCount = 0 + } + return info +} diff --git a/call/es.go b/call/es.go new file mode 100644 index 0000000..5e6fce7 --- /dev/null +++ b/call/es.go @@ -0,0 +1,113 @@ +package call + +import ( + "context" + "encoding/json" + "server/db" + "server/natsClient" + "server/pb" + "server/util" + "time" + + "github.com/liangdas/mqant/log" + "github.com/olivere/elastic/v7" +) + +func InsertToESGO(index string, params interface{}, id ...string) { + if GetTopicName() == "common" { + data := &WriteData{Index: index, Data: params} + if id != nil { + data.ID = id[0] + } + Go(func() { + AddBulk(data) + }) + } else { + byt, _ := json.Marshal(params) + data := &pb.InnerESBulk{Index: index, Data: string(byt)} + if id != nil { + data.ID = id[0] + } + Go(func() { Publish(natsClient.TopicInnerESBulk, data) }) + } +} + +var ( + Bulk *elastic.BulkService + WriteChan = make(chan *WriteData, 20000) + ESCloseChan = make(chan struct{}) + ESFinishChan = make(chan struct{}) // 完成信号 + MaxSize int64 = 50 * 1024 * 1024 // bulk最大长度 +) + +type WriteData struct { + ID string + Index string + Data interface{} +} + +func InitBulkQueue() { + es := db.ES().C() + Bulk = es.Bulk() + util.Go(func() { + t := time.NewTimer(time.Second) + for { + select { + case <-t.C: + t.Reset(time.Second) + Flush() + case one := <-WriteChan: + e := elastic.NewBulkCreateRequest().Index(one.Index) + if one.ID != "" { + e.Id(one.ID) + } + e.Doc(one.Data) + Bulk.Add(e) + if Bulk.EstimatedSizeInBytes() >= MaxSize { + Flush() + } + case <-ESCloseChan: + log.Debug("module closing") + Flush() + ESFinishChan <- struct{}{} + } + // fmt.Println(total) + } + }) +} + +func AddBulk(w *WriteData) { + WriteChan <- w +} + +func Flush() { + if Bulk.EstimatedSizeInBytes() <= 0 { + return + } + bulk := Bulk + // util.IndexTry(func() error { + util.Go(func() { + _, err := bulk.Do(context.Background()) + if err != nil { + log.Error("err:%v", err) + // return err + } + }) + // return nil + // }) + Bulk = db.ES().C().Bulk() +} + +// 滚动设置新的索引 +func Rollover(aliasName, indexName string) { + if db.ES().IndexExist(indexName) { + return + } + // 不存在创建 + if !db.ES().IndexExist(aliasName) { + db.ES().CreateExist(indexName) + db.ES().AddAlias(aliasName, indexName) + } else { + db.ES().Rollover(aliasName, indexName, nil) + } +} diff --git a/call/recover.go b/call/recover.go new file mode 100644 index 0000000..6e0a0b5 --- /dev/null +++ b/call/recover.go @@ -0,0 +1,87 @@ +package call + +import ( + "fmt" + "runtime" + "server/common" + "time" + + "github.com/liangdas/mqant/log" +) + +// Go 用协程处理f +func Go(f func()) { + go func() { + defer Recover() + f() + }() +} + +func IndexTryCallback(f func() error, cb func()) { + Go(func() { + for i := 0; i <= 6; i++ { + if i > 0 { + next := time.Duration(i*i) * time.Minute + time.Sleep(next) + } + err := f() + if err == nil { + break + } + log.Error("err:%v next:%v", err, i) + if i == 6 { + cb() + } + } + }) +} + +func IndexTry(f func() error) { + Go(func() { + for i := 0; i <= 6; i++ { + if i > 0 { + next := time.Duration(i*i) * time.Minute + time.Sleep(next) + } + err := f() + if err == nil { + break + } + log.Error("err:%v next:%v", err, i) + } + }) +} + +func IndexTryS(f func() error) { + Go(func() { + for i := 0; i <= 6; i++ { + if i > 0 { + next := time.Duration(i*i) * time.Second + time.Sleep(next) + } + err := f() + if err == nil { + break + } + log.Error("err:%v next:%v", err, i) + } + }) +} + +// 捕获异常并打日志 +// Usage: defer Recover() +func Recover() { + if err := recover(); err != nil { + buf := make([]byte, 1024) + runtime.Stack(buf, false) + str := fmt.Sprintf("%+v", err) + log.Error("panic(%s), stack:\n%s", str, string(buf)) + name := GetCaller().GetType() + InsertToESGO(common.ESIndexBackPanic, common.ESPanic{ + Module: name, + Func: str, + Time: time.Now().Unix(), + Error: string(buf), + }) + } +} diff --git a/call/reload.go b/call/reload.go index 22a8dc6..8efa7ef 100644 --- a/call/reload.go +++ b/call/reload.go @@ -268,15 +268,6 @@ func CommonReload(c map[int][]func(*pb.ReloadGameConfig) error) { return nil }} } - if _, ok := c[common.ReloadConfigShare]; !ok { - c[common.ReloadConfigShare] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { - if err := LoadConfigShare(); err != nil { - log.Error("error : [%s]", err.Error()) - return err - } - return nil - }} - } if _, ok := c[common.ReloadConfigShareSys]; !ok { c[common.ReloadConfigShareSys] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { if err := LoadConfigShareSys(); err != nil { @@ -578,4 +569,58 @@ func CommonReload(c map[int][]func(*pb.ReloadGameConfig) error) { return nil }} } + if _, ok := c[common.ReloadConfigShareTaskNew]; !ok { + c[common.ReloadConfigShareTaskNew] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigShareTaskNew(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadConfigShare]; !ok { + c[common.ReloadConfigShare] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigShare(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadConfigShareLimitTask]; !ok { + c[common.ReloadConfigShareLimitTask] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigShareLimitTask(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadConfigShareWithdrawProducts]; !ok { + c[common.ReloadConfigShareWithdrawProducts] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigShareWithdrawProducts(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadConfigShareBanner]; !ok { + c[common.ReloadConfigShareBanner] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigShareBanner(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadTypeConfigWithdrawWeight]; !ok { + c[common.ReloadTypeConfigWithdrawWeight] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigWithdrawChannels(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } } diff --git a/call/share.go b/call/share.go index afb021c..cf05fce 100644 --- a/call/share.go +++ b/call/share.go @@ -7,6 +7,7 @@ import ( "server/db" "server/pb" "server/util" + "strings" "time" "github.com/liangdas/mqant/log" @@ -20,7 +21,7 @@ func GetShareInfo(uid int) *common.ShareInfo { info, _ := GetUserXInfo(uid, "channel_id") shareInfo.ChannelID = info.ChannelID shareInfo.Share = util.GetShareCode(uid) - shareInfo.Time = time.Now().Unix() + shareInfo.CreateTime = time.Now().Unix() db.Mysql().Create(shareInfo) } return shareInfo @@ -31,56 +32,78 @@ func GetShareInfoByCode(code string) *common.ShareInfo { return shareInfo } +func GetShareLink(cid, uid int) string { + shareInfo := GetShareInfo(uid) + channel := GetChannelByID(cid) + if channel == nil { + return "" + } + u := "" + if strings.Contains(channel.ShareURL, "?") { + u = channel.ShareURL + fmt.Sprintf("&shareCode=%s", shareInfo.Share) + } else { + u = channel.ShareURL + fmt.Sprintf("?shareCode=%s", shareInfo.Share) + } + if !strings.Contains(u, "app") { + u += fmt.Sprintf("&app=%d", common.GetShareChannel(cid)) + } + return u +} + // 分享查询 func ShareBind(share string, isOld bool, uid, cid int) { - // 绑定 + // 分享码为空 if share == "" { return } - activityId := 0 - now := time.Now().Unix() - // 关联活动分享码 - codeInfo := &common.ShareActivityCode{ShareCode: share} - upInfo := &common.ShareInfo{} - db.Mysql().Get(codeInfo) - if codeInfo.Id > 0 { - upInfo.UID = codeInfo.UID - activityId = codeInfo.ActivityId - // 判断是否过期 - if now < codeInfo.ExpireAt { - util.Go(func() { - SendShareReward(cid, codeInfo.UID, codeInfo.ActivityId) - }) - } + // 获取上一级分享信息 + upInfo := &common.ShareInfo{Share: share} + db.Mysql().Get(upInfo) + if upInfo.ID > 0 { + upInfo.UID = upInfo.UID + // todo ?发送奖励? + //util.Go(func() { + // SendShareReward(cid, codeInfo.UID, codeInfo.ActivityId) + //}) } else { // 一级 upInfo = &common.ShareInfo{Share: share} } - db.Mysql().Get(upInfo) if upInfo.ID <= 0 { return } - if !isOld { - shareInfo := &common.ShareInfo{UID: uid, UP1: upInfo.UID, UP2: upInfo.UP1, UP3: upInfo.UP2, Time: time.Now().Unix(), ChannelID: cid, Share: util.GetShareCode(uid), ActivityId: activityId} + if !isOld { // 新账号创建分享信息 + shareInfo := &common.ShareInfo{UID: uid, UP1: upInfo.UID, UP2: upInfo.UP1, UP3: upInfo.UP2, UP4: upInfo.UP3, UP5: upInfo.UP4, CreateTime: time.Now().Unix(), ChannelID: cid, Share: util.GetShareCode(uid)} db.Mysql().Create(shareInfo) - } else { + } else { // 已有账号直接走更新 err := db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{ "up1": upInfo.UID, "up2": upInfo.UP1, "up3": upInfo.UP2, + "up4": upInfo.UP3, + "up5": upInfo.UP4, }) if err != nil { log.Error("ShareBind err:%v", err) } } - // 更新上级邀请玩家数 - db.Mysql().Update(&common.ShareInfo{UID: upInfo.UID}, map[string]interface{}{"invites": gorm.Expr("invites + 1")}) + // 更新上级的下级数 + ref := reflect.ValueOf(upInfo).Elem() + for i := 1; i <= 4; i++ { + upUid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) + if uid == 0 { + break + } + field := fmt.Sprintf("down%d", i+1) + db.Mysql().Update(&common.ShareInfo{UID: upUid}, map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%s + 1", field))}) + } - // 完成邀请任务 + // todo 更新上级邀请玩家数量? CheckTask(Task{Uid: upInfo.UID, Value: 1, Types: []common.TaskType{common.TaskTypeInvite}}) // todo util.Go(func() { if upInfo.UID != 0 { + // pdd摇奖次数 err := db.Mysql().C().Model(&common.PddDataNew{}).Where("uid = ?", upInfo.UID). Updates(map[string]interface{}{ "spin": gorm.Expr("spin + ?", 1), @@ -89,6 +112,15 @@ func ShareBind(share string, isOld bool, uid, cid int) { log.Error("update spin err, %s", err.Error()) return } + // 裂变任务邀请人数 + err = db.Mysql().C().Model(&common.ShareTaskNewData{}).Where("uid = ? and `type` = 2 and `status` = 0", upInfo.UID). + Updates(map[string]interface{}{ + "progress": gorm.Expr("progress + ?", 1), + }).Error + if err != nil { + log.Error("update share invite task err, %s", err.Error()) + return + } } }) } @@ -146,25 +178,40 @@ func ShareRecharge(uid int, amount int64, typ int) { } ref := reflect.ValueOf(shareInfo).Elem() // 循环查询上级 - for i := 1; i <= 3; i++ { + for i := 1; i <= 5; i++ { upUid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) if upUid == 0 { break } - con := GetConfigShareByLevel(i) + tmpShareInfo := GetShareInfo(upUid) + con := GetConfigShareByLevel(tmpShareInfo.Level) if con == nil { log.Error("unknown config share level:%v", i) continue } + var per int64 + for _, v := range con.SubRewardTiers { + if v.Tier == i { + per = v.Per + } + } // 发奖 - reward := amount * con.Per / 1000 + reward := amount * per / 1000 if reward <= 0 { continue } db.Mysql().Update(&common.ShareInfo{UID: upUid}, map[string]interface{}{ - "bet_reward": gorm.Expr("bet_reward + ?", reward), - "available_reward": gorm.Expr("available_reward + ?", reward), + "withdrawable": gorm.Expr("withdrawable + ?", reward), }) + if i == 1 { // 上一级的充值任务 + err := db.Mysql().C().Model(&common.ShareTaskNewData{}).Where("uid = ? and `type` = ? and `status` = 0", + upUid, common.ShareTaskNewTypeRecharge).Updates(map[string]interface{}{ + "progress": gorm.Expr("progress + ?", amount), + }).Error + if err != nil { + log.Error("update share recharge task err, %s", err.Error()) + } + } db.Mysql().Create(&common.ShareDetail{ UID: uid, Type: typ, @@ -178,35 +225,44 @@ func ShareRecharge(uid int, amount int64, typ int) { // 投注奖励结算 func ShareSettle(d *pb.InnerAfterSettle) { - shareInfo := &common.ShareInfo{UID: int(d.UID)} - db.Mysql().Get(shareInfo) - if shareInfo.UP1 == 0 { - return - } - db.Mysql().Update(&common.ShareInfo{UID: int(d.UID)}, map[string]interface{}{"bet": gorm.Expr("bet + ?", d.TotalBet)}) + //shareInfo := &common.ShareInfo{UID: int(d.UID)} + //db.Mysql().Get(shareInfo) + //if shareInfo.UP1 == 0 { + // return + //} + //db.Mysql().Update(&common.ShareInfo{UID: int(d.UID)}, map[string]interface{}{"bet": gorm.Expr("bet + ?", d.TotalBet)}) + // + //ref := reflect.ValueOf(shareInfo).Elem() + //// 循环查询上级 + //for i := 1; i <= 3; i++ { + // uid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) + // if uid == 0 { + // break + // } + // con := GetConfigShareByLevel(i) + // if con == nil { + // log.Error("unknown config share level:%v", i) + // continue + // } + // // 发奖 + // reward := d.TotalBet * con.Per / 1000 + // if reward <= 0 { + // continue + // } + // db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{ + // "bet_reward": gorm.Expr("bet_reward + ?", reward), + // "available_reward": gorm.Expr("available_reward + ?", reward), + // }) + //} +} - ref := reflect.ValueOf(shareInfo).Elem() - // 循环查询上级 - for i := 1; i <= 3; i++ { - uid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) - if uid == 0 { - break +func GetConfigShareByLevel(level int) (result *common.ConfigShare) { + for _, v := range configShare { + if v.Level == level { + return v } - con := GetConfigShareByLevel(i) - if con == nil { - log.Error("unknown config share level:%v", i) - continue - } - // 发奖 - reward := d.TotalBet * con.Per / 1000 - if reward <= 0 { - continue - } - db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{ - "bet_reward": gorm.Expr("bet_reward + ?", reward), - "available_reward": gorm.Expr("available_reward + ?", reward), - }) } + return } func PackLevelSql(uid, level int) (sql string) { @@ -365,3 +421,174 @@ func SendShareReward(channel, uid, actId int) { } } } + +// WriteShareBalance 写入分享流水 +func WriteShareBalance(b *common.ESShareBalance, shouldUpdate bool) { + if b.Amount == 0 { + return + } + now := time.Now() + if (b.FriendNick == "" || b.Phone == "") && b.FriendUID > 0 { + ret, _ := GetUserXInfo(b.FriendUID, "nick", "mobile") + b.FriendNick = ret.Nick + b.Phone = ret.Mobile + } + if b.RefererNick == "" { + ret, _ := GetUserXInfo(b.RefererUID, "nick") + b.RefererNick = ret.Nick + } + if b.Date == "" { + b.Date = now.Format("20060102") + } + if b.Time == 0 { + b.Time = now.Unix() + } + InsertToESGO(common.ESIndexShareBalance, b) + + if !shouldUpdate { + return + } + + // 先更新总收益 + total := &common.ShareRewardData{} + // totalSql := fmt.Sprintf("select * from share_reward_data where uid = %d and time = 0", b.RefererUID) + db.Mysql().QueryBySql(fmt.Sprintf("select * from share_reward_data where uid = %d and time = 0", b.RefererUID), total) + if total.ID == 0 { + total = &common.ShareRewardData{} + total.UID = b.RefererUID + total.Date = "" + total.Time = 0 + total.SetReward(b.Event, b.Amount) + db.Mysql().Create(total) + } else { + field := total.GetRewardName(b.Event) + if field != "" { + db.Mysql().UpdateW(&common.ShareRewardData{}, + map[string]interface{}{ + "total_reward": gorm.Expr("total_reward + ?", b.Amount), + field: gorm.Expr(fmt.Sprintf("%s + %d", field, b.Amount))}, + fmt.Sprintf("uid = %d and time = 0", b.RefererUID)) + } + } + // 更新当天收益 + t := util.GetZeroTime(now).Unix() + today := &common.ShareRewardData{UID: b.RefererUID, Time: t} + db.Mysql().Get(today) + if today.ID == 0 { + today = &common.ShareRewardData{UID: b.RefererUID, Time: t} + today.Date = b.Date + today.SetReward(b.Event, b.Amount) + db.Mysql().Create(today) + } else { + field := today.GetRewardName(b.Event) + if field != "" { + db.Mysql().Update(&common.ShareRewardData{UID: b.RefererUID, Time: t}, + map[string]interface{}{ + "total_reward": gorm.Expr("total_reward + ?", b.Amount), + field: gorm.Expr(fmt.Sprintf("%s + %d", field, b.Amount))}) + } + } + + // 更新分享者总奖励表 + // one := &common.ShareTotalReward{RefererUID: b.RefererUID, FriendUID: b.FriendUID, Level: b.Level, Reward: b.Amount} + // if !db.Mysql().Exist(one) { + // one.Reward = b.Amount + // db.Mysql().Create(one) + // return + // } + // db.Mysql().Update(one, map[string]interface{}{"reward": gorm.Expr("reward + ?", b, b.Amount)}) + // db.Mysql().UpsertMap(fmt.Sprintf("referer_uid = %v and friend_uid = %v", b.RefererUID, b.FriendUID), + // one, map[string]interface{}{"reward": gorm.Expr("reward + ?", b.Amount)}) +} + +// 计算排行榜 +func CalShareRank(t int, ti int64) (list []*common.ShareRank) { + data := []*OneRank{} + switch t { + case common.ShareRankTypeDaily: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,total_reward as Reward from share_reward_data where time = %d ORDER BY Reward desc LIMIT %d", + ti, common.ShareRankMaxNum), &data) + case common.ShareRankTypeWeekly: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d group by uid ORDER BY Reward desc LIMIT %d", + ti, ti+7*common.OneDay, common.ShareRankMaxNum), &data) + case common.ShareRankTypeMonthly: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d group by uid ORDER BY Reward desc LIMIT %d", + ti, util.GetLastDateOfMonth(time.Unix(ti, 0)).Unix()+common.OneDay, common.ShareRankMaxNum), &data) + } + for _, v := range data { + one := &common.ShareRank{ + UID: v.UID, + Type: t, + Time: ti, + Level: GetShareInfo(v.UID).Level, + Reward: v.Reward, + } + p, _ := GetUserXInfo(v.UID, "avatar", "nick") + one.Avatar = p.Avatar + one.Nick = p.Nick + list = append(list, one) + } + return +} + +func GetShareRank(t int, ti int64) (list []*common.ShareRank) { + now := time.Now() + switch t { + case common.ShareRankTypeDaily: + if util.GetZeroTime(now).Unix() == ti { // 查询今天 + list = CalShareRank(t, ti) + return + } + case common.ShareRankTypeWeekly: + if util.GetWeekZeroTime(now).Unix() == ti { // 查询本周 + list = CalShareRank(t, ti) + return + } + case common.ShareRankTypeMonthly: + if util.GetFirstDateOfMonth(now).Unix() == ti { // 查询本月 + list = CalShareRank(t, ti) + return + } + } + db.Mysql().QueryList(0, common.ShareRankMaxNum, fmt.Sprintf("type = %d and time = %d", t, ti), "reward desc", &common.ShareRank{}, &list) + return +} + +type OneRank struct { + UID int + Reward int64 +} + +func GetShareRewardData(uid, t int, ti int64) *common.ShareRank { + data := &OneRank{} + switch t { + case common.ShareRankTypeDaily: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,total_reward as Reward from share_reward_data where time = %d AND uid = %d", + ti, uid), &data) + case common.ShareRankTypeWeekly: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d AND uid = %d", + ti, ti+7*common.OneWeek, uid), data) + case common.ShareRankTypeMonthly: + db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d AND uid = %d", + ti, util.GetLastDateOfMonth(time.Unix(ti, 0)).Unix()+common.OneDay, uid), &data) + } + + one := &common.ShareRank{ + UID: uid, + Type: t, + Time: ti, + Level: GetShareInfo(uid).Level, + Reward: data.Reward, + } + p, _ := GetUserXInfo(uid, "avatar", "nick") + one.Avatar = p.Avatar + one.Nick = p.Nick + return one +} + +func GetShareWithdrawHis(uid, page, num int) (list []*common.RechargeOrder, count int64) { + count, _ = db.Mysql().QueryListW(page, num, "created_at desc", + &common.RechargeOrder{UID: uid}, &list, "uid = ? and (event = ? or event = ?) and scene = ?", + uid, common.CurrencyEventWithDraw, common.CurrencyEventShareWithdraw, common.ActivityIDShare) + return +} diff --git a/call/task.go b/call/task.go index 55ee6ad..3143a5c 100644 --- a/call/task.go +++ b/call/task.go @@ -16,6 +16,10 @@ type Task struct { } func CheckTask(task Task) (taskId int) { + /* + todo 检查(根据场景进来获取查询任务更新进度) + */ + return log.Info("checkTask task:%v", task) now := time.Now().Unix() con := GetConfigTask() diff --git a/common/activity.go b/common/activity.go index 1d3d2a1..927f2ba 100644 --- a/common/activity.go +++ b/common/activity.go @@ -24,7 +24,7 @@ const ( ActivityIDSuper // 超级1+2 ActivityIDBetDraw // 下注抽奖活动 ActivityIDInviteRank // 邀请排行榜 - + ActivityIDShare // 分享裂变 ) const ( diff --git a/common/config.go b/common/config.go index 3889bb1..5a29be6 100644 --- a/common/config.go +++ b/common/config.go @@ -67,6 +67,11 @@ const ( ReloadConfigPdd ReloadConfigLuckyCodeList ReloadConfigLuckyWheel + ReloadConfigShareTaskNew + ReloadConfigShareLimitTask + ReloadConfigShareWithdrawProducts + ReloadConfigShareBanner + ReloadTypeConfigWithdrawWeight ) // GetConfigStructByType 获取相应配置的结构 @@ -112,8 +117,6 @@ func GetConfigStructByType(t int) (interface{}, interface{}) { return &ConfigRobot{}, &[]ConfigRobot{} case ReloadConfigAppSpin: return &ConfigAppSpin{}, &[]ConfigAppSpin{} - case ReloadConfigShare: - return &ConfigShare{}, &[]ConfigShare{} case ReloadConfigShareSys: return &ConfigShareSys{}, &[]ConfigShareSys{} case ReloadConfigActivityPddSpin: @@ -182,7 +185,18 @@ func GetConfigStructByType(t int) (interface{}, interface{}) { return &ConfigPdd{}, &[]ConfigPdd{} case ReloadConfigLuckyWheel: return &ConfigLuckyWheel{}, &[]ConfigLuckyWheel{} - + case ReloadConfigShareTaskNew: + return &ConfigShareTaskNew{}, &[]ConfigShareTaskNew{} + case ReloadConfigShare: + return &ConfigShare{}, &[]ConfigShare{} + case ReloadConfigShareLimitTask: + return &ConfigShareLimitTask{}, &[]ConfigShareLimitTask{} + case ReloadConfigShareWithdrawProducts: + return &ConfigShareWithdrawProducts{}, &[]ConfigShareWithdrawProducts{} + case ReloadConfigShareBanner: + return &ConfigShareBanner{}, &[]ConfigShareBanner{} + case ReloadTypeConfigWithdrawWeight: + return &ConfigWithdrawChannels{}, &[]ConfigWithdrawChannels{} default: return nil, nil } @@ -412,14 +426,14 @@ func (c *ConfigBroadcast) TableName() string { type ConfigNotice struct { ID int `gorm:"primarykey"` - Title1 string `gorm:"column:title1;type:varchar(255);comment:标题1" web:"title1"` // 公告标题_1(英语) - Content1 string `gorm:"column:content1;type:varchar(255);comment:正文1" web:"content1"` // 公告内容_1(英语) - Title2 string `gorm:"column:title2;type:varchar(255);comment:标题2" web:"title2"` // 公告标题_2 - Content2 string `gorm:"column:content2;type:varchar(255);comment:正文2" web:"content2"` // 公告内容_2 + Title1 string `gorm:"column:title1;type:varchar(255);comment:标题1" web:"title1"` // 公告标题_1(英语) + Content1 string `gorm:"column:content1;type:varchar(255);comment:正文1" web:"content1"` // 公告内容_1(英语) + Title2 string `gorm:"column:title2;type:varchar(255);comment:标题2" web:"title2"` // 公告标题_2 + Content2 string `gorm:"column:content2;type:varchar(255);comment:正文2" web:"content2"` // 公告内容_2 Type int `gorm:"column:type;type:int(11);comment:公告类型 (1.紧急 2.常规)" web:"type"` // 公告类型 (1.紧急 2.常规) - Open int `gorm:"column:open;type:int(11);comment:是否打开 1打开" web:"open"` // 是否发布 - Method int `gorm:"column:method;type:int(11);comment:发布方式" web:"method"` // 发布方式 - Time int64 `gorm:"column:time;type:int(11);comment:发布时间" web:"time"` // 发布时间 + Open int `gorm:"column:open;type:int(11);comment:是否打开 1打开" web:"open"` // 是否发布 + Method int `gorm:"column:method;type:int(11);comment:发布方式" web:"method"` // 发布方式 + Time int64 `gorm:"column:time;type:int(11);comment:发布时间" web:"time"` // 发布时间 Interval int `gorm:"column:interval;type:int(11);comment:间隔" web:"interval"` PushTimes int `gorm:"column:push_times;type:int(11);comment:推送次数" web:"push_times"` // 推送次数 } @@ -518,7 +532,7 @@ type ConfigTgRobot struct { Type int `gorm:"column:type;type:int(11);default:0;comment:机器人类型" web:"type"` ChannelName string `gorm:"column:channel_name;type:varchar(255);comment:频道名称" web:"channel_name"` // 频道id ChannelType string `gorm:"column:channel_type;type:varchar(255);comment:频道类型" web:"channel_type"` // 频道类型 vip 普通 - Content string `gorm:"column:content;type:text;comment:内容" web:"content"` // 内容 + Content string `gorm:"column:content;type:text;comment:内容" web:"content"` // 内容 ContentType string `gorm:"column:content_type;type:varchar(255);comment:发送类型" web:"content_type"` // 发送类型 Image string `gorm:"column:image;type:longtext;comment:发送类型" web:"image"` // 图片 Time string `gorm:"column:time;type:varchar(255);comment:发送类型" web:"time"` // 时间 @@ -762,3 +776,9 @@ type ConfigProviderGameList struct { func (c *ConfigProviderGameList) TableName() string { return "config_provider_game_list" } + +const ( + WithdrawSorceBank = iota + 1 + WithdrawSorceBlock + WithdrawSorceShare // 分享 +) diff --git a/common/es.go b/common/es.go index 2432192..c0199ef 100644 --- a/common/es.go +++ b/common/es.go @@ -8,6 +8,8 @@ const ( ESIndexGameData = "game_data" // 玩家游戏记录 ESIndexShareProfitReport = "share_profit_report" // 分享者每日收益汇总 ESIndexShareProfitRecord = "share_profit_record" // 分享者所有推荐人贡献的每日收益详情 + ESIndexShareBalance = "share_balance" // 分享流水 + ESIndexBackPanic = "back_panic" // 崩溃日志 ) // backend @@ -337,3 +339,11 @@ type ESActivityBetDraw struct { Reward int64 Type int // 转盘类型 } + +// ESPanic 崩溃记录 +type ESPanic struct { + Module string + Func string + Error string + Time int64 +} diff --git a/common/platform.go b/common/platform.go index 2cb932c..ccc3b61 100644 --- a/common/platform.go +++ b/common/platform.go @@ -7,6 +7,12 @@ import ( "strings" ) +const ( + OneDay = 86400 + OneWeek = 604800 + OneMonth = 2592000 +) + // 平台登录方式 const ( AccountTypeGuest = iota @@ -49,8 +55,7 @@ const ( ) var ( - DecimalCounts = 0 - OneDay int64 = 24 * 60 * 60 // 一天的秒数 + DecimalCounts = 0 ) func init() { @@ -202,7 +207,7 @@ type Channel struct { FBAccessToken string `gorm:"column:fb_accesstoken;type:varchar(256);not null;comment:fb验证码" json:"fb_accesstoken"` UP int `gorm:"column:up;type:int(11);default:0;comment:上级渠道" json:"up"` ADUpload int `gorm:"column:ad_upload;type:int(11);default:0;comment:上报事件的平台" json:"ad_upload"` - ShareUrl string `gorm:"column:share_url;type:varchar(256);comment:分享地址;NOT NULL" json:"share_url"` + ShareURL string `gorm:"column:share_url;type:varchar(256);not null;default:'https://d.slotgolden777.com/s/s.html';comment:分享地址" json:"share_url"` } func (c *Channel) TableName() string { @@ -372,3 +377,10 @@ type BlackList struct { func (c *BlackList) TableName() string { return "black_list" } + +func GetShareChannel(cid int) int { + if cid > 10000 { + return cid + } + return cid + 10000 +} diff --git a/common/player.go b/common/player.go index 8120620..45a941c 100644 --- a/common/player.go +++ b/common/player.go @@ -39,6 +39,7 @@ type PlayerDBInfo struct { AccountName string `gorm:"column:account_name;default:null;uniqueIndex:channel_account_name;commont:账户名" json:"account_name" redis:"account_name"` GateID string `gorm:"-" json:"gateID" redis:"gateID"` Token string `gorm:"-" json:"token" redis:"token"` + IsOldDevice int `gorm:"column:isOldDevice;type:tinyint(4);default:0;comment:是否是老设备" json:"isOldDevice" redis:"isOldDevice"` Birth int64 `gorm:"column:birth;type:bigint(20);default:0;comment:账号创建时间,时间戳" json:"birth" redis:"birth"` Role int `gorm:"column:role;type:smallint(8);default:0;comment:玩家角色0普通玩家,100机器人" json:"role" redis:"role"` ChannelID int `gorm:"column:channel_id;type:bigint(20);uniqueIndex:channel_openid;uniqueIndex:channel_mobile;uniqueIndex:channel_account_name;default:1;comment:渠道id" json:"channel_id" redis:"channel_id"` diff --git a/common/recharge.go b/common/recharge.go index 7bdd3dd..1ef262a 100644 --- a/common/recharge.go +++ b/common/recharge.go @@ -1,11 +1,14 @@ package common +import "gorm.io/gorm" + const ( StatusROrderWaitting = iota // 等待提交状态 StatusROrderCreate StatusROrderPay StatusROrderFinish StatusROrderFail + StatusROrderCancel StatusROrderRefuse StatusROrderPending // 挂起 StatusROrderAll @@ -117,6 +120,7 @@ func AddProductPayCount(total int64, id int) int64 { } type RechargeOrder struct { + gorm.Model ID uint `gorm:"primarykey"` UID int `gorm:"column:uid;not null;type:int(11);index:uid"` CreateTime int64 `gorm:"column:create_time;type:bigint(20);comment:创建时间" redis:"create_time"` @@ -138,6 +142,8 @@ type RechargeOrder struct { UPI int `gorm:"column:upi;not null;type:int(11);comment:玩家选择的upi"` Bonus int64 `gorm:"column:bonus;type:bigint(20);default:0;comment:选择了bonus后赠送的数额"` Times int `gorm:"column:times;not null;type:int(11);comment:额度购买次数"` + Scene int `gorm:"column:scene;type:int(11);default:0;comment:支付场景"` + WithdrawCash int64 `gorm:"column:withdraw_cash;type:bigint(20);default:0;comment:提现扣除的金币" json:"withdraw_cash" redis:"withdraw_cash"` } func (r *RechargeOrder) TableName() string { @@ -151,6 +157,13 @@ const ( WithdrawOrderTypeAll ) +// 支付类型 +const ( + WithdrawTypeWallet = "3" + WithdrawTypeUPI = "4" + WithdrawTypeBank = "7" +) + type WithdrawOrder struct { ID uint `gorm:"primarykey"` UID int `gorm:"column:uid;not null;type:int(11)"` diff --git a/common/share.go b/common/share.go index 8a61873..43ebaec 100644 --- a/common/share.go +++ b/common/share.go @@ -1,16 +1,9 @@ package common -// 分享配置 -type ConfigShare struct { - ID int `gorm:"primarykey"` - Level int `gorm:"column:level;type:int(11);default:0;comment:等级" web:"level"` - Bet int64 `gorm:"column:bet;type:bigint(20);default:0;comment:档次投注额" web:"bet"` - Per int64 `gorm:"column:per;type:bigint(20);default:0;comment:佣金比例,万分位" web:"per"` -} - -func (c *ConfigShare) TableName() string { - return "config_share" -} +import ( + "fmt" + "time" +) // 分享配置 type ConfigShareSys struct { @@ -28,23 +21,34 @@ func (c *ConfigShareSys) TableName() string { // 绑定关系 type ShareInfo struct { - ID int `gorm:"primarykey"` - UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"` - Share string `gorm:"column:share;not null;type:varchar(64);uniqueIndex:share;comment:分享码"` - // UP int `gorm:"column:up;not null;type:int(11);comment:上级"` - UP1 int `gorm:"column:up1;type:int(11);default:0;comment:一级"` - UP2 int `gorm:"column:up2;type:int(11);default:0;comment:二级"` - UP3 int `gorm:"column:up3;type:int(11);default:0;comment:三级"` - ChannelID int `gorm:"column:channel_id;type:int(11);default:0;comment:渠道id"` - Invites int `gorm:"column:invites;type:int(11);default:0;comment:邀请人数"` - InvaidInvites int `gorm:"column:invalid_invites;type:int(11);default:0;comment:有效邀请人数"` - InviteReward int64 `gorm:"column:invite_reward;type:bigint(20);default:0;comment:邀请获得的奖励金额"` - BetReward int64 `gorm:"column:bet_reward;type:bigint(20);default:0;comment:邀请人下注获得的金额"` - AvailableReward int64 `gorm:"column:available_reward;type:bigint(20);default:0;comment:可支配佣金"` - Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:加入的时间"` - ActivityId int `gorm:"column:activity_id;type:int(11);default:0;comment:来自于哪个分享活动"` - RechargeAmount int64 `gorm:"column:recharge_amount;type:bigint(20);default:0;comment:充值金额"` - BetAmount int64 `gorm:"column:bet_amount;type:bigint(20);default:0;comment:下注金额"` + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"` + CreateTime int64 `gorm:"column:create_time;type:bigint(20);index:ct;default:0;comment:创建时间"` + Exp int64 `gorm:"column:exp;default:0;type:int(11);comment:当前经验值"` + Level int `gorm:"column:level;default:1;type:int(11);comment:等级"` + LastLevel int `gorm:"column:last_level;default:1;type:int(11);comment:上次查看时的等级"` + Share string `gorm:"column:share;not null;type:varchar(64);uniqueIndex:share;comment:分享码"` + UP1 int `gorm:"column:up1;type:int(11);default:0;comment:上1级"` + UP2 int `gorm:"column:up2;type:int(11);default:0;comment:上2级"` + UP3 int `gorm:"column:up3;type:int(11);default:0;comment:上3级"` + UP4 int `gorm:"column:up4;default:0;type:int(11);comment:上4级"` + UP5 int `gorm:"column:up5;default:0;type:int(11);comment:上5级"` + Reward int64 `gorm:"column:reward;default:0;type:bigint(20);comment:总奖励"` + Withdrawable int64 `gorm:"column:withdrawable;default:0;type:bigint(20);comment:可退出奖励"` + UpInviteReward int64 `gorm:"column:up_invite_reward;default:0;type:int(11);comment:为上级创造的邀请奖励"` + UpInviteUnlock int64 `gorm:"column:up_invite_Unlock;default:0;type:int(11);comment:为上级已解锁的邀请奖励"` + Down1 int64 `gorm:"column:down1;default:0;type:int(11);comment:下1级数量"` + Down2 int64 `gorm:"column:down2;default:0;type:int(11);comment:下2级数量"` + Down3 int64 `gorm:"column:down3;default:0;type:int(11);comment:下3级数量"` + Down4 int64 `gorm:"column:down4;default:0;type:int(11);comment:下4级数量"` + Down5 int64 `gorm:"column:down5;default:0;type:int(11);comment:下5级数量"` + CalLoseValue int64 `gorm:"column:cal_lose_value;default:0;type:bigint(20);comment:用于计算客损的额度"` + PopWithdraw int `gorm:"pop_withdraw;default:0;type:tinyint(4);comment:是否弹出过退出"` + + ChannelID int `gorm:"column:channel_id;type:int(11);default:0;comment:渠道id"` + BetReward int64 `gorm:"column:bet_reward;type:bigint(20);default:0;comment:邀请人下注获得的金额"` + RechargeAmount int64 `gorm:"column:recharge_amount;type:bigint(20);default:0;comment:充值金额"` + BetAmount int64 `gorm:"column:bet_amount;type:bigint(20);default:0;comment:下注金额"` } func (a *ShareInfo) TableName() string { @@ -165,3 +169,331 @@ type ConfigShareRankRule struct { func (c *ConfigShareRankRule) TableName() string { return "config_share_rank_rule" } + +const ( + ShareEvent = iota + // ShareEventDaily // 每日活动 + ShareEventInvitation // 邀请奖励 + ShareEventRecharge // 充值返利 + ShareEventAffiliate // 客损返利 + ShareEventOther // 活动、签到等归此类 + // ShareEventBet // 下注返回 +) + +// ConfigShareTaskNew 分享新手任务 +type ConfigShareTaskNew struct { + ID int `gorm:"primarykey"` + TaskID int `gorm:"column:task_id;type:int(11);default:1;uniqueIndex:task_id;comment:任务编号" web:"task_id"` + Type int `gorm:"column:type;type:int(11);default:1;comment:任务类型" web:"type"` + Condition int `gorm:"column:condition;type:int(11);default:0;comment:任务条件,玩牌对应游戏id" web:"condition"` + Target int64 `gorm:"column:target;type:int(11);default:1;comment:任务目标" web:"target"` + Reward int64 `gorm:"column:reward;type:int(11);default:0;comment:任务奖励" web:"reward"` +} + +func (c *ConfigShareTaskNew) TableName() string { + return "config_share_task_new" +} + +const ( + ShareTaskNewTypeZero = iota + ShareTaskNewTypeFirst // 首次任务 + ShareTaskNewTypeInvite // 邀请注册任务 + ShareTaskNewTypeRecharge // 邀请下级用户充值任务 + ShareTaskNewTypeAll +) + +type ShareTaskNewData struct { + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:ut"` + TaskID int `gorm:"column:task_id;type:int(11);default:1;uniqueIndex:ut;comment:当前任务id"` + Type int `gorm:"column:type;type:int(11);default:1;comment:任务类型"` + Condition int `gorm:"column:condition;type:int(11);default:0;comment:任务条件,玩牌对应游戏id"` + Progress int64 `gorm:"column:progress;type:int(11);default:0;comment:任务进度"` + Target int64 `gorm:"column:target;type:int(11);default:1;comment:任务目标"` + Reward int64 `gorm:"column:reward;type:int(11);default:0;comment:任务奖励"` + Status int `gorm:"column:status;type:int(11);default:0;comment:状态 0未领取 1已领取"` +} + +func (c *ShareTaskNewData) TableName() string { + return "share_task_new_data" +} + +func (c *ShareTaskNewData) GetDesc() string { + switch c.Type { + case ShareTaskNewTypeFirst: + return "First Check in" + case ShareTaskNewTypeInvite: + str := fmt.Sprintf("Successfully invited %d player", c.Target) + if c.Target > 1 { + str += "s" + } + return str + case ShareTaskNewTypeRecharge: + str := fmt.Sprintf("Recharge for %d invited player", c.Target) + if c.Target > 1 { + str += "s" + } + return str + default: + return "" + } +} + +type ConfigShareReward struct { + CanWithdraw bool + Amount int64 // 奖励金额 + ConditionAmount int64 // 转化条件金额 +} + +type ConfigShareTiers struct { + Tier int // 层级 + Per int64 // 分成比例 +} + +// 分享配置 +type ConfigShare struct { + ID int `gorm:"primarykey"` + PN int `gorm:"column:pn;type:int(11);default:0;comment:包类别" web:"pn"` + Channel int `gorm:"column:channel;type:int(11);default:0;comment:渠道" web:"channel"` + Level int `gorm:"column:level;type:int(11);default:1;comment:代理等级" web:"level"` + Exp int64 `gorm:"column:exp;type:int(11);default:1;comment:升到本级所需总充值" web:"exp"` + InviteReward string `gorm:"column:invite_reward;type:varchar(256);default:'';comment:拉新奖励配置" web:"invite_reward"` + SubInviteReward ConfigShareReward `gorm:"-"` + NewReward string `gorm:"column:new_reward;type:varchar(256);default:'';comment:新手奖励配置" web:"new_reward"` + SubNewReward ConfigShareReward `gorm:"-"` + RechargeReward int64 `gorm:"column:recharge_reward;type:int(11);default:10;comment:充值返利比例" web:"recharge_reward"` + AffiliateReward int64 `gorm:"column:affiliate_reward;type:int(11);default:0;comment:客损返利比例" web:"affiliate_reward"` + RewardTiers string `gorm:"column:reward_tiers;type:varchar(256);default:'[]';comment:返利层级配置" web:"reward_tiers"` + SubRewardTiers []ConfigShareTiers `gorm:"-"` + DayWithdrawCount int `gorm:"column:day_withdraw_count;type:int(11);default:3;comment:日退出次数" web:"day_withdraw_count"` + Open int `gorm:"column:open;type:int(11);default:0;comment:是否打开 1打开" web:"open"` + AffiliateDiscount int64 `gorm:"column:affiliate_discount;type:int(11);default:0;comment:客损折扣比例" web:"affiliate_discount"` + WithdrawAudit int64 `gorm:"column:withdraw_audit;type:int(11);default:50000;comment:退出审核金额" web:"withdraw_audit"` +} + +func (c *ConfigShare) TableName() string { + return "config_share" +} + +func (c *ConfigShare) CalReward(event int, amount int64) int64 { + switch event { + case ShareEventInvitation: + return c.SubInviteReward.Amount + case ShareEventRecharge: + return amount * c.RechargeReward / 100 + case ShareEventAffiliate: + return amount * c.AffiliateDiscount * c.AffiliateReward / 10000 + default: + return 0 + } +} + +func (c *ConfigShare) GetLevelUpInfo() LevelUpInfo { + info := LevelUpInfo{} + info.Level = c.Level + info.Invitation = fmt.Sprintf("%drs/person", c.SubInviteReward.Amount/100) + info.RechargeCommission = fmt.Sprintf("%d", c.RechargeReward+c.AffiliateReward) + "%" + tmp := "" + for i, v := range c.SubRewardTiers { + this := "" + switch v.Tier { + case 1: + this = "A" + case 2: + this = "B" + case 3: + this = "C" + case 4: + this = "D" + case 5: + this = "E" + } + tmp += this + if i != len(c.SubRewardTiers)-1 { + tmp += "+" + } + } + info.CommissionFromAffiliate = fmt.Sprintf("Lv%d(%s)", info.Level, tmp) + return info +} + +type LevelUpInfo struct { + Level int + Invitation string + RechargeCommission string + CommissionFromAffiliate string +} + +const ( + ShareAffiliatePer = 80 // 客损计算比例 + ShareRankMaxNum = 100 // 排行榜最大个数 +) + +const ( + ShareRankTypeDaily = iota + ShareRankTypeWeekly + ShareRankTypeMonthly +) + +// 分享排行榜 +type ShareRank struct { + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:ut"` + Type int `gorm:"column:type;type:int(11);default:0;uniqueIndex:ut;comment:类型 0日榜 1周榜 2月榜"` + Time int64 `gorm:"column:time;type:bigint(20);default:0;uniqueIndex:ut;comment:创建时间"` + Avatar string `gorm:"column:avatar;type:varchar(256);default:''"` + Nick string `gorm:"column:nick;type:varchar(256);default:''"` + Level int `gorm:"column:level;type:int(11);default:0;comment:等级"` + Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励"` + Rank int `gorm:"-"` +} + +func (c *ShareRank) TableName() string { + return "share_rank" +} + +type ConfigShareLimitTask struct { + ID int `gorm:"primarykey"` + PN int `gorm:"column:pn;type:int(11);default:0;comment:包类别" web:"pn"` + Channel int `gorm:"column:channel;type:int(11);default:0;comment:渠道" web:"channel"` + Level int `gorm:"column:level;type:int(11);default:0;comment:等级" web:"level"` + Time int64 `gorm:"column:time;type:int(11);default:4320;comment:完成时限,单位分钟" web:"time"` + Reward int64 `gorm:"column:reward;type:int(11);default:0;comment:任务奖励" web:"reward"` +} + +func (c *ConfigShareLimitTask) TableName() string { + return "config_share_limit_task" +} + +type ShareLimitTaskData struct { + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:ul"` + Level int `gorm:"column:level;type:int(11);default:1;uniqueIndex:ul;comment:当前任务等级"` + CreateTime int64 `gorm:"column:create_time;type:bigint(20);default:0;comment:创建时间"` + Time int64 `gorm:"column:time;type:int(11);default:4320;comment:完成时限,单位分钟"` + Reward int64 `gorm:"column:reward;type:int(11);default:0;comment:任务奖励"` + Status int `gorm:"column:status;type:int(11);default:0;comment:状态 0未领取 1已领取"` +} + +func (c *ShareLimitTaskData) TableName() string { + return "share_limit_task_data" +} + +func (c *ShareLimitTaskData) IsValid() bool { + if c.ID == 0 { + return false + } + return c.Status == 0 && c.CreateTime+c.Time*60-time.Now().Unix() > 0 +} + +type ShareWithdrawInfo struct { + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"` + DayCount int `gorm:"column:day_count;type:int(11);default:0;comment:日退出次数"` + DayTime int64 `gorm:"column:day_time;type:bigint(20);default:0;comment:日退出时间标记"` + Record string `gorm:"column:record;type:varchar(256);default:'';comment:已退出金额标记"` + TotalWithdraw int64 `gorm:"column:total_withdraw;type:int(11);default:0;comment:已退出总数"` + SubRecord map[int64]int `gorm:"-"` +} + +func (c *ShareWithdrawInfo) TableName() string { + return "share_withdraw_info" +} + +// 退出商品配置 +type ConfigShareWithdrawProducts struct { + ID int `gorm:"primarykey"` + PN int `gorm:"column:pn;type:int(11);default:0;comment:包类别" web:"pn"` + Channel int `gorm:"column:channel;type:int(11);default:0;comment:渠道" web:"channel"` + ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"` + Amount int64 `gorm:"column:amount;type:int(11);default:0;comment:金额" web:"amount"` + Count int `gorm:"column:count;type:int(11);default:0;comment:可使用次数,-1为不限制" web:"count"` +} + +func (c *ConfigShareWithdrawProducts) TableName() string { + return "config_share_withdraw_products" +} + +type ConfigShareBanner struct { + ID int `gorm:"primarykey"` + PN int `gorm:"column:pn;type:int(11);default:0;comment:包类别" web:"pn"` + Channel int `gorm:"column:channel;type:int(11);default:0;comment:渠道" web:"channel"` + Sort int `gorm:"column:sort;type:int(11);default:1;comment:排序" web:"sort"` + URL string `gorm:"column:url;type:varchar(256);default:'';comment:图片地址" web:"url"` +} + +func (c *ConfigShareBanner) TableName() string { + return "config_share_banner" +} + +type ShareRewardData struct { + ID int `gorm:"primarykey"` + UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:ut"` + Time int64 `gorm:"column:time;type:bigint(20);default:0;uniqueIndex:ut;comment:创建时间"` + Date string `gorm:"column:date;type:varchar(256);default:''"` + PopTime int64 `gorm:"column:pop_time;type:bigint(20);default:0;comment:弹出时间"` + TotalReward int64 `gorm:"column:total_reward;type:int(11);default:0;comment:总奖励"` + InviteReward int64 `gorm:"column:invite_reward;type:int(11);default:0;comment:邀请奖励"` + RechargeReward int64 `gorm:"column:recharge_reward;type:int(11);default:0;comment:充值返利"` + AffiliateReward int64 `gorm:"column:affiliate_reward;type:int(11);default:0;comment:下级返利"` + OtherReward int64 `gorm:"column:other_reward;type:int(11);default:0;comment:活动、签到等"` +} + +func (c *ShareRewardData) TableName() string { + return "share_reward_data" +} + +func (c *ShareRewardData) SetReward(shareEvent int, reward int64) { + switch shareEvent { + case ShareEventInvitation: + c.InviteReward += reward + case ShareEventRecharge: + c.RechargeReward += reward + case ShareEventAffiliate: + c.AffiliateReward += reward + case ShareEventOther: + c.OtherReward += reward + } + c.TotalReward += reward +} + +func (c *ShareRewardData) GetRewardName(shareEvent int) string { + switch shareEvent { + case ShareEventInvitation: + return "invite_reward" + case ShareEventRecharge: + return "recharge_reward" + case ShareEventAffiliate: + return "affiliate_reward" + case ShareEventOther: + return "other_reward" + default: + return "" + } +} + +// ESShareBalance 分享流水 +// Time 时间戳 +// Event 事件 +// FriendUID 奖励来源玩家uid +// FriendNick 奖励来源玩家nick +// Phone 奖励来源玩家手机号 +// AmountType 奖励类型 +// Amount 数量 +// RefererUID 分享者UID +// RefererNick 分享者昵称 +// Level 分享等级 +type ESShareBalance struct { + Date string + Time int64 + Event int + FriendUID int + FriendNick string + Phone string + AmountType int + Amount int64 + RefererUID int + RefererNick string + Level int + Balance int64 +} diff --git a/db/es/es_exec.go b/db/es/es_exec.go index b915988..0bf8cc6 100644 --- a/db/es/es_exec.go +++ b/db/es/es_exec.go @@ -599,3 +599,49 @@ func (ES *EsClient) Exist(index, id string) bool { } return ret } + +// Exist 判断是否存在 +func (ES *EsClient) IndexExist(index string) bool { + ret, err := ES.C().IndexExists(index).Do(context.Background()) + if err != nil { + log.Error("err:%v", err) + return false + } + return ret +} + +// Exist 判断是否存在 +func (ES *EsClient) CreateExist(index string) error { + _, err := ES.C().CreateIndex(index).Do(context.Background()) + if err != nil { + log.Error("err:%v", err) + return err + } + return nil +} + +// Exist 判断是否存在 +func (ES *EsClient) AddAlias(aliasName, indexName string) error { + alias := elastic.NewAliasAddAction(aliasName).Index(indexName).IsWriteIndex(true) + aliasResult, err := ES.client.Alias().Action(alias).Do(context.Background()) + if err != nil || !aliasResult.Acknowledged { + log.Error("err:%v", err) + return err + } + return nil +} + +func (ES *EsClient) Rollover(aliasName, indexName string, conditon map[string]interface{}) error { + req := ES.client.RolloverIndex(aliasName).NewIndex(indexName) + if conditon != nil { + for k, v := range conditon { + req.AddCondition(k, v) + } + } + aliasResult, err := req.Do(context.Background()) + if err != nil || !aliasResult.Acknowledged { + log.Error("err:%v", err) + return err + } + return nil +} diff --git a/modules/backend/migrate.go b/modules/backend/migrate.go index 3026c99..4d29ed3 100644 --- a/modules/backend/migrate.go +++ b/modules/backend/migrate.go @@ -72,7 +72,6 @@ func MigrateDB() { new(common.ConfigWater), new(common.ConfigRobot), new(common.ConfigAppSpin), - new(common.ConfigShare), new(common.ConfigShareSys), new(common.ShareInfo), new(common.ShareOrder), @@ -137,6 +136,16 @@ func MigrateDB() { new(common.ConfigLuckyWheel), new(common.PddDataNew), new(common.PddLotteryHistory), + new(common.ConfigShareTaskNew), + new(common.ShareTaskNewData), + new(common.ConfigShare), + new(common.ShareRank), + new(common.ConfigShareLimitTask), + new(common.ShareLimitTaskData), + new(common.ShareWithdrawInfo), + new(common.ConfigShareWithdrawProducts), + new(common.ConfigShareBanner), + new(common.ShareRewardData), ) if err != nil { panic("Migrate db fail") diff --git a/modules/backend/values/gm.go b/modules/backend/values/gm.go index e3e4c84..6465ef2 100644 --- a/modules/backend/values/gm.go +++ b/modules/backend/values/gm.go @@ -108,8 +108,6 @@ func GetControlType(path string) int { return common.ReloadConfigRobot case "appSpin": return common.ReloadConfigAppSpin - case "share": - return common.ReloadConfigShare case "shareSys": return common.ReloadConfigShareSys case "pddSpin": @@ -187,6 +185,16 @@ func GetControlType(path string) int { return common.ReloadConfigPdd case "luckyWheel": return common.ReloadConfigLuckyWheel + case "share": + return common.ReloadConfigShare + case "shareWithdrawProducts": + return common.ReloadConfigShareWithdrawProducts + case "shareLimitTask": + return common.ReloadConfigShareLimitTask + case "shareTaskNew": + return common.ReloadConfigShareTaskNew + case "shareBanner": + return common.ReloadConfigShareBanner default: return 0 } diff --git a/modules/common/es.go b/modules/common/es.go new file mode 100644 index 0000000..54fc999 --- /dev/null +++ b/modules/common/es.go @@ -0,0 +1,10 @@ +package common + +import ( + "server/call" + "server/pb" +) + +func esBulk(d *pb.InnerESBulk) { + call.AddBulk(&call.WriteData{Index: d.Index, Data: d.Data, ID: d.ID}) +} diff --git a/modules/common/nats.go b/modules/common/nats.go index 9599016..f03dea7 100644 --- a/modules/common/nats.go +++ b/modules/common/nats.go @@ -22,6 +22,16 @@ func initNats(conn *nats.Conn) { } afterSettle(d) }, natsClient.QueueAfterSettle) + + natsClient.NewCommonNatsImp(conn, natsClient.TopicInnerESBulk, func(data []byte) { + d := new(pb.InnerESBulk) + err := proto.Unmarshal(data, d) + if err != nil { + log.Error("err:%v", err) + return + } + esBulk(d) + }) } type Player struct { diff --git a/modules/web/handler/share.go b/modules/web/handler/share.go index fc1ab96..cd392de 100644 --- a/modules/web/handler/share.go +++ b/modules/web/handler/share.go @@ -1,491 +1,776 @@ package handler import ( + "encoding/json" "fmt" + "github.com/gin-gonic/gin" + "github.com/liangdas/mqant/log" + "gorm.io/gorm" "server/call" "server/common" + "server/config" "server/db" "server/modules/web/app" "server/modules/web/values" - "server/pb" "server/util" "time" - - "github.com/gin-gonic/gin" - "github.com/liangdas/mqant/log" - "gorm.io/gorm" ) -// func ShareInfo(c *gin.Context) { -// a := app.NewApp(c) -// defer func() { -// a.Response() -// }() -// shareInfo := &common.ShareInfo{} -// resp := &values.ShareInfoResp{ -// ShareConfig: call.GetConfigShare(), -// } -// a.Data = resp -// a.GetUID() -// if a.UID > 0 { -// shareInfo = call.GetShareInfo(a.UID) -// resp.Today = values.ShareRecord{ -// Regist: shareInfo.TodayAgents, -// Real: shareInfo.TodayRealAgents, -// Bet: shareInfo.TodayAgentsBet, -// Reward: shareInfo.TodayReward, -// } -// resp.Total = values.ShareRecord{ -// Regist: shareInfo.TotalAgents, -// Real: shareInfo.TotalRealAgents, -// Bet: shareInfo.TotalAgentsBet, -// Reward: shareInfo.TotalReward, -// } -// resp.Rewards = values.RewardRecord{ -// Level: shareInfo.Level, -// TotalWithdraw: shareInfo.TotalReward - shareInfo.AvailableReward, -// Available: shareInfo.AvailableReward, -// } -// } - -// channel := call.GetChannelByID(a.Channel) -// if channel != nil { -// resp.ShareLink = channel.URL + "?code=" + shareInfo.Share -// if a.Prefix != "" { -// resp.ShareLink = a.Prefix + "." + resp.ShareLink -// } else { -// resp.ShareLink = "www." + resp.ShareLink -// } -// if shareInfo.Share == "" { -// resp.ShareLink += "xxxxxx" -// } -// } -// con := call.GetConfigShareSys() -// if con != nil { -// resp.Rewards.WithdrawLimit = con.WithdrawLimit -// } -// } - +// 分享信息[done] func ShareInfo(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() - resp := &values.ShareInfoResp{ - InviteRecharge: call.GetConfigShareSys().ShareRecharge, - PlatformInviteReward: values.ShareTotalInviteReward + call.GetConfigShareSys().FakeInviteReward, - PlatformBetReward: values.ShareTotalBetReward + call.GetConfigShareSys().FakeBetReward, - Rank: values.ShareRank, + if !a.CheckActivityExpire(common.ActivityIDShare) { + return } + resp := &values.ShareNewInfoResp{} a.Data = resp - resp.PlatformTotalReward = resp.PlatformInviteReward + resp.PlatformBetReward - for _, v := range call.GetConfigShare() { - resp.BetPer = append(resp.BetPer, util.FormatFloat(float64(v.Per)/10, 2)+"%") + + banners := call.GetConfigShareBanner(a.Channel) + for _, v := range banners { + resp.Banners = append(resp.Banners, v.URL) } - channel := call.GetChannelByID(a.Channel) - if channel != nil { - resp.ShareLink = channel.ShareUrl + + shareInfo := call.GetShareInfo(a.UID) + resp.NowLevel = shareInfo.Level + resp.NowExp = shareInfo.Exp + nextCon := call.GetConfigShare(shareInfo.Level+1, a.Channel) + if nextCon != nil { + resp.NextExp = nextCon.Exp + } else { + resp.NextExp = shareInfo.Exp } - a.GetUID() - if a.UID <= 0 { + conShare := call.GetConfigShare(shareInfo.Level, a.Channel) + if conShare == nil { + a.Code = values.CodeRetry return } - shareInfo := call.GetShareInfo(a.UID) - resp.InviteReward = shareInfo.InviteReward - resp.BetReward = shareInfo.BetReward - resp.Invites = shareInfo.Invites - resp.InvalidInvites = shareInfo.InvaidInvites - resp.TotalReward = resp.InviteReward + resp.BetReward - resp.AvailableReward = shareInfo.AvailableReward - resp.RechargeCount = call.GetUserShareRecharges(a.UID, 1) - resp.TotalRecharge = call.GetUserShareRechargeAmount(a.UID, 1) - resp.ShareCode = shareInfo.Share - if len(resp.ShareLink) > 0 { - resp.ShareLink += fmt.Sprintf("&code=%v", shareInfo.Share) - } - num := 0 - if resp.AvailableReward > 0 { - num = 1 - } - if num > 0 { - call.PushRed(a.UID, pb.RedPointModule_RedPointShare, uint32(num)) + resp.ShareLink = call.GetShareLink(a.Channel, a.UID) + user, _ := call.GetUserInfo(a.UID) + resp.Avatar = user.Avatar + // 新手任务弹窗 + task := &common.ShareTaskNewData{UID: a.UID} + db.Mysql().Get(task) + if task.ID == 0 { // 初始化任务 + if user.IsOldDevice != 1 { + resp.PopNewTask = true + } + resp.NewReward = conShare.SubNewReward.Amount + shareInfo.Reward += conShare.SubNewReward.Amount + update := map[string]interface{}{"reward": gorm.Expr("reward + ?", conShare.SubNewReward.Amount)} + if conShare.SubNewReward.CanWithdraw { + shareInfo.Withdrawable += conShare.SubNewReward.Amount + update["withdrawable"] = gorm.Expr("withdrawable + ?", conShare.SubNewReward.Amount) + // 新建一个任务标记玩家已经领取过新手奖励 + task := &common.ShareTaskNewData{UID: a.UID, TaskID: 1, Type: common.ShareTaskNewTypeFirst, Progress: 1, Target: 1, Reward: 0, Status: 1} + db.Mysql().Create(task) + } else { + con := call.GetConfigShareTaskNew() + for _, v := range con { + task := &common.ShareTaskNewData{UID: a.UID, TaskID: v.TaskID, Type: v.Type, Progress: 0, Target: v.Target, Reward: v.Reward, Condition: v.Condition} + if v.Type == common.ShareTaskNewTypeFirst { + task.Progress = 1 + } + db.Mysql().Create(task) + } + } + db.Mysql().Update(&common.ShareInfo{UID: a.UID}, update) + call.WriteShareBalance(&common.ESShareBalance{ + Event: common.ShareEventOther, + FriendUID: a.UID, + AmountType: int(common.CurrencyINR), + RefererUID: a.UID, + Amount: conShare.SubNewReward.Amount, + Level: 1, + Balance: conShare.SubNewReward.Amount, + }, true) + } + + // 可退出弹窗 + //products := call.GetConfigWithdrawProduct(common.WithdrawSorceShare) + //if shareInfo.PopWithdraw == 0 && len(products) > 0 && shareInfo.Withdrawable >= products[0].Amount*100 { + // resp.PopWithdraw = true + // resp.PopWithdrawAmount = products[0].Amount * 100 + // shareInfo.PopWithdraw = 1 + // db.Mysql().Update(&common.ShareInfo{ID: shareInfo.ID}, map[string]interface{}{"pop_withdraw": 1}) + //} + + resp.Balance = shareInfo.Reward + resp.TotalCommission = shareInfo.Withdrawable + resp.TotalReferrals = shareInfo.Down1 + shareInfo.Down2 + shareInfo.Down3 + shareInfo.Down4 + shareInfo.Down5 + resp.TotalWithdrawals = call.GetShareWithdrawInfo(a.UID).TotalWithdraw * 100 + + // 昨日收益弹窗 + { + now := time.Now() + t := util.GetZeroTime(now.AddDate(0, 0, -1)).Unix() + last := &common.ShareRewardData{UID: a.UID, Time: t} + db.Mysql().Get(last) + if last.ID > 0 && !util.IsSameDayTimeStamp(now.Unix(), last.PopTime) { + db.Mysql().Update(&common.ShareRewardData{UID: a.UID, Time: t}, map[string]interface{}{"pop_time": now.Unix()}) + resp.LastReward.Total = last.TotalReward + resp.LastReward.Invitation = last.InviteReward + resp.LastReward.Recharge = last.RechargeReward + resp.LastReward.Affiliate = last.AffiliateReward + resp.LastReward.Other = last.OtherReward + } + } + + // 升级弹窗 + { + if shareInfo.LastLevel != shareInfo.Level { + db.Mysql().Update(&common.ShareInfo{UID: a.UID}, map[string]interface{}{"last_level": shareInfo.Level}) + resp.LevelUpInfo = conShare.GetLevelUpInfo() + } + } +} + +// 分享新手任务[done] +func ShareNewTaskInfo(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + resp := &values.ShareNewTaskInfoResp{} + a.Data = resp + list := []common.ShareTaskNewData{} + db.Mysql().QueryAll(fmt.Sprintf("uid = %d", a.UID), "", &common.ShareTaskNewData{}, &list) + for _, v := range list { + one := values.OneShareNewTask{ + TaskID: v.TaskID, + Desc: v.GetDesc(), + Type: v.Type, + Progess: v.Progress, + Target: v.Target, + Reward: v.Reward, + } + if one.Progess >= one.Target || v.Status == 1 { + one.Progess = one.Target + if v.Status == 1 { + one.Status = 2 + } else { + one.Status = 1 + } + } + resp.TaskList = append(resp.TaskList, one) } } -func ShareList(c *gin.Context) { +// 新手任务领取[done] +func ShareNewTaskDraw(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() - req := new(values.ShareListReq) + req := new(values.ShareNewTaskDrawReq) if !a.S(req) { return } - resp := &values.ShareListResp{} + resp := &values.ShareNewTaskDrawResp{} a.Data = resp - type TempData struct { - Uid int `gorm:"column:UID"` - Amount int64 `gorm:"column:total_reward"` - RechargeAmount int64 `gorm:"column:total_recharge"` + + task := &common.ShareTaskNewData{UID: a.UID, TaskID: req.TaskID} + db.Mysql().Get(task) + if task.ID == 0 || task.Progress < task.Target { + a.Code = values.CodeParam + a.Msg = "Task not completed." + return } - var ret []TempData - if req.Type == 1 { - err := db.Mysql().QueryCountBySql(fmt.Sprintf("select count(*) from (SELECT count(*) FROM share_detail WHERE FROM_UNIXTIME(Time, '%%Y-%%m-%%d') = CURDATE() and up = %d GROUP BY UID ORDER BY SUM(reward) DESC)a", a.UID), &resp.Count) - if err != nil { - log.Error("err:%v", err) - } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail WHERE up = %d and FROM_UNIXTIME(Time, '%%Y-%%m-%%d') = CURDATE() GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) - if err != nil { - log.Error("err:%v", err) - } - for _, item := range ret { - resp.TodayRewardList = append(resp.TodayRewardList, values.RewardInfo{ - UID: item.Uid, - Amount: util.Decimal(float64(item.Amount)/common.DecimalDigits, 2), - }) - } - } else if req.Type == 2 { - err := db.Mysql().QueryCountBySql(fmt.Sprintf("select count(*) from (SELECT count(*) FROM share_detail where up = %d GROUP BY UID ORDER BY SUM(reward) DESC)a", a.UID), &resp.Count) - if err != nil { - log.Error("err:%v", err) - } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) - if err != nil { - log.Error("err:%v", err) - } - for _, item := range ret { - resp.RewardList = append(resp.RewardList, values.RewardInfo{ - UID: item.Uid, - Amount: util.Decimal(float64(item.Amount)/common.DecimalDigits, 2), - }) - } - } else if req.Type == 3 { - err := db.Mysql().QueryCountBySql(fmt.Sprintf("select count(*) from (SELECT count(*) FROM share_detail where up = %d GROUP BY UID ORDER BY SUM(recharge_amount) DESC)a", a.UID), &resp.Count) - if err != nil { - log.Error("err:%v", err) - } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_recharge DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) - if err != nil { - log.Error("err:%v", err) - } - for _, item := range ret { - user, _ := call.GetUserXInfo(item.Uid, "birth") - resp.InviteList = append(resp.InviteList, values.InviteInfo{ - UID: item.Uid, - RechargeAmount: item.RechargeAmount / common.DecimalDigits, - RegisterTime: user.Birth, - }) - } + if task.Status == 1 { + a.Code = values.CodeParam + a.Msg = "Task received." + return + } + rows, err := db.Mysql().UpdateWRes(&common.ShareTaskNewData{}, map[string]interface{}{"status": 1}, fmt.Sprintf("uid = %d and task_id = %d and status = 0", a.UID, req.TaskID)) + if rows == 0 || err != nil { + a.Code = values.CodeRetry + return } + s := call.GetShareInfo(a.UID) + // 转化奖励 + db.Mysql().Update(&common.ShareInfo{UID: a.UID}, map[string]interface{}{"withdrawable": gorm.Expr("withdrawable + ?", task.Reward)}) + bal := &common.ESShareBalance{ + Event: common.ShareEventOther, + AmountType: int(common.CurrencyINR), + Amount: task.Reward, + RefererUID: a.UID, + Level: s.Level, + Balance: s.Withdrawable + task.Reward, + } + call.WriteShareBalance(bal, false) + resp.Reward = task.Reward } -func GetActivityCode(c *gin.Context) { +func ShareNewAffiliate(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() - req := new(values.GetActivityCodeReq) + req := new(values.ShareNewAffiliateReq) if !a.S(req) { return } - resp := &values.GetActivityCodeResp{} + if req.Num > 50 { + req.Num = 50 + } + + resp := &values.ShareNewAffiliateResp{} a.Data = resp - channel := call.GetChannelByID(a.Channel) - if channel != nil { - resp.ShareLink += channel.URL + "?code=" + "xxxxxx" + + si := &common.ShareInfo{UID: a.UID} + db.Mysql().Get(si) + if si.ID == 0 { + return } - a.GetUID() - if a.UID <= 0 { + resp.Level1 = si.Down1 + resp.Level2 = si.Down2 + resp.Level3 = si.Down3 + resp.Level4 = si.Down4 + resp.Level5 = si.Down5 + list := []common.ShareInfo{} + sql := fmt.Sprintf("up1 = %d", a.UID) + if req.Level > 0 { + sql = fmt.Sprintf("up%d = %d", req.Level, a.UID) + } + resp.Count, _ = db.Mysql().QueryList(req.Page, req.Num, sql, "down1 desc", &common.ShareInfo{}, &list) + for _, v := range list { + one := values.OneShareNewAffiliate{UID: v.UID, AffiliateCount: v.Down1} + p, _ := call.GetUserXInfo(v.UID, "nick", "last_login") + one.Nick = p.Nick + one.LastLogin = p.LastLogin + resp.AffiliateList = append(resp.AffiliateList, one) + } +} + +// 收益列表 +func ShareNewCommission(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + req := new(values.ShareNewCommissionReq) + if !a.S(req) { return } - code, err := call.GetActivityShareCode(a.UID, req.ActivityId) - if err != nil { - a.Code = values.CodeRetry + resp := &values.ShareNewCommissionResp{Count: 100, List: []values.OneShareNewCommission{}} + a.Data = resp + total := &common.ShareRewardData{UID: a.UID} + db.Mysql().QueryBySql(fmt.Sprintf("select * from share_reward_data where uid = %d and time = 0", a.UID), total) + resp.All = total.TotalReward + resp.Invitation = total.InviteReward + resp.Affiliate = total.AffiliateReward + resp.Recharge = total.RechargeReward + resp.Other = total.OtherReward + + if req.Num*req.Page >= 100 { return } - if channel != nil { - resp.ShareLink = channel.URL + "?code=" + code - if a.Prefix != "" { - resp.ShareLink = a.Prefix + "." + resp.ShareLink - } else { - resp.ShareLink = "www." + resp.ShareLink + list := []common.ShareRewardData{} + db.Mysql().QueryList(0, 100, fmt.Sprintf("uid = %d", a.UID), "time desc", &common.ShareRewardData{}, &list) + now := time.Now() + zero := util.GetZeroTime(now) + if req.Page > 0 { + zero = zero.AddDate(0, 0, -req.Page*req.Num) + } + for i := 0; i < req.Num; i++ { + one := values.OneShareNewCommission{Date: zero.Format("20060102")} + for _, v := range list { + if v.Date == one.Date { + one.Invitation = v.InviteReward + one.Recharge = v.RechargeReward + one.Affiliate = v.AffiliateReward + one.Other = v.OtherReward + break + } } + resp.List = append(resp.List, one) + zero = zero.AddDate(0, 0, -1) } } -func SharePlatformInfo(c *gin.Context) { +// 排行榜 +func ShareNewRank(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() - resp := &values.SharePlatformResp{ - InviteReward: values.ShareTotalInviteReward, - BetReward: values.ShareTotalBetReward, + req := new(values.ShareNewRankReq) + if !a.S(req) { + return + } + resp := &values.ShareNewRankResp{ + List: []*common.ShareRank{}, + } + a.Data = resp + + now := time.Now() + dayNow := now + for i := 0; i < 7; i++ { + resp.Days = append(resp.Days, dayNow.Format("01/02")) + dayNow = dayNow.AddDate(0, 0, -1) } + weekNow := util.GetWeekZeroTime(now) + for i := 0; i < 4; i++ { + resp.Weeks = append(resp.Weeks, fmt.Sprintf("%s-%s", weekNow.Format("01/02"), weekNow.AddDate(0, 0, 7).Format("01/02"))) + weekNow = weekNow.AddDate(0, 0, -7) + } + monthNow := util.GetFirstDateOfMonth(now) + for i := 0; i < 3; i++ { + resp.Months = append(resp.Months, fmt.Sprintf("%s-%s", monthNow.Format("01/02"), monthNow.AddDate(0, 1, 0).Format("01/02"))) + monthNow = monthNow.AddDate(0, -1, 0) + } + + var list []*common.ShareRank + resp.Self = &common.ShareRank{ + UID: a.UID, + Type: req.Type, + Rank: -1, + } + if req.Time == 0 { + resp.Self.Time = time.Now().Unix() + switch req.Type { + case common.ShareRankTypeDaily: + list = values.ShareRankDaily + case common.ShareRankTypeWeekly: + list = values.ShareRankWeekly + case common.ShareRankTypeMonthly: + list = values.ShareRankMonthly + } + } else { + var ti int64 + switch req.Type { + case common.ShareRankTypeDaily: + ti = util.GetZeroTime(now.AddDate(0, 0, -req.Time)).Unix() + case common.ShareRankTypeWeekly: + ti = util.GetWeekZeroTime(now.AddDate(0, 0, -req.Time*7)).Unix() + case common.ShareRankTypeMonthly: + ti = util.GetFirstDateOfMonth(now.AddDate(0, -req.Time, 0)).Unix() + } + resp.Self.Time = ti + list = call.GetShareRank(req.Type, ti) + } + for i, v := range list { + v.Rank = i + 1 + if v.UID == a.UID { + resp.Self = v + } + } + if resp.Self.Rank == -1 { + resp.Self = call.GetShareRewardData(a.UID, req.Type, resp.Self.Time) + resp.Self.Rank = -1 + } + start := req.Page * req.Num + if start > common.ShareRankMaxNum { + return + } + if start > len(list) { + return + } + end := start + req.Num + if end > common.ShareRankMaxNum { + end = common.ShareRankMaxNum + } + if end > len(list) { + end = len(list) + } + resp.List = list[start:end] +} + +// 限时任务 +func ShareLimitTaskInfo(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + resp := &values.ShareLimitTaskInfoResp{} a.Data = resp + si := call.GetShareInfo(a.UID) + tasks := []*common.ShareLimitTaskData{} + db.Mysql().QueryBySql(fmt.Sprintf("select * from share_limit_task_data where uid = %d order by level asc", a.UID), &tasks) + now := time.Now().Unix() + + var task *common.ShareLimitTaskData + + for i := 1; i <= si.Level; i++ { + var thisTask *common.ShareLimitTaskData + for _, v := range tasks { + if v.Level == i { + thisTask = v + break + } + } + if thisTask == nil { // 当前等级还未创建 + conTask := call.GetConfigShareLimitTask(i, a.Channel) + if conTask != nil { + thisTask = &common.ShareLimitTaskData{} + thisTask.UID = a.UID + thisTask.Level = i + thisTask.CreateTime = now + thisTask.Time = conTask.Time + thisTask.Status = 0 + thisTask.Reward = conTask.Reward + db.Mysql().Create(thisTask) + if i <= si.Level && task == nil { + task = thisTask + } + } + } else if thisTask.IsValid() && task == nil { + task = thisTask + } + } + exLevel := si.Level + nextLevel := si.Level + 1 + if task != nil { + exLevel = task.Level + nextLevel = task.Level + 1 + resp.TimeLeft = task.CreateTime + task.Time*60 - now + resp.Reward = task.Reward + } - resp.TotalReward = resp.InviteReward + resp.BetReward - resp.Rank = values.ShareRank + conShareEx := call.GetConfigShare(exLevel, a.Channel) + conShare := call.GetConfigShare(nextLevel, a.Channel) + if conShare == nil { + conShare = conShareEx + } + + resp.NowLevel = conShareEx.GetLevelUpInfo() + resp.NextLevel = conShare.GetLevelUpInfo() + resp.Exp = si.Exp + resp.LevelUpExp = conShare.Exp + if resp.LevelUpExp < 0 { + resp.LevelUpExp = resp.Exp + } + resp.CanDraw = task != nil && si.Exp >= resp.LevelUpExp } -func ShareWithdraw(c *gin.Context) { +func ShareLimitTaskDraw(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() - req := new(values.ShareWithdrawReq) + req := new(values.ShareLimitTaskDrawReq) if !a.S(req) { return } - if req.Opt < 1 || req.Opt > 2 { + resp := &values.ShareLimitTaskDrawResp{} + a.Data = resp + task := &common.ShareLimitTaskData{UID: a.UID, Level: req.NowLevel} + db.Mysql().Get(task) + if !task.IsValid() { a.Code = values.CodeParam + a.Msg = "Invalid draw." return } - con := call.GetConfigShareSys() - log.Debug("player %d ShareWithdraw,con:%+v", a.UID, con) + si := call.GetShareInfo(a.UID) + if si.Level <= task.Level { // 不可领取 + a.Code = values.CodeParam + a.Msg = "Invalid draw." + return + } + rows, err := db.Mysql().UpdateWRes(&common.ShareLimitTaskData{}, map[string]interface{}{"status": 1}, + fmt.Sprintf("uid = %d and level = %d and status = 0", a.UID, task.Level)) + if err != nil || rows == 0 { + a.Code = values.CodeParam + a.Msg = "Invalid draw." + return + } + db.Mysql().Update(&common.ShareInfo{UID: a.UID}, + map[string]interface{}{"reward": gorm.Expr("reward + ?", task.Reward), "withdrawable": gorm.Expr("withdrawable + ?", task.Reward)}) + call.WriteShareBalance(&common.ESShareBalance{ + Event: common.ShareEventOther, + // FriendUID: , + AmountType: int(common.CurrencyINR), + Amount: task.Reward, + RefererUID: a.UID, + Level: si.Level, + Balance: si.Reward + task.Reward, + }, true) + resp.Reward = task.Reward +} + +func ShareNewWithdrawInfo(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + resp := &values.ShareNewWithdrawInfoResp{Tips: call.GetConfigPlatform().WithdrawTips} + a.Data = resp + si := call.GetShareInfo(a.UID) + resp.TotalBalance = si.Reward + resp.Withdrawable = si.Withdrawable + list := call.GetConfigWithdrawProduct(common.WithdrawSorceShare) + db.Mysql().QueryList(0, 3, fmt.Sprintf("uid = %d and draw_type = '%s'", a.UID, common.WithdrawTypeBank), "id desc", &common.PayInfo{}, &resp.Accounts) + sw := call.GetShareWithdrawInfo(a.UID) + resp.WithDrawCount = sw.DayCount + for _, v := range list { + // todo + one := &values.WithdrawProduct{ID: v.ProductID, Amount: v.Amount} + resp.List = append(resp.List, one) + } + + con := call.GetConfigShare(si.Level, a.Channel) if con == nil { a.Code = values.CodeRetry return } - shareInfo := call.GetShareInfo(a.UID) - if shareInfo.ID <= 0 { + resp.TotalWithdrawCount = con.DayWithdrawCount + channels := call.GetConfigWithdrawChannels() + if len(channels) > 0 { + resp.NewList = []*common.ConfigWithdrawChannels{channels[0]} + } else { + resp.NewList = []*common.ConfigWithdrawChannels{} + } +} + +func ShareNewWithdraw(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + + req := new(values.WithdrawReq) + if !a.S(req) { + return + } + if req.CurrencyType != common.CurrencyINR { + req.CurrencyType = common.CurrencyINR + } + + one := call.GetConfigWithdrawProductByID(req.AmountID) + if one == nil { a.Code = values.CodeParam + a.Msg = "Withdraw product not found." return } - availableReward := shareInfo.AvailableReward - if availableReward < con.WithdrawLimit { + + uid := a.UID + log.Debug("player %v withdraw %+v,one:%+v", uid, *req, *one) + + amount := one.Amount * 100 + si := call.GetShareInfo(uid) + if si.Withdrawable < amount { a.Code = values.CodeParam - a.Msg = fmt.Sprintf("Minimum withdrawal requirement is %d.", con.WithdrawLimit/common.DecimalDigits) + a.Msg = "Insufficient balance." return } - if req.Amount > availableReward { + + con := call.GetConfigShare(si.Level, a.Channel) + if con == nil { + a.Code = values.CodeRetry + return + } + + sw := call.GetShareWithdrawInfo(uid) + if sw.DayCount >= con.DayWithdrawCount { a.Code = values.CodeParam + a.Msg = "Withdrawal limit." return } - // 直接到余额 - if req.Opt == 1 { - rows, err := db.Mysql().UpdateResW(&common.ShareInfo{}, map[string]interface{}{"available_reward": gorm.Expr("available_reward - ?", req.Amount)}, - fmt.Sprintf("available_reward = %d and uid = %d", availableReward, a.UID)) - if err != nil { - log.Error("err:%v", err) + // 到游戏账户 + if req.Type == 1 { + tx := db.Mysql().Begin() + defer a.MCommit(tx) + // 更新余额 + res := tx.Model(&common.ShareInfo{}).Where("uid = ? and reward >= ? and withdrawable >= ?", uid, amount, amount). + Updates(map[string]interface{}{ + "reward": gorm.Expr("reward - ?", amount), + "withdrawable": gorm.Expr("withdrawable - ?", amount), + }) + if res.RowsAffected == 0 || res.Error != nil { + log.Error("err:%v", res.Error) a.Code = values.CodeRetry return } - if rows == 0 { + // 更新次数 + res = tx.Model(&common.ShareWithdrawInfo{}).Where("uid = ? and day_time = ?", uid, sw.DayTime). + Updates(map[string]interface{}{"day_count": sw.DayCount + 1, "day_time": time.Now().Unix(), "total_withdraw": gorm.Expr("total_withdraw + ?", one.Amount)}) + if res.RowsAffected == 0 || res.Error != nil { + log.Error("err:%v", res.Error) a.Code = values.CodeRetry return } - call.UpdateCurrencyPro(&common.UpdateCurrency{ + // 更新rechargeinfo,转移到游戏等同于充值 + re := call.GetRechargeInfo(uid) + if re.ID == 0 { + res = tx.Model(&common.RechargeInfo{}).Create(&common.RechargeInfo{UID: uid, TotalRecharge: one.Amount}) + } else { + res = tx.Model(&common.RechargeInfo{}).Where("uid = ? ", uid). + Updates(map[string]interface{}{ + "total_charge": gorm.Expr("total_charge + ?", one.Amount), + }) + } + if res.RowsAffected == 0 || res.Error != nil { + log.Error("err:%v", res.Error) + a.Code = values.CodeRetry + return + } + db.Mysql().Create(&common.RechargeOrder{ + UID: uid, + OrderID: util.NewOrderID(uid), + APIPayID: "", + // ProductID: common.ActivityIDPddShare, + Amount: one.Amount, + WithdrawCash: amount, + Status: common.StatusROrderFinish, + PaySource: common.PaySourceModulePay, + Event: int(common.CurrencyEventShareWithdraw), + // PayAccount: payInfo, + // Extra: strconv.FormatInt(serviceFee, 10), + CallbackTime: time.Now().Unix(), + ChannelID: a.Channel, + UPI: -1, + Scene: common.ActivityIDShare, + }) + _, err := call.UpdateCurrencyPro(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ - UID: a.UID, - Type: common.CurrencyINR, - ChannelID: a.Channel, - Value: req.Amount, - Event: common.CurrencyEventShareWithdraw, - NeedBet: call.GetConfigCurrencyResourceNeedBet(common.CurrencyResourceShare, req.Amount), + UID: uid, + Value: amount * -1, + Event: common.CurrencyEventShareWithdraw, + Type: common.CurrencyINR, }, }) + if err != nil { + a.Code = values.CodeRetry + return + } + a.Msg = "Withdraw to game successfully." return } ip := a.GetRemoteIP() - payInfo, code := NewWithdraw(&values.WithdrawReq{PayAccount: req.PayAccount}, a.UID, ip, a.UUID) + payInfo, code := NewWithdraw(req, a.UID, ip, a.UUID) if code != values.CodeOK { a.Code = code a.Msg = payInfo return } - if len(payInfo) > 500 { - a.Code = values.CodeParam - a.Msg = "Withdrawal information too long." - return - } + tx := db.Mysql().Begin() + defer a.MCommit(tx) - re := call.GetRechargeInfo(a.UID) - now := time.Now().Unix() - if re.ID == 0 { - re.LastWithdraw = now - if err := db.Mysql().Create(re); err != nil { - a.Code = values.CodeRetry - return - } - } else { - u := map[string]interface{}{"last_withdraw": now} - if !util.IsSameDayTimeStamp(now, re.LastWithdraw) { - u["withdraw_count"] = 0 - u["day_withdraw"] = 0 - } - rows, err := db.Mysql().UpdateRes(&common.RechargeInfo{UID: a.UID, LastWithdraw: re.LastWithdraw}, u) - if err != nil || rows == 0 { - a.Code = values.CodeRetry - return - } - } - - orderID := util.NewOrderID(a.UID) - - vipCon := call.GetVipCon(a.UID) - realAmount := req.Amount // 实际打款 - if con != nil && vipCon.Fee > 0 { - realAmount = common.RoundCurrency(common.CurrencyINR, (1000-int64(vipCon.Fee))*realAmount/1000) - } - rows, err := db.Mysql().UpdateResW(&common.ShareInfo{}, map[string]interface{}{"available_reward": gorm.Expr("available_reward - ?", req.Amount)}, - fmt.Sprintf("available_reward = %d and uid = %d", availableReward, a.UID)) - if err != nil { - log.Error("err:%v", err) + // 发起tx + // 更新余额 + res := tx.Model(&common.ShareInfo{}).Where("uid = ? and reward >= ? and withdrawable >= ?", uid, amount, amount). + Updates(map[string]interface{}{ + "reward": gorm.Expr("reward - ?", amount), + "withdrawable": gorm.Expr("withdrawable - ?", amount), + }) + if res.RowsAffected == 0 || res.Error != nil { + log.Error("err:%v", res.Error) a.Code = values.CodeRetry return } - if rows == 0 { + + // 更新次数 + sw.SubRecord[one.Amount]++ + byt, _ := json.Marshal(sw.SubRecord) + res = tx.Model(&common.ShareWithdrawInfo{}).Where("uid = ? and day_time = ?", uid, sw.DayTime). + Updates(map[string]interface{}{"day_count": sw.DayCount + 1, "day_time": time.Now().Unix(), "record": string(byt), + "total_withdraw": gorm.Expr("total_withdraw + ?", one.Amount)}) + if res.RowsAffected == 0 || res.Error != nil { + log.Error("err:%v", res.Error) a.Code = values.CodeRetry return } - order := &common.WithdrawOrder{ - UID: int(a.UID), - OrderID: orderID, - APIPayID: "", - // ProductID: one.ID, - Extra: "share", - CreateTime: time.Now().Unix(), - Amount: realAmount, - WithdrawCash: req.Amount, - Status: uint8(common.StatusROrderCreate), + orderID := util.NewOrderID(uid) + + order := &common.RechargeOrder{ + UID: uid, + OrderID: orderID, + APIPayID: "", + ProductID: one.ProductID, + Amount: one.Amount, + WithdrawCash: amount, + Status: common.StatusROrderCreate, PaySource: common.PaySourceModulePay, Event: int(common.CurrencyEventWithDraw), - CurrencyType: common.CurrencyINR, PayAccount: payInfo, - ChannelID: a.Channel, - UPI: -1, - OrderType: common.WithdrawOrderTypeShare, + // Extra: strconv.FormatInt(serviceFee, 10), + ChannelID: a.Channel, + UPI: -1, + Scene: common.ActivityIDShare, + } + if config.GetBase().Release && amount < con.WithdrawAudit { + order.Status = common.StatusROrderWaitting } - if err := db.Mysql().Create(order); err != nil { - log.Error("player %v create withdraw order fail err:%v", a.UID, err) + if err := tx.Model(order).Create(order).Error; err != nil { a.Code = values.CodeRetry + log.Error("create withdraw order fail err:%v", err) return } - u := map[string]interface{}{} - u["withdrawing_cash"] = gorm.Expr("withdrawing_cash + ?", req.Amount) - u["withdraw_count"] = gorm.Expr("withdraw_count + ?", 1) - u["total_withdrawing"] = gorm.Expr("total_withdrawing + ?", realAmount) - u["day_withdraw"] = gorm.Expr("day_withdraw + ?", realAmount) - db.Mysql().Update(&common.RechargeInfo{UID: a.UID}, u) - a.Data = values.ShareWithdrawResp{Available: availableReward - req.Amount} + a.Data = values.ShareNewWithdrawResp{TotalBalance: si.Reward - amount, Withdrawable: si.Withdrawable - amount} +} + +func ShareNewWithdrawHis(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() - call.PushRed(a.UID, pb.RedPointModule_RedPointShare, uint32(0)) + req := new(values.ShareNewWithdrawHisReq) + if !a.S(req) { + return + } + if req.Num > 100 { + req.Num = 100 + } + resp := &values.ShareNewWithdrawHisResp{} + a.Data = resp + list, count := call.GetShareWithdrawHis(a.UID, req.Page, req.Num) + resp.Count = count + for i, v := range list { + if v.Status <= common.StatusROrderCreate { + list[i].Status = common.StatusROrderPay + } else if v.Status == common.StatusROrderRefuse || v.Status == common.StatusROrderCancel { + list[i].Status = common.StatusROrderFail + } + one := common.WithdrawCommon{} + if v.PayAccount != "" { + err := json.Unmarshal([]byte(v.PayAccount), &one) + if err != nil { + log.Error("err:%v", err) + continue + } + } + list[i].PayAccount = one.BankCardNo + resp.List = append(resp.List, values.OneShareNewWithdrawHis{ + CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05"), + OrderID: v.OrderID, + PayAccount: v.PayAccount, + UID: v.UID, + Amount: v.Amount, + Event: v.Event, + ProductID: v.ProductID, + Status: v.Status, + FailReason: v.FailReason, + ChannelID: v.ChannelID, + UPI: v.UPI, + Scene: v.Scene, + WithdrawCash: v.WithdrawCash, + }) + } } -// func ShareReference(c *gin.Context) { -// a := app.NewApp(c) -// defer func() { -// a.Response() -// }() -// req := new(values.ShareReferenceReq) -// if !a.S(req) { -// return -// } -// if req.Num > 100 { -// req.Num = 100 -// } -// resp := &values.ShareReferenceResp{} -// a.Data = resp - -// a.GetUID() -// if a.UID == 0 { -// return -// } -// q := elastic.NewBoolQuery() -// if req.Start > 0 { -// q.Filter(elastic.NewRangeQuery("Time").Gte(req.Start)) -// } -// if req.End > 0 { -// q.Filter(elastic.NewRangeQuery("Time").Lt(req.End)) -// } -// q.Filter(elastic.NewTermQuery("Up", a.UID)) -// db.ES().QueryList(common.ESIndexShareProfitRecord, req.Page, req.Num, q, &resp.List) -// resp.TotalBet = db.ES().SumByInt64(common.ESIndexShareProfitRecord, "DownBet", q) + db.ES().SumByInt64(common.ESIndexShareProfitRecord, "Bet", q) -// resp.TotalReward = db.ES().SumByInt64(common.ESIndexShareProfitRecord, "Reward", q) -// } - -// func ShareReport(c *gin.Context) { -// a := app.NewApp(c) -// defer func() { -// a.Response() -// }() -// req := new(values.ShareReportReq) -// if !a.S(req) { -// return -// } -// if req.Num > 100 { -// req.Num = 100 -// } -// resp := &values.ShareReportResp{} -// a.Data = resp - -// a.GetUID() -// if a.UID == 0 { -// return -// } -// q := elastic.NewBoolQuery() -// if req.Start > 0 { -// q.Filter(elastic.NewRangeQuery("Time").Gte(req.Start)) -// } -// if req.End > 0 { -// q.Filter(elastic.NewRangeQuery("Time").Lt(req.End)) -// } -// q.Filter(elastic.NewTermQuery("UID", a.UID)) -// db.ES().QueryList(common.ESIndexShareProfitReport, req.Page, req.Num, q, &resp.List, "Time", false) -// today := &common.ShareInfo{UID: a.UID} -// db.Mysql().Get(today) -// if today.TodayAgents > 0 { -// resp.List = append([]common.ESShareProfitReport{{ -// UID: a.UID, -// Regist: today.TodayAgents, -// Bet: today.TodayAgentsBet, -// Level: today.Level, -// Reward: today.TodayReward, -// Date: time.Now().Format("20060102"), -// Time: time.Now().Unix(), -// }}, resp.List...) -// } -// } - -// func ShareTransfer(c *gin.Context) { -// a := app.NewApp(c) -// defer func() { -// a.Response() -// }() -// req := new(values.ShareTransferReq) -// if !a.S(req) { -// return -// } -// if req.Num > 100 { -// req.Num = 100 -// } - -// resp := &values.ShareTransferResp{} -// a.Data = resp - -// a.GetUID() -// if a.UID == 0 { -// return -// } - -// sql := fmt.Sprintf("uid = %d", a.UID) -// // q := elastic.NewBoolQuery() -// if req.Start > 0 { -// // q.Filter(elastic.NewRangeQuery("Time").Gte(req.Start)) -// sql += fmt.Sprintf(" and create_time>=%d", req.Start) -// } -// if req.End > 0 { -// sql += fmt.Sprintf(" and create_time<%d", req.End) -// // q.Filter(elastic.NewRangeQuery("Time").Lt(req.End)) -// } -// // q.Filter(elastic.NewTermQuery("UID", a.UID)) -// db.Mysql().QueryListW(req.Page, req.Num, "create_time desc", &common.ShareOrder{}, &resp.List, sql) -// // db.ES().QueryList(common.ESIndexShareProfitTransfer, req.Page, req.Num, q, &resp.List) -// } +func ShareNewBroadcast(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + + // req := new(values.ShareNewBroadcastReq) + // if !a.S(req) { + // return + // } + // if req.Num > 100 { + // req.Num = 100 + // } + + resp := &values.ShareNewBroadcastResp{List: values.ShareWithdrawBroadcast} + a.Data = resp +} diff --git a/modules/web/routers/routers_share.go b/modules/web/routers/routers_share.go index d4b61a3..7e885e6 100644 --- a/modules/web/routers/routers_share.go +++ b/modules/web/routers/routers_share.go @@ -7,12 +7,17 @@ import ( ) func share(e *gin.RouterGroup) { + // 新版分享 e.POST("/share/info", handler.ShareInfo) - e.POST("/share/platform", handler.SharePlatformInfo) - e.POST("/share/withdraw", handler.ShareWithdraw) - e.POST("/share/activity_code", handler.GetActivityCode) - e.POST("/share/list", handler.ShareList) - // e.POST("/share/reference", handler.ShareReference) - // e.POST("/share/report", handler.ShareReport) - // e.POST("/share/transfer", handler.ShareTransfer) + e.POST("/share/taskInfo", handler.ShareNewTaskInfo) + e.POST("/share/taskDraw", handler.ShareNewTaskDraw) + e.POST("/share/affiliate", handler.ShareNewAffiliate) + e.POST("/share/commission", handler.ShareNewCommission) + e.POST("/share/rank", handler.ShareNewRank) + e.POST("/share/limitTaskInfo", handler.ShareLimitTaskInfo) + e.POST("/share/limitTaskDraw", handler.ShareLimitTaskDraw) + e.POST("/share/withdrawInfo", handler.ShareNewWithdrawInfo) + e.POST("/share/withdraw", handler.ShareNewWithdraw) + e.POST("/share/withdrawHis", handler.ShareNewWithdrawHis) + e.POST("/share/broadcast", handler.ShareNewBroadcast) } diff --git a/modules/web/values/pay.go b/modules/web/values/pay.go index 22111fd..f54a5a1 100644 --- a/modules/web/values/pay.go +++ b/modules/web/values/pay.go @@ -113,12 +113,13 @@ type WithdrawCheckReq struct { // WithdrawReq 退出请求 type WithdrawReq struct { + Type int `json:"Type" binding:"required"` ChannelID *int `json:"ChannelID"` // 代付渠道选择 CurrencyType common.CurrencyType `json:"CurrencyType"` // 可能对应多种结构 PayAccount map[string]interface{} `json:"payAccount" binding:"required"` - - Amount int64 `json:"amount"` + AmountID int `json:"amountID"` + Amount int64 `json:"amount"` } type WithdrawInfo struct { diff --git a/modules/web/values/protocol.go b/modules/web/values/protocol.go index 5a87b6f..e9f4f1f 100644 --- a/modules/web/values/protocol.go +++ b/modules/web/values/protocol.go @@ -162,3 +162,12 @@ type FavoriteGameReq struct { GameId int // 游戏ID Cancel bool // 是否取消 } + +type WithdrawProduct struct { + ID int `json:"amount_id" redis:"amount_id" table:"amount_id"` // id + Method int `json:"withdrawal_method" redis:"withdrawal_method" table:"withdrawal_method"` // 提现方式 1UPI 2Bank 3UPI+Bank + Amount int64 `json:"withdrawal_amount" redis:"withdrawal_amount" table:"withdrawal_amount"` + ServiceCharge string `json:"service_charge" redis:"service_charge" table:"service_charge"` + PayGold int64 `json:"pay_gold" redis:"pay_gold" table:"pay_gold"` + ReceiptType int `json:"receipt_type" redis:"receipt_type" table:"receipt_type"` // 到账类型 1实时 2延时 +} diff --git a/modules/web/values/shareNew.go b/modules/web/values/shareNew.go new file mode 100644 index 0000000..5e8c0bb --- /dev/null +++ b/modules/web/values/shareNew.go @@ -0,0 +1,233 @@ +package values + +import "server/common" + +// Balance 总余额 +// TotalCommission 可退出 +// TotalWithdrawals 已退出 +// Banners banner图 +// TotalReferrals 总分享 +// ShareLink 分享地址 +// PopNewTask 是否弹出新手任务 +// PopWithdraw 可退出弹窗 +// PopWithdrawAmount 弹出退出金额 +// NewReward 新手奖励金额 +// LastReward 昨天收益 +// LevelUpInfo 升级提示,如果升级了,该字段会有值 +type ShareNewInfoResp struct { + Balance int64 + TotalCommission int64 + TotalWithdrawals int64 + TotalReferrals int64 + Banners []string + ShareLink string + PopNewTask bool + PopWithdraw bool + PopWithdrawAmount int64 + NewReward int64 + LastReward struct { + Total int64 + Invitation int64 + Recharge int64 + Affiliate int64 + Other int64 + } + LevelUpInfo common.LevelUpInfo + NowLevel int + NowExp int64 + NextExp int64 + Avatar string +} + +type ShareNewTaskInfoResp struct { + TaskList []OneShareNewTask +} + +type ShareNewTaskDrawReq struct { + TaskID int +} + +type ShareNewTaskDrawResp struct { + Reward int64 +} + +// TaskID 任务id +// Desc 任务描述 +// Type 任务类型 +// Progress 任务进度 +// Target 任务目标 +// Reward 任务奖励 +// Status 任务状态,0进行中,1可领取,2已领取 +type OneShareNewTask struct { + TaskID int + Desc string + Type int + Progess int64 + Target int64 + Reward int64 + Status int +} + +// Page 页码 +// Num 一页个数,最大50 +// Level int +type ShareNewAffiliateReq struct { + Page int + Num int + Level int +} + +// Level1 每个等级人数 +type ShareNewAffiliateResp struct { + Level1 int64 + Level2 int64 + Level3 int64 + Level4 int64 + Level5 int64 + Count int64 + AffiliateList []OneShareNewAffiliate +} + +// AffiliateCount 下级数量 +type OneShareNewAffiliate struct { + UID int + Nick string + AffiliateCount int64 + LastLogin int64 +} + +// Page 页码 +// Num 一页个数,最大50 +type ShareNewCommissionReq struct { + Page int + Num int +} + +// All 总收益 +// Invitation 总邀请收益 +// Recharge 总充值收益 +// Affiliate 总客损收益 +// Other 总其他收益 +type ShareNewCommissionResp struct { + All int64 + Invitation int64 + Recharge int64 + Affiliate int64 + Other int64 + List []OneShareNewCommission + Count int64 +} + +type OneShareNewCommission struct { + Date string + Invitation int64 + Recharge int64 + Affiliate int64 + Other int64 +} + +// Page 页码 +// Num 一页个数,最大50 +// Type 类型 0日榜 1周榜 2月榜 +// Time 查询时间,0当前周期,1上一周期,以此类推 +type ShareNewRankReq struct { + Page int + Num int + Type int + Time int +} + +type ShareNewRankResp struct { + List []*common.ShareRank + Self *common.ShareRank + Days []string + Weeks []string + Months []string +} + +// 如果参数都是零代表当前没有任务或任务已超时 +// NowLevel 当前等级 +// NextLevel 下一等级 +// Exp 当前经验 +// LevelUpExp 升级所需经验 +// TimeLeft 剩余时间,单位秒 +// CanDraw 是否能领取 +type ShareLimitTaskInfoResp struct { + NowLevel common.LevelUpInfo + NextLevel common.LevelUpInfo + Exp int64 + LevelUpExp int64 + TimeLeft int64 + CanDraw bool + Reward int64 +} + +// NowLevel 领取任务的等级 +type ShareLimitTaskDrawReq struct { + NowLevel int +} + +type ShareLimitTaskDrawResp struct { + Reward int64 +} + +type ShareNewWithdrawInfoResp struct { + TotalBalance int64 + Withdrawable int64 + Method int + List []*WithdrawProduct + WithDrawCount int + TotalWithdrawCount int + Tips string + Accounts []*common.PayInfo + NewList []*common.ConfigWithdrawChannels +} + +// Type 类型 1转移到游戏账户 2退出 +// PayAccount 退出信息,Type为2是不能为空 +type ShareNewWithdrawReq struct { + Type int `json:"Type" binding:"required"` + AmountID int + // 可能对应多种结构 + PayAccount map[string]interface{} `json:"PayAccount"` +} + +type ShareNewWithdrawResp struct { + TotalBalance int64 + Withdrawable int64 +} + +type ShareNewWithdrawHisReq struct { + Page int + Num int +} + +type ShareNewWithdrawHisResp struct { + Count int64 + List []OneShareNewWithdrawHis +} + +type OneShareNewWithdrawHis struct { + CreatedAt string + OrderID string + PayAccount string + UID int + Amount int64 + Event int + ProductID int + Status uint8 + FailReason string + ChannelID int + UPI int + Scene int + WithdrawCash int64 `json:"withdraw_cash"` +} + +type ShareNewBroadcastReq struct { + Page int + Num int +} + +type ShareNewBroadcastResp struct { + List []string +} diff --git a/modules/web/values/timer.go b/modules/web/values/timer.go index 8391b72..15420f4 100644 --- a/modules/web/values/timer.go +++ b/modules/web/values/timer.go @@ -1,10 +1,31 @@ package values -import "server/common" +import ( + "server/call" + "server/common" + "server/util" + "time" +) var ( ShareTotalInviteReward int64 ShareTotalBetReward int64 ShareRank []*OneShareRank ActivitySlotsRank []*common.ActivitySlotsData + + // 分享排行榜 + ShareRankDaily []*common.ShareRank + ShareRankWeekly []*common.ShareRank + ShareRankMonthly []*common.ShareRank + ShareWithdrawBroadcast []string ) + +func LoadShareRankData() { + now := time.Now() + dayZero := util.GetZeroTime(now).Unix() + ShareRankDaily = call.GetShareRank(common.ShareRankTypeDaily, dayZero) + weekZero := util.GetWeekZeroTime(now).Unix() + ShareRankWeekly = call.GetShareRank(common.ShareRankTypeWeekly, weekZero) + monthZero := util.GetFirstDateOfMonth(now).Unix() + ShareRankMonthly = call.GetShareRank(common.ShareRankTypeMonthly, monthZero) +} diff --git a/natsClient/values.go b/natsClient/values.go index 154ed0d..818c167 100644 --- a/natsClient/values.go +++ b/natsClient/values.go @@ -20,6 +20,8 @@ const ( TopicInnerAfterSettle = "TopicInnerAfterSettle" // 玩家游戏场结算后的一些处理逻辑 TopicBroadcastAll = "TopicBroadcastAll" // 任意协议进行广播操作 TopicCustomerMsg = "TopicCustomerMsg" // 广播玩家客服消息 + + TopicInnerESBulk = "TopicInnerESBulk" // es批量写入 ) const ( diff --git a/pb/proto/inner.proto b/pb/proto/inner.proto index 7fb2d54..07a9d46 100644 --- a/pb/proto/inner.proto +++ b/pb/proto/inner.proto @@ -8,148 +8,155 @@ option go_package = "../../pb"; // 服务器内部协议 message ClientDisConnectNotify { - uint32 UserID = 1; - string SessionId = 2; + uint32 UserID = 1; + string SessionId = 2; } message ReloadGameConfig { - int32 Type = 1; - bytes Data = 2; + int32 Type = 1; + bytes Data = 2; } // 新玩家登录发布消息 message NewPlayerLogin { - int32 uid = 1; - string GateServerID = 2; - string HallServerID = 3; + int32 uid = 1; + string GateServerID = 2; + string HallServerID = 3; } message InnerBroadcast { - int32 ID = 1; - string Content = 2; - int32 Priority = 3; - int32 Frequency = 4; - int32 Interval = 5; + int32 ID = 1; + string Content = 2; + int32 Priority = 3; + int32 Frequency = 4; + int32 Interval = 5; } message InnerBroadcastAll { - uint32 ProtocolType = 1; // 主协议号 - uint32 ProtocolID = 2; // 子协议号 - bytes Data = 3; // 数据 + uint32 ProtocolType = 1; // 主协议号 + uint32 ProtocolID = 2; // 子协议号 + bytes Data = 3; // 数据 } message InnerRefreshGold { - uint32 UID = 1; - repeated CurrencyPair Pair = 2; - uint32 Event = 3; - int64 Amount = 4; // 如果是充值,代表充值金额 - string Desc = 5; + uint32 UID = 1; + repeated CurrencyPair Pair = 2; + uint32 Event = 3; + int64 Amount = 4; // 如果是充值,代表充值金额 + string Desc = 5; } message InnerRefreshMail { - repeated uint32 UIDs = 1; + repeated uint32 UIDs = 1; } // InnerStatisticsData 内部玩家数据统计 message InnerStatisticsData { - uint32 UID = 1; - uint32 Channel = 2; - bytes Data = 3; + uint32 UID = 1; + uint32 Channel = 2; + bytes Data = 3; } // InnerOnlineData 内部玩家在线统计 message InnerOnlineData { - bytes Data = 1; - string Field = 2; - int64 Time = 3; + bytes Data = 1; + string Field = 2; + int64 Time = 3; } // InnerPushRed 内部玩家红点推送 message InnerPushRed { - uint32 UID = 1; + uint32 UID = 1; } // InnerUpdateRed 内部更新玩家红点推送 message InnerUpdateRed { - uint32 UID = 1; - uint32 Num = 2; - string Module = 3; + uint32 UID = 1; + uint32 Num = 2; + string Module = 3; } // InnerPlayerData 内部更新玩家数据 message InnerPlayerData { - uint32 UID = 1; - bytes Update = 2; + uint32 UID = 1; + bytes Update = 2; } // InnerTableFee 内部更新每日台费 message InnerTableFee { - uint32 Channel = 1; - bytes Data = 2; + uint32 Channel = 1; + bytes Data = 2; } // InnerReply 内部请求回复结构 message InnerReply { - uint32 Code = 1; - string Msg = 2; + uint32 Code = 1; + string Msg = 2; } // InnerWarn 内部预警请求结构 message InnerWarn { - string ID = 1; // 预警ID - uint32 Opt = 2; // 操作类型 1新增 2修改 3删除 - bytes Content = 3; // 内容 + string ID = 1; // 预警ID + uint32 Opt = 2; // 操作类型 1新增 2修改 3删除 + bytes Content = 3; // 内容 } // InnerUpdateWarn 内部预警更新参数/确认是否触发预警请求结构 message InnerUpdateWarn { - uint32 Type = 1; // 预警类型 - uint32 Opt = 2; // 操作类型 1更新 2确认 - repeated int64 Amount = 3; // 参数 + uint32 Type = 1; // 预警类型 + uint32 Opt = 2; // 操作类型 1更新 2确认 + repeated int64 Amount = 3; // 参数 } // InnerOptPlayer 内部通知对玩家做出某些操作 message InnerOptPlayer { - uint32 UID = 1; // uid - uint32 Opt = 2; // 操作类型 1踢出玩家 + uint32 UID = 1; // uid + uint32 Opt = 2; // 操作类型 1踢出玩家 } // InnerWhiteSwitch 内部白名单更新 message InnerWhiteSwitch { - uint32 Channel = 1; // - uint32 Opt = 2; // 操作类型 1开启 2关闭 + uint32 Channel = 1; // + uint32 Opt = 2; // 操作类型 1开启 2关闭 } // InnerWaterConfig 内部通知水位配置改动 message InnerWaterConfig { - uint32 GameID = 1; // 游戏id - uint32 RoomID = 2; // 房间id + uint32 GameID = 1; // 游戏id + uint32 RoomID = 2; // 房间id } // InnerWithdrawCallback 通知某个玩家退出回调了 message InnerWithdrawCallback { - uint32 UID = 1; // 玩家id + uint32 UID = 1; // 玩家id } // InnerAfterSettle 玩家结算后逻辑 message InnerAfterSettle { - int64 UID = 1; // 玩家id - int64 ProviderID = 2; - int64 GameID = 3; - int64 TotalBet = 4; // 有效投注 - int64 OriginSettle = 5; - int64 FinalSettle = 6; - string Phone = 7; - string UUID = 8; - string Nick = 9; - string MyUUID = 10; - int64 CurrencyType = 11; - bool IsNew = 12; - int64 SubID = 13; - int64 PlayTime = 14; + int64 UID = 1; // 玩家id + int64 ProviderID = 2; + int64 GameID = 3; + int64 TotalBet = 4; // 有效投注 + int64 OriginSettle = 5; + int64 FinalSettle = 6; + string Phone = 7; + string UUID = 8; + string Nick = 9; + string MyUUID = 10; + int64 CurrencyType = 11; + bool IsNew = 12; + int64 SubID = 13; + int64 PlayTime = 14; } // 客服消息通知 message InnerCustomerMsgNotify { - uint32 UID = 1; // 玩家id + uint32 UID = 1; // 玩家id +} + +// InnerESBulk es写入 +message InnerESBulk { + string Index = 1; + string Data = 2; + string ID = 3; }