userBehavior.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. package service
  2. import (
  3. "bufio"
  4. "designs/config"
  5. "designs/global"
  6. "designs/model"
  7. "designs/utils"
  8. "fmt"
  9. "os"
  10. "path/filepath"
  11. "strconv"
  12. "strings"
  13. "time"
  14. )
  15. var timeDuration = []string{
  16. "00.00",
  17. "01.00",
  18. "02.00",
  19. "03.00",
  20. "04.00",
  21. "05.00",
  22. "06.00",
  23. "07.00",
  24. "08.00",
  25. "09.00",
  26. "10.00",
  27. "11.00",
  28. "12.00",
  29. "13.00",
  30. "14.00",
  31. "15.00",
  32. "16.00",
  33. "17.00",
  34. "18.00",
  35. "19.00",
  36. "20.00",
  37. "21.00",
  38. "22.00",
  39. "23.00",
  40. }
  41. // 获取新增用户的时段信息
  42. func GetRegisterTimeDistribution(pf string, gid string) (map[string]int, map[string]int, int64, int64, int64, error) {
  43. now := time.Now()
  44. today := now.Format("2006-01-02")
  45. hours := utils.GetDayHour(now)
  46. var todayRegister []time.Time
  47. //计算今日曲线
  48. err := global.App.DB.Table("user").
  49. Where("pf", pf).
  50. Where("gid", gid).
  51. Where("createdAt", ">", today).
  52. Pluck("createdAt", &todayRegister).Error
  53. if err != nil {
  54. global.App.Log.Error(err.Error())
  55. return nil, nil, 0, 0, 0, err
  56. }
  57. todayCount := len(todayRegister)
  58. todayTimeDistribution := getTimeDistribution(todayRegister, hours)
  59. //计算昨日曲线
  60. var yesterdayRegister []time.Time
  61. yesterdayHours := utils.GetDayHour(now.AddDate(0, 0, -1))
  62. yesterday := now.AddDate(0, 0, -1).Format("2006-01-02")
  63. yesterdayThisTime := now.AddDate(0, 0, -1).Format("2006-01-02 15:04:05")
  64. err = global.App.DB.Table("user").
  65. Where("pf", pf).
  66. Where("gid", gid).
  67. Where("createdAt", ">", yesterday).
  68. Where("createdAt", "<=", today).
  69. Pluck("createdAt", &yesterdayRegister).Error
  70. if err != nil {
  71. global.App.Log.Error(err.Error())
  72. return nil, nil, 0, 0, 0, err
  73. }
  74. yesterdayCount := len(yesterdayRegister)
  75. yesterdayTimeDistribution := getTimeDistribution(yesterdayRegister, yesterdayHours)
  76. var yesterdayThisTimeCount int64
  77. err = global.App.DB.Table("user").
  78. Where("pf", pf).
  79. Where("gid", gid).
  80. Where("createdAt", ">", yesterday).
  81. Where("createdAt", "<=", yesterdayThisTime).
  82. Count(&yesterdayThisTimeCount).Error
  83. if err != nil {
  84. global.App.Log.Error(err.Error())
  85. return nil, nil, 0, 0, 0, err
  86. }
  87. todayTimeDistributionRes := make(map[string]int)
  88. for k, v := range todayTimeDistribution {
  89. todayTimeDistributionRes[timeDuration[k]] = v
  90. }
  91. yesterdayTimeDistributionRes := make(map[string]int)
  92. for k, v := range yesterdayTimeDistribution {
  93. yesterdayTimeDistributionRes[timeDuration[k]] = v
  94. }
  95. return todayTimeDistributionRes, yesterdayTimeDistributionRes, int64(yesterdayCount), int64(todayCount), yesterdayThisTimeCount, nil
  96. }
  97. // 活跃用户的时段信息
  98. func GetActiveTimeDistribution(pf string, gid string) (map[string]int, map[string]int, int64, int64, int64, error) {
  99. now := time.Now()
  100. today := now.Format("2006-01-02")
  101. hours := utils.GetDayHour(now)
  102. var todayRegisterModel []model.UserLogin
  103. //计算今日曲线
  104. err := global.App.DB.Table("user_login").
  105. Where("pf", pf).
  106. Where("gid", gid).
  107. Where("loginTime", ">", today).
  108. Select("userId", "loginTime").
  109. Scan(&todayRegisterModel).Error
  110. if err != nil {
  111. global.App.Log.Error(err.Error())
  112. return nil, nil, 0, 0, 0, err
  113. }
  114. todayRegister := distinctUserHour(todayRegisterModel)
  115. var todayCount int64
  116. err = global.App.DB.Table("user_login").
  117. Where("pf", pf).
  118. Where("gid", gid).
  119. Where("loginTime", ">", today).
  120. Group("userId").Count(&todayCount).Error
  121. if err != nil {
  122. global.App.Log.Error(err.Error())
  123. return nil, nil, 0, 0, 0, err
  124. }
  125. todayTimeDistribution := getTimeDistribution(todayRegister, hours)
  126. //计算昨日曲线
  127. //var yesterdayRegister []time.Time
  128. var yesterdayRegisterModel []model.UserLogin
  129. yesterdayHours := utils.GetDayHour(now.AddDate(0, 0, -1))
  130. yesterday := now.AddDate(0, 0, -1).Format("2006-01-02")
  131. yesterdayThisTime := now.AddDate(0, 0, -1).Format("2006-01-02 15:04:05")
  132. err = global.App.DB.Table("user_login").
  133. Where("pf", pf).
  134. Where("gid", gid).
  135. Where("loginTime", ">", yesterday).
  136. Where("loginTime", "<=", today).
  137. Select("userId", "loginTime").
  138. Scan(&yesterdayRegisterModel).Error
  139. if err != nil {
  140. global.App.Log.Error(err.Error())
  141. return nil, nil, 0, 0, 0, err
  142. }
  143. var yesterdayCount int64
  144. err = global.App.DB.Table("user_login").
  145. Where("pf", pf).
  146. Where("gid", gid).
  147. Where("loginTime", ">", yesterday).
  148. Where("loginTime", "<=", today).
  149. Group("userId").Count(&yesterdayCount).Error
  150. if err != nil {
  151. global.App.Log.Error(err.Error())
  152. return nil, nil, 0, 0, 0, err
  153. }
  154. var yesterdayThisTimeCount int64
  155. err = global.App.DB.Table("user_login").
  156. Where("pf", pf).
  157. Where("gid", gid).
  158. Where("loginTime", ">", yesterday).
  159. Where("loginTime", "<=", yesterdayThisTime).
  160. Group("userId").Count(&yesterdayCount).Error
  161. if err != nil {
  162. global.App.Log.Error(err.Error())
  163. return nil, nil, 0, 0, 0, err
  164. }
  165. yesterdayRegister := distinctUserHour(yesterdayRegisterModel)
  166. yesterdayTimeDistribution := getTimeDistribution(yesterdayRegister, yesterdayHours)
  167. todayTimeDistributionRes := make(map[string]int)
  168. for k, v := range todayTimeDistribution {
  169. todayTimeDistributionRes[timeDuration[k]] = v
  170. }
  171. yesterdayTimeDistributionRes := make(map[string]int)
  172. for k, v := range yesterdayTimeDistribution {
  173. yesterdayTimeDistributionRes[timeDuration[k]] = v
  174. }
  175. return todayTimeDistributionRes, yesterdayTimeDistributionRes, yesterdayCount, todayCount, yesterdayThisTimeCount, nil
  176. }
  177. // 启动次数的时段信息
  178. func GetActionDistribution(pf string, gid string) (map[string]int, map[string]int, int64, int64, int64, error) {
  179. now := time.Now()
  180. today := now.Format("2006-01-02")
  181. hours := utils.GetDayHour(now)
  182. var todayRegisterModel []time.Time
  183. //计算今日曲线
  184. err := global.App.DB.Table("user_login").
  185. Where("pf", pf).
  186. Where("gid", gid).
  187. Where("loginTime", ">", today).
  188. Select("userId", "loginTime").
  189. Pluck("loginTime", &todayRegisterModel).Error
  190. if err != nil {
  191. global.App.Log.Error(err.Error())
  192. return nil, nil, 0, 0, 0, err
  193. }
  194. //todayRegister := distinctUserHour(todayRegisterModel)
  195. var todayCount int64
  196. err = global.App.DB.Table("user_login").
  197. Where("pf", pf).
  198. Where("gid", gid).
  199. Where("loginTime", ">", today).
  200. Group("userId").Count(&todayCount).Error
  201. if err != nil {
  202. global.App.Log.Error(err.Error())
  203. return nil, nil, 0, 0, 0, err
  204. }
  205. todayTimeDistribution := getTimeDistribution(todayRegisterModel, hours)
  206. //计算昨日曲线
  207. var yesterdayRegisterModel []time.Time
  208. yesterdayHours := utils.GetDayHour(now.AddDate(0, 0, -1))
  209. yesterday := now.AddDate(0, 0, -1).Format("2006-01-02")
  210. yesterdayThisTime := now.AddDate(0, 0, -1).Format("2006-01-02 15:04:05")
  211. err = global.App.DB.Table("user_login").
  212. Where("pf", pf).
  213. Where("gid", gid).
  214. Where("loginTime", ">", yesterday).
  215. Where("loginTime", "<=", today).
  216. Pluck("loginTime", &yesterdayRegisterModel).Error
  217. if err != nil {
  218. global.App.Log.Error(err.Error())
  219. return nil, nil, 0, 0, 0, err
  220. }
  221. var yesterdayCount int64
  222. err = global.App.DB.Table("user_login").
  223. Where("pf", pf).
  224. Where("gid", gid).
  225. Where("loginTime", ">", yesterday).
  226. Where("loginTime", "<=", today).
  227. Group("userId").Count(&yesterdayCount).Error
  228. if err != nil {
  229. global.App.Log.Error(err.Error())
  230. return nil, nil, 0, 0, 0, err
  231. }
  232. var yesterdayThisTimeCount int64
  233. err = global.App.DB.Table("user_login").
  234. Where("pf", pf).
  235. Where("gid", gid).
  236. Where("loginTime", ">", yesterday).
  237. Where("loginTime", "<=", yesterdayThisTime).
  238. Group("userId").Count(&yesterdayCount).Error
  239. if err != nil {
  240. global.App.Log.Error(err.Error())
  241. return nil, nil, 0, 0, 0, err
  242. }
  243. //yesterdayRegister := distinctUserHour(yesterdayRegisterModel)
  244. yesterdayTimeDistribution := getTimeDistribution(yesterdayRegisterModel, yesterdayHours)
  245. todayTimeDistributionRes := make(map[string]int)
  246. for k, v := range todayTimeDistribution {
  247. todayTimeDistributionRes[timeDuration[k]] = v
  248. }
  249. yesterdayTimeDistributionRes := make(map[string]int)
  250. for k, v := range yesterdayTimeDistribution {
  251. yesterdayTimeDistributionRes[timeDuration[k]] = v
  252. }
  253. return todayTimeDistributionRes, yesterdayTimeDistributionRes, yesterdayCount, todayCount, yesterdayThisTimeCount, nil
  254. }
  255. // 新增设备日趋势图
  256. func GetRegisterDayDistribution(pf string, gid string, startTime string, endTime string) (map[string]int, int, float32, error) {
  257. var registerDays []time.Time
  258. err := global.App.DB.Table("user").
  259. Where("gid", gid).
  260. Where("pf", pf).
  261. Where("createdAt", ">=", startTime).
  262. Where("createdAt", "<=", endTime).
  263. Pluck("createdAt", &registerDays).Error
  264. if err != nil {
  265. return nil, 0, 0, err
  266. }
  267. days := utils.GetTimeDay(startTime, endTime)
  268. todayTimeDistribution := getTimeDistribution(registerDays, days)
  269. daysFormat := utils.GetTimeDayDateFormat(startTime, endTime) //用户分别是在哪天注册的
  270. todayTimeDistributionRes := make(map[string]int)
  271. for k, day := range daysFormat {
  272. todayTimeDistributionRes[day] = todayTimeDistribution[k]
  273. }
  274. return todayTimeDistributionRes, len(registerDays), float32(len(registerDays) / len(days)), nil
  275. }
  276. // 活跃用户趋势图
  277. func GetActiveDayDistribution(pf string, gid string, startTime string, endTime string) (map[string]int, int64, float32, error) {
  278. layout := "2006-01-02 15:04:05"
  279. start, _ := time.Parse(layout, startTime)
  280. end, _ := time.Parse(layout, endTime)
  281. var dir string
  282. if config.Get("app.local") == "local" {
  283. //url = "mongodb://localhost:27017"
  284. dir = "storage"
  285. } else {
  286. dir = "/www/wwwroot/chunhao_receive/storage"
  287. }
  288. countUserList := make(map[int]bool)
  289. todayTimeDistributionRes := make(map[string]int)
  290. for currTime := start; !currTime.After(end); currTime = currTime.AddDate(0, 0, 1) {
  291. //读取对应的文件夹
  292. filePath := filepath.Join(dir, currTime.Format("2006-01-02"), fmt.Sprintf("%s_%s.txt", gid, pf))
  293. file, _ := os.Open(filePath)
  294. defer file.Close() // 确保函数结束时关闭文件
  295. // 创建 Scanner 对象
  296. scanner := bufio.NewScanner(file)
  297. res := make(map[int]bool)
  298. // 逐行读取文件内容
  299. lineNumber := 1
  300. for scanner.Scan() {
  301. line := scanner.Text() // 获取当前行内容
  302. lineNumber++
  303. //11887,2,2025-03-24 09:05:19
  304. lineSlice := strings.Split(line, ",")
  305. userId, _ := strconv.Atoi(lineSlice[0])
  306. res[userId] = true
  307. }
  308. todayTimeDistributionRes[currTime.Format("2006-01-02")] = len(res)
  309. }
  310. return todayTimeDistributionRes, int64(len(countUserList)), 0, nil
  311. }
  312. // 活跃用户周趋势图
  313. func GetActiveWeekDistribution(pf string, gid string, startTime string, endTime string) (map[string]int, int64, float32, error) {
  314. var activeDays []time.Time
  315. err := global.App.DB.Table("user_login").
  316. Where("gid", gid).
  317. Where("pf", pf).
  318. Where("loginTime", ">=", startTime).
  319. Where("loginTime", "<=", endTime).
  320. Pluck("loginTime", &activeDays).Error
  321. if err != nil {
  322. return nil, 0, 0, err
  323. }
  324. days := utils.GetTimeDay(startTime, endTime)
  325. todayTimeDistribution := getTimeDistribution(activeDays, days)
  326. daysFormat := utils.GetTimeDayDateFormat(startTime, endTime) //用户分别是在哪天注册的
  327. todayTimeDistributionRes := make(map[string]int)
  328. for k, day := range daysFormat {
  329. todayTimeDistributionRes[day] = todayTimeDistribution[k]
  330. }
  331. return todayTimeDistributionRes, 0, float32(len(activeDays) / len(days)), nil
  332. }
  333. // 活跃用户月趋势图
  334. func GetActiveMouthDistribution(pf string, gid string, startTime string, endTime string) (map[string]int, int64, float32, error) {
  335. var activeDays []time.Time
  336. err := global.App.DB.Table("user_login").
  337. Where("gid", gid).
  338. Where("pf", pf).
  339. Where("loginTime", ">=", startTime).
  340. Where("loginTime", "<=", endTime).
  341. Pluck("loginTime", &activeDays).Error
  342. if err != nil {
  343. return nil, 0, 0, err
  344. }
  345. days := utils.GetTimeDay(startTime, endTime)
  346. todayTimeDistribution := getTimeDistribution(activeDays, days)
  347. daysFormat := utils.GetTimeDayDateFormat(startTime, endTime) //用户分别是在哪天注册的
  348. todayTimeDistributionRes := make(map[string]int)
  349. for k, day := range daysFormat {
  350. todayTimeDistributionRes[day] = todayTimeDistribution[k]
  351. }
  352. return todayTimeDistributionRes, 0, float32(len(activeDays) / len(days)), nil
  353. }
  354. func GetLoginDistribution(pf string, gid string, startTime string, endTime string) (map[int]int, float32, error) {
  355. var activeDays []time.Time
  356. err := global.App.DB.Table("user_login").
  357. Where("gid", gid).
  358. Where("pf", pf).
  359. Where("loginTime", ">=", startTime).
  360. Where("loginTime", "<=", endTime).
  361. Pluck("loginTime", &activeDays).Error
  362. if err != nil {
  363. return nil, 0, err
  364. }
  365. days := utils.GetTimeDay(startTime, endTime)
  366. todayTimeDistribution := getTimeDistribution(activeDays, days)
  367. return todayTimeDistribution, float32(len(activeDays) / len(days)), nil
  368. }
  369. // 根据时段对信息进行去重(每个小时只有一条数据是有效的)
  370. func distinctUserHour(data []model.UserLogin) []time.Time {
  371. var result []time.Time
  372. check := make(map[string][]int)
  373. for _, v := range data {
  374. date := v.LoginTime.Format("15")
  375. if !utils.InArray(v.UserId, check[date]) {
  376. check[date] = append(check[date], v.UserId)
  377. result = append(result, v.LoginTime)
  378. }
  379. }
  380. return result
  381. }
  382. // 根据时间求出时段信息
  383. func getTimeDistribution(todayRegister []time.Time, hours []int64) map[int]int {
  384. todayRegisterSum := make(map[int]int)
  385. //长度为1 不需要循环
  386. if len(hours) == 1 {
  387. todayRegisterSum[0] = len(todayRegister)
  388. return todayRegisterSum
  389. }
  390. //循环获取时段信息
  391. var todayRegisterUnix []int64
  392. for _, t := range todayRegister {
  393. todayRegisterUnix = append(todayRegisterUnix, t.Unix())
  394. }
  395. for k := range hours {
  396. todayRegisterSum[k] = 0
  397. }
  398. for _, t := range todayRegisterUnix {
  399. for k := range hours {
  400. if k == 0 {
  401. if t < hours[k+1] {
  402. todayRegisterSum[0]++
  403. }
  404. } else if k == len(hours)-1 {
  405. if t > hours[k] {
  406. todayRegisterSum[len(hours)-1]++
  407. }
  408. } else {
  409. if t > hours[k] && t <= hours[k+1] {
  410. todayRegisterSum[k]++
  411. }
  412. }
  413. }
  414. }
  415. return todayRegisterSum
  416. }
  417. //// 根据日期求出分天信息
  418. //func getDayDistribution(mouthRegister []time.Time, days []int64) {
  419. // var mouthRegisterUnix []int64
  420. // for _, t := range mouthRegister {
  421. // mouthRegisterUnix = append(mouthRegisterUnix, t.Unix())
  422. // }
  423. //
  424. // mouthRegisterSum := make(map[int]int)
  425. // for k := range days {
  426. // mouthRegisterSum[k] = 0
  427. // }
  428. //
  429. // for _, t := range mouthRegisterUnix {
  430. // for k := range days {
  431. // if k == 0 {
  432. // if t < days[k+1] {
  433. // todayRegisterSum[0]++
  434. // }
  435. // } else if k == {
  436. // if t > days[k] {
  437. // todayRegisterSum[23]++
  438. // }
  439. // } else {
  440. // if t > days[k] && t <= days[k+1] {
  441. // todayRegisterSum[k]++
  442. // }
  443. // }
  444. // }
  445. // }
  446. //
  447. //
  448. //}