changed_logs.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. package service
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "gadmin/config"
  6. "gadmin/internal/admin/consts"
  7. "gadmin/internal/admin/data"
  8. "gadmin/internal/admin/forms"
  9. "gadmin/internal/elastic/eapi"
  10. "gadmin/internal/gorm/model"
  11. "gadmin/internal/gorm/query"
  12. "gadmin/utility"
  13. "gadmin/utility/serializer"
  14. "github.com/gin-gonic/gin"
  15. "github.com/sirupsen/logrus"
  16. "os"
  17. "sort"
  18. )
  19. var ChangedLogs = new(sChangedLogs)
  20. type sChangedLogs struct{}
  21. func (s *sChangedLogs) ItemRanking(ctx *gin.Context, req forms.ItemRankingReq) serializer.Response {
  22. type mods struct {
  23. ID int64 `json:"id"`
  24. UserId int64 `json:"user_id"`
  25. T int64 `json:"total"`
  26. NickName string `json:"nickName"`
  27. Source int64 `json:"source"`
  28. }
  29. var (
  30. where eapi.M
  31. index = fmt.Sprintf("%s%s", os.Getenv("ELASTIC_TOPIC"), "changed_logs_*")
  32. lists []*mods
  33. )
  34. must := []eapi.M{
  35. {
  36. "term": eapi.M{
  37. "source": req.Source,
  38. },
  39. },
  40. {
  41. "range": eapi.M{
  42. "times": eapi.M{
  43. "gt": 0,
  44. },
  45. },
  46. },
  47. }
  48. if req.ServerId > 0 {
  49. must = append(must, eapi.M{
  50. "term": eapi.M{
  51. "server_id": req.ServerId,
  52. },
  53. })
  54. }
  55. if len(req.Createtime) == 2 {
  56. must = append(must, eapi.M{
  57. "range": eapi.M{
  58. "time": eapi.M{
  59. "gte": req.Createtime[0],
  60. "lte": req.Createtime[1],
  61. },
  62. }})
  63. }
  64. where = eapi.M{
  65. "query": eapi.M{
  66. "bool": eapi.M{
  67. "must": must,
  68. },
  69. },
  70. }
  71. logrus.Warnf("where:%+v", utility.DumpToJSON(where))
  72. topList, err := eapi.TopSumScore(ctx, index, where, "user_id", "times", 100)
  73. if err != nil {
  74. return serializer.Err(consts.CodeParamErr, "查询出错 TopList", err)
  75. }
  76. var (
  77. models forms.ListRes
  78. )
  79. for i := 0; i < len(topList); i++ {
  80. v := new(mods)
  81. v.ID = int64(i + 1)
  82. v.UserId = topList[i].Key
  83. v.T = int64(topList[i].SumScore.Value)
  84. v.Source = req.Source
  85. user := data.GetUser(v.UserId)
  86. if user != nil {
  87. v.NickName = user.NickName
  88. }
  89. lists = append(lists, v)
  90. }
  91. models.List = lists
  92. models.Page = req.Page
  93. models.PerPage = req.PerPage
  94. models.PageCount = 0
  95. return serializer.Suc(models)
  96. }
  97. func (s *sChangedLogs) DiamondRanking(ctx *gin.Context, req forms.DiamondRankingReq) serializer.Response {
  98. type Result struct {
  99. ID int64 `json:"id"`
  100. UserId int64 `json:"user_id"`
  101. T int64 `json:"total"`
  102. NickName string `json:"nickName"`
  103. RechargeAmount float64 `json:"rechargeAmount"`
  104. }
  105. type Counter struct {
  106. Total float64 `json:"total"`
  107. }
  108. var (
  109. models forms.ListRes
  110. field = "expend_diamond"
  111. offset int64 = 0
  112. result []Result
  113. count int64 = 0
  114. )
  115. if req.Type == 2 {
  116. field = "expend_coin"
  117. }
  118. req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
  119. countSql := fmt.Sprintf("SELECT sum(`%v`) as t FROM `changed_player` WHERE `%v` < 0", field, field)
  120. if req.ServerId > 0 {
  121. countSql = fmt.Sprintf(countSql+" and server_id = %v", req.ServerId)
  122. }
  123. countSql = countSql + " GROUP BY `playerid` ORDER BY t ASC"
  124. config.DB.Raw(countSql).Count(&count)
  125. if count > 0 {
  126. listSql := fmt.Sprintf("SELECT `playerid` as user_id,sum(`%v`) as t FROM `changed_player` WHERE `%v` < 0", field, field)
  127. if req.ServerId > 0 {
  128. listSql = fmt.Sprintf(listSql+" and server_id = %v", req.ServerId)
  129. }
  130. listSql = fmt.Sprintf("%v GROUP BY `playerid` ORDER BY t ASC LIMIT %d OFFSET %d", listSql, req.PerPage, offset)
  131. config.DB.Raw(listSql).Find(&result)
  132. for i := 0; i < len(result); i++ {
  133. result[i].ID = offset + int64(i) + 1
  134. result[i].T = result[i].T * -1
  135. user := data.GetUser(result[i].UserId)
  136. if user != nil {
  137. result[i].NickName = user.NickName
  138. }
  139. var (
  140. orderQuery = query.Use(config.DB).Order
  141. rechargeAmountCounter Counter
  142. )
  143. err := orderQuery.WithContext(ctx).Select(orderQuery.Money.Sum().As("total")).
  144. Where(orderQuery.PlayerID.Eq(result[i].UserId), orderQuery.Status.Eq(consts.OrderStateSuccess)).
  145. Scan(&rechargeAmountCounter)
  146. if err != nil {
  147. return serializer.Err(
  148. consts.CodeParamErr,
  149. "查询出错 DiamondRanking RechargeAmount count",
  150. err,
  151. )
  152. }
  153. result[i].RechargeAmount = rechargeAmountCounter.Total
  154. }
  155. }
  156. models.List = result
  157. models.Page = req.Page
  158. models.PerPage = req.PerPage
  159. models.PageCount = (count + req.PerPage - 1) / req.PerPage
  160. return serializer.Suc(models)
  161. }
  162. func (s *sChangedLogs) unionModel(ctx *gin.Context, where string) (unionALL string, err error) {
  163. type Table struct {
  164. Value string
  165. }
  166. dbName := config.GetDBName(os.Getenv("MYSQL_DSN"))
  167. var sql = "SELECT TABLE_NAME as `value` FROM information_schema.`TABLES` WHERE TABLE_SCHEMA ='" + dbName + "' AND TABLE_NAME LIKE 'changed_logs%'"
  168. tx := config.DB.Raw(sql)
  169. var tables []string
  170. if err = tx.Scan(&tables).Error; err != nil {
  171. return
  172. }
  173. logrus.Warnf("tables:%+v", tables)
  174. for k, table := range tables {
  175. if k == 0 {
  176. unionALL = fmt.Sprintf("(SELECT * FROM %s %s)", table, where)
  177. continue
  178. }
  179. unionALL += fmt.Sprintf(" UNION ALL (SELECT * FROM %s %s)", table, where)
  180. }
  181. return unionALL, nil
  182. }
  183. func (s *sChangedLogs) List(ctx *gin.Context, req forms.ChangedLogsListReq) serializer.Response {
  184. type ChangedLog struct {
  185. model.ChangedLog
  186. NickName string `json:"nickName"`
  187. }
  188. var (
  189. //c = query.Use(config.DB).PlayerChannel
  190. //q = query.Use(config.DB).ChangedLog
  191. //m = q.WithContext(ctx)
  192. offset int64 = 0
  193. models forms.UserAccountListRes
  194. lists []ChangedLog
  195. hasWhere bool
  196. where string
  197. count int64
  198. masterWhere string
  199. )
  200. if req.ServerId > 0 {
  201. if hasWhere {
  202. where += fmt.Sprintf(" and server_id = %v", req.ServerId)
  203. } else {
  204. hasWhere = true
  205. where += fmt.Sprintf(" where server_id = %v", req.ServerId)
  206. }
  207. }
  208. if len(req.Createtime) == 2 {
  209. if hasWhere {
  210. where += fmt.Sprintf(" and `time` BETWEEN %v AND %v", int32(req.Createtime[0]), int32(req.Createtime[1]))
  211. } else {
  212. hasWhere = true
  213. where += fmt.Sprintf(" where `time` BETWEEN %v AND %v", int32(req.Createtime[0]), int32(req.Createtime[1]))
  214. }
  215. }
  216. if req.Source > 0 {
  217. if hasWhere {
  218. where += fmt.Sprintf(" and source = %v", req.Source)
  219. } else {
  220. hasWhere = true
  221. where += fmt.Sprintf(" where source = %v", req.Source)
  222. }
  223. }
  224. if req.UserId > 0 {
  225. if hasWhere {
  226. where += fmt.Sprintf(" and user_id = %v", req.UserId)
  227. } else {
  228. hasWhere = true
  229. where += fmt.Sprintf(" where user_id = %v", req.UserId)
  230. }
  231. }
  232. switch req.ChannelId {
  233. case consts.ChannelIdNone:
  234. // 不选择渠道
  235. case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
  236. var cls = Channel.GetIdsByTypeToString(req.ChannelId)
  237. if hasWhere {
  238. where += fmt.Sprintf(" and channel_id in (%v)", cls)
  239. } else {
  240. hasWhere = true
  241. where += fmt.Sprintf(" where channel_id in (%v)", cls)
  242. }
  243. default:
  244. // 指定渠道
  245. if hasWhere {
  246. where += fmt.Sprintf(" and channel_id = %v", req.ChannelId)
  247. } else {
  248. hasWhere = true
  249. where += fmt.Sprintf(" where channel_id = %v", req.ChannelId)
  250. }
  251. }
  252. unionALL, err := s.unionModel(ctx, where)
  253. if err != nil {
  254. return serializer.Err(consts.CodeParamErr, "查询出错 unionModel", err)
  255. }
  256. countSql := fmt.Sprintf("SELECT count(1) FROM(%s) as a", unionALL)
  257. getSql := fmt.Sprintf("SELECT * FROM(%s) as a", unionALL)
  258. // 排序
  259. masterWhere += " ORDER BY time DESC"
  260. // 分页
  261. req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
  262. config.DB.Raw(countSql + masterWhere).Scan(&count)
  263. if count > 0 {
  264. masterWhere += fmt.Sprintf(" LIMIT %v", req.PerPage)
  265. if offset > 0 {
  266. masterWhere += fmt.Sprintf(" OFFSET %v", offset)
  267. }
  268. config.DB.Raw(getSql + masterWhere).Scan(&lists)
  269. }
  270. for k, v := range lists {
  271. user := data.GetUser(v.UserID)
  272. if user != nil {
  273. lists[k].NickName = user.NickName
  274. }
  275. }
  276. models.List = lists
  277. models.Page = req.Page
  278. models.PerPage = req.PerPage
  279. models.PageCount = (count + req.PerPage - 1) / req.PerPage
  280. return serializer.Suc(models)
  281. }
  282. type StatisticsResult struct {
  283. Type int32 `json:"type"`
  284. Source int32 `json:"source"`
  285. UserCount int `json:"user_count"`
  286. Counts int64 `json:"counts"`
  287. Amount int64 `json:"amount"`
  288. Players []int64 `json:"-"`
  289. }
  290. type StatisticsResults []*StatisticsResult
  291. func (s StatisticsResults) Len() int {
  292. return len(s)
  293. }
  294. func (s StatisticsResults) Less(i, j int) bool {
  295. return s[i].Amount < s[j].Amount
  296. }
  297. func (s StatisticsResults) Swap(i, j int) {
  298. s[i], s[j] = s[j], s[i]
  299. }
  300. // Statistics 消费统计
  301. func (s *sChangedLogs) Statistics(ctx *gin.Context, req forms.ConsumptionStatisticsReq) serializer.Response {
  302. var (
  303. q = query.Use(config.DB).ChangedStatistic
  304. m = q.WithContext(ctx)
  305. models forms.UserAccountListRes
  306. lists []*model.ChangedStatistic
  307. results StatisticsResults
  308. )
  309. if req.Type == 1 {
  310. // 钻石
  311. m = m.Where(q.Type.Eq(1))
  312. } else {
  313. // 金币
  314. m = m.Where(q.Type.Eq(2))
  315. }
  316. if req.ServerId > 0 {
  317. m = m.Where(q.ServerID.Eq(req.ServerId))
  318. }
  319. if req.Source > 0 {
  320. m = m.Where(q.Source.Eq(req.Source))
  321. }
  322. if len(req.Date) == 2 {
  323. m = m.Where(q.Date.Between(req.Date[0], req.Date[1]))
  324. }
  325. switch req.ChannelId {
  326. case consts.ChannelIdNone:
  327. // 不选择渠道
  328. case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
  329. // 所有的广告渠道
  330. m = m.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
  331. default:
  332. // 指定渠道
  333. m = m.Where(q.ChannelID.Eq(req.ChannelId))
  334. }
  335. if err := m.Scan(&lists); err != nil {
  336. return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
  337. }
  338. for _, v := range lists {
  339. var (
  340. exist bool
  341. players []int64
  342. )
  343. for _, vv := range results {
  344. if vv.Source == v.Source {
  345. exist = true
  346. vv.Amount = vv.Amount + v.Amount
  347. vv.Counts = vv.Counts + v.Counts
  348. if err := json.Unmarshal([]byte(v.Players), &players); err != nil {
  349. logrus.Warnf("json.Unmarshal err:%+v, v:%+v", err, v)
  350. return serializer.Err(consts.CodeParamErr, "json.Unmarshal err", err)
  351. }
  352. vv.Players = append(vv.Players, players...)
  353. }
  354. }
  355. if exist == false {
  356. if err := json.Unmarshal([]byte(v.Players), &players); err != nil {
  357. logrus.Warnf("json.Unmarshal2 err:%+v, v:%+v", err, v)
  358. return serializer.Err(consts.CodeParamErr, "json.Unmarshal2 err", err)
  359. }
  360. results = append(results, &StatisticsResult{
  361. Type: v.Type,
  362. Source: v.Source,
  363. Amount: v.Amount,
  364. Counts: v.Counts,
  365. Players: players,
  366. })
  367. }
  368. }
  369. for _, v := range results {
  370. v.UserCount = len(utility.UniqueInt64s(v.Players))
  371. }
  372. sort.Sort(results)
  373. models.List = results
  374. return serializer.Suc(models)
  375. }