package smdl import ( "admin/apps/game/domain/entity" "admin/apps/game/domain/projects/smdl/internal" "admin/apps/game/model" "admin/internal/errcode" dto2 "admin/internal/model/dto" "admin/lib/httpclient" "admin/lib/utils" "math" "net/url" "strconv" "time" ) type AccountHook struct { } func (hook *AccountHook) List(projectInfo *entity.Project, resource string, params *dto2.CommonListReq, fields []*dto2.CommonDtoFieldDesc, totalCount int, rows []dto2.CommonDtoValues) ( int, []*dto2.CommonDtoFieldDesc, []dto2.CommonDtoValues, error) { alisrvAddr := projectInfo.GetApiAddr() if alisrvAddr == "" { return 0, nil, nil, errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name) } serverList, err := getAllRunningServers(projectInfo) if err != nil { return 0, nil, nil, err } totalCount, reqPageServerList, err := getPaginationServerReqList(projectInfo, serverList, params, func(info *internal.ServerInfo) int { return info.TotalAccountCount }) if err != nil { return 0, nil, nil, err } // {"data":[{"account":"20250425cs01","roleList":[{"account":"20250425cs01","createAt":1745567667525,"latestLoginAt":1745567714234,"roleId":"20001000001","serverId":"20001"}],"serverId":"20001"}], // "state":{"code":2000000,"msg":"OK"}} type RspData struct { State struct { Code int `json:"code"` Msg string `json:"msg"` } `json:"state"` Data []struct { Account string `json:"account"` ServerId string `json:"serverId"` RoleList []*Role `json:"roleList"` } `json:"data"` } body := &url.Values{} for _, cond := range params.ParsedWhereConditions.Conditions { if cond.Key == "Account" { // 按账号查询 body.Set("userId", cond.Value1.(string)) break } } for _, reqServer := range reqPageServerList { body.Set("serverid", reqServer.RawInfo.ServerId) body.Set("offset", strconv.Itoa(reqServer.Offset)) body.Set("count", strconv.Itoa(reqServer.Count)) body.Set("userlist", "true") rsp := &RspData{} err := httpclient.Request(alisrvAddr+"/rolelist", "get", body, rsp) if err != nil { return 0, nil, nil, err } for _, user := range rsp.Data { userPo := &model.Account{ Account: user.Account, ServerConfId: user.ServerId, } latestLoginTime := int64(0) earliestCreateTime := int64(math.MaxInt64) for _, v := range user.RoleList { userPo.RoleIds = append(userPo.RoleIds, v.RoleId) if latestLoginTime < v.LatestLoginTime { latestLoginTime = v.LatestLoginTime } if earliestCreateTime > v.CreateTime { earliestCreateTime = v.CreateTime } } userPo.LatestLoginTime = utils.ParseUnixTimestamp2LocalTime(latestLoginTime) userPo.CreatedAt = utils.ParseUnixTimestamp2LocalTime(earliestCreateTime) et := (&entity.CommonResource{}).FromPo(userPo) rows = append(rows, et.ToCommonDto()) } } return totalCount, fields, rows, nil } type AccountDetailOrderInfo struct { ServerId string `json:"server_id"` AccountId string `json:"account_id"` RoleId string `json:"role_id"` RoleName string `json:"role_name"` Sn string `json:"sn"` ProductId string `json:"product_id"` Price int `json:"price"` PurchaseType string `json:"purchase_type"` PurchaseAt int64 `json:"purchase_at"` } func (info *AccountDetailOrderInfo) toDto() *dto2.AccountDetailOrderInfo { return &dto2.AccountDetailOrderInfo{ ServerId: info.ServerId, AccountId: info.AccountId, RoleId: info.RoleId, RoleName: info.RoleName, Sn: info.Sn, ProductId: info.ProductId, Price: info.Price, PurchaseType: info.PurchaseType, PurchaseAt: utils.ParseUnixTimestamp2LocalTime(info.PurchaseAt).Format(time.DateTime), } } type AccountDetailRoleInfo struct { Platform string `json:"platform"` // ios ad ServerId string `json:"serverId"` Name string `json:"name"` RoleId string `json:"roleId"` Level int `json:"level"` CurrencyItems []*dto2.ItemInfo `json:"item_list"` Ip string `json:"ip"` Channel string `json:"channel"` CreatedAt int64 `json:"created_at"` LastLoginTime int64 `json:"last_login_time"` OrderList []*AccountDetailOrderInfo `json:"order_list"` } func (info *AccountDetailRoleInfo) toDto() *dto2.AccountDetailRoleInfo { retInfo := &dto2.AccountDetailRoleInfo{ Platform: info.Platform, ServerId: info.ServerId, Name: info.Name, RoleId: info.RoleId, Level: info.Level, CurrencyItems: info.CurrencyItems, CreatedAt: utils.ParseUnixTimestamp2LocalTime(info.CreatedAt).Format(time.DateTime), LastLoginTime: utils.ParseUnixTimestamp2LocalTime(info.LastLoginTime).Format(time.DateTime), } totalPayAmount := 0 for _, order := range info.OrderList { totalPayAmount += order.Price retInfo.OrderList = append(retInfo.OrderList, order.toDto()) } retInfo.TotalPayAmount = totalPayAmount retInfo.TotalPayTimes = len(info.OrderList) return retInfo } type AccountDetailInfo struct { AccountId string `json:"account_id"` LoginDeviceCount int `json:"login_device_count"` RoleList []*AccountDetailRoleInfo `json:"role_list"` } func (info *AccountDetailInfo) toDto() *dto2.AccountDetailInfo { retInfo := &dto2.AccountDetailInfo{ AccountId: info.AccountId, } var earliestRole *AccountDetailRoleInfo var totalPayAmount int var totalPayCount int var firstPayAt int64 = math.MaxInt64 var lastPayAt int64 = 0 var lastLoginTime int64 = 0 for _, r := range info.RoleList { if earliestRole == nil || earliestRole.CreatedAt > r.CreatedAt { earliestRole = r } retInfo.RoleList = append(retInfo.RoleList, r.toDto()) if lastLoginTime < r.LastLoginTime { lastLoginTime = r.LastLoginTime } for _, o := range r.OrderList { if firstPayAt > o.PurchaseAt { firstPayAt = o.PurchaseAt } if lastPayAt < o.PurchaseAt { lastPayAt = o.PurchaseAt } } } retInfo.TotalPayAmount = totalPayAmount retInfo.TotalPayTimes = totalPayCount retInfo.FirstPayAt = utils.ParseUnixTimestamp2LocalTime(firstPayAt).Format(time.DateTime) retInfo.LastPayAt = utils.ParseUnixTimestamp2LocalTime(lastPayAt).Format(time.DateTime) retInfo.LastLoginTime = utils.ParseUnixTimestamp2LocalTime(lastLoginTime).Format(time.DateTime) if earliestRole != nil { retInfo.Platform = earliestRole.Platform retInfo.Channel = earliestRole.Channel retInfo.CreatedAt = utils.ParseUnixTimestamp2LocalTime(earliestRole.CreatedAt).Format(time.DateTime) retInfo.CreatedIp = earliestRole.Ip retInfo.Platform = earliestRole.Platform retInfo.Platform = earliestRole.Platform retInfo.Platform = earliestRole.Platform retInfo.Platform = earliestRole.Platform } return retInfo } func (hook *AccountHook) GetDetail(projectInfo *entity.Project, account string) (*dto2.GetAccountDetailRsp, error) { accountId := account if accountId == "" { return nil, errcode.New(errcode.ParamsInvalid, "not found account id:%v", accountId) } params := &url.Values{} allRunningServers, err := getAllRunningServers(projectInfo) if err != nil { return nil, err } roleList := make([]*AccountDetailRoleInfo, 0) for _, runningServer := range allRunningServers { params.Set("serverid", runningServer.ServerId) params.Set("userId", accountId) params.Set("userlist", "true") type RspData struct { State struct { Code int `json:"code"` Msg string `json:"msg"` } `json:"state"` Data *AccountDetailInfo `json:"data"` } detailRsp := &RspData{} err := httpclient.Request(projectInfo.GetApiAddr()+"/rolelist", "get", params, detailRsp) if err != nil { return nil, err } if detailRsp.Data == nil { continue } roleList = append(roleList, detailRsp.Data.RoleList...) } accountDetailTotal := &AccountDetailInfo{AccountId: accountId, RoleList: roleList} return &dto2.GetAccountDetailRsp{AccountInfo: accountDetailTotal.toDto()}, nil } func getPaginationServerReqList(projectInfo *entity.Project, serverInfoList internal.ServerInfoList, params *dto2.CommonListReq, queryCountField func(*internal.ServerInfo) int) ( totalCount int, reqServerInfoList []*internal.PageServerCountInfo, err error) { pageNo := params.PageNo pageLen := params.PageLen reqServerList := make([]*internal.PageServerCountInfo, 0) if specServerId, serverInfo, find := findWhereConditionSpecServer(params.ParsedWhereConditions.Conditions, serverInfoList); find { if serverInfo == nil { logServerList := make([]string, 0, len(serverInfoList)) for _, s := range serverInfoList { logServerList = append(logServerList, s.ServerId) } return 0, nil, errcode.New(errcode.GameServerNotRunning, "运行的区服列表(%+v)中没有指定的区服(%v)", logServerList, specServerId) } // 前端检索条件指定了区服 totalCount = queryCountField(serverInfo) offset := (pageNo - 1) * pageLen limit := pageLen reqServerList = append(reqServerList, &internal.PageServerCountInfo{ RawInfo: serverInfo, Offset: offset, Count: limit, }) } else { // 根据分页参数计算需要几个区服数据参与查询 totalCountTmp, tidyPageInfoList := serverInfoList.TidyToPageList(pageLen, queryCountField) if len(tidyPageInfoList) == 0 { // 没有找到分页信息,返回空表 return 0, nil, nil } totalCount = totalCountTmp for i, tidyPageInfo := range tidyPageInfoList { if i+1 == pageNo { reqServerList = append(reqServerList, tidyPageInfo.ServerList...) break } } } return totalCount, reqServerList, nil } func findWhereConditionSpecServer(whereConditions []*dto2.GetWhereCondition, serverInfoList internal.ServerInfoList) (string, *internal.ServerInfo, bool) { if len(whereConditions) > 1 { // 第一个是ProjectId条件 for _, cond := range whereConditions { if cond.Key == "ServerConfId" { specServerId := cond.Value1.(string) // 前端指定了查询某个区服的数据 for _, v := range serverInfoList { if v.ServerId == specServerId { return v.ServerId, v, true } } return specServerId, nil, true } } } return "", nil, false }