01_user_path.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package quota
  2. import (
  3. "app/commons/core"
  4. "app/commons/model/entity"
  5. "encoding/json"
  6. "github.com/demdxx/gocast"
  7. "github.com/samber/lo"
  8. "gorm.io/datatypes"
  9. "reflect"
  10. )
  11. // 更新用户关系路径 -- 完成自测
  12. func (s *Service) userParentIdsHandler() error {
  13. // 同步用户指标表与用户表pid关系
  14. // 获取所有用户路径信息
  15. type ParentInfo struct {
  16. Id int64 `json:"id"`
  17. ParentId int64 `json:"parentId"`
  18. ParentIds datatypes.JSON `json:"parentIds"`
  19. }
  20. var rows []ParentInfo
  21. err := s.DB().Model(&entity.User{}).
  22. Select("id,parent_id,parent_ids").Scan(&rows).Error
  23. if err != nil {
  24. return err
  25. }
  26. idPidMap := make(map[int64]int64)
  27. for _, row := range rows {
  28. idPidMap[row.Id] = row.ParentId
  29. }
  30. type QuotaInfo struct {
  31. UserId int64 `json:"userId"`
  32. ParentId int64 `json:"parentId"`
  33. }
  34. var quotas []QuotaInfo
  35. err = s.DB().Model(&entity.UserQuota{}).
  36. Select("user_id,parent_id").Scan(&quotas).Error
  37. if err != nil {
  38. return err
  39. }
  40. quotaIdMap := make(map[int64]int64)
  41. for _, item := range quotas {
  42. quotaIdMap[item.UserId] = item.ParentId
  43. }
  44. count := len(rows)
  45. for i, row := range rows {
  46. if (i+1)%2000 == 0 {
  47. core.JobLog.Infof("用户更新 ParentIds 进度:%d/%d", i+1, count)
  48. }
  49. quotaPid, ok := quotaIdMap[row.Id]
  50. if !ok {
  51. continue
  52. }
  53. // tips: 如果当前上级id 与 指标用户上级ID不一致则进行修复
  54. if row.ParentId != quotaPid {
  55. err = s.DB().Model(&entity.UserQuota{}).
  56. Where("user_id", row.Id).
  57. Updates(map[string]interface{}{
  58. "parent_id": row.ParentId,
  59. }).Error
  60. if err != nil {
  61. return err
  62. }
  63. }
  64. ids := make([]int64, 0)
  65. if len(row.ParentIds) > 0 {
  66. if err := json.Unmarshal(row.ParentIds, &ids); err != nil {
  67. core.JobLog.Infof("json.Unmarshal:%s", err.Error())
  68. continue
  69. }
  70. }
  71. path := make([]int64, 0)
  72. var uid int64 // 当前用户ID
  73. var pid int64 // 当前上级ID
  74. pid = row.ParentId
  75. uid = row.Id
  76. if pid == 0 {
  77. if len(ids) == 0 {
  78. continue
  79. }
  80. jsonData, err := json.Marshal(path)
  81. if err != nil {
  82. return err
  83. }
  84. core.JobLog.Infof("原路径:%+v 新路径:%+v", ids, []int64{})
  85. err = s.DB().Model(&entity.User{}).
  86. Where("id", uid).
  87. Updates(map[string]interface{}{
  88. "parent_ids": jsonData,
  89. }).Error
  90. if err != nil {
  91. return err
  92. }
  93. continue
  94. }
  95. // 上级不存在则跳过 同时 路径发生了变化则修改
  96. // 遍历找出上级
  97. for {
  98. path = append(path, pid)
  99. // 通过映射查找出 当前上级ID
  100. value, exists := idPidMap[pid]
  101. if !exists {
  102. break
  103. }
  104. if value == 0 {
  105. break
  106. }
  107. // 防止死循环
  108. if lo.Contains(path, value) {
  109. break
  110. }
  111. uid = pid
  112. pid = gocast.ToInt64(value)
  113. }
  114. // 可优化为原生批量修改
  115. if !reflect.DeepEqual(ids, path) {
  116. jsonData, err := json.Marshal(path)
  117. if err != nil {
  118. return err
  119. }
  120. core.JobLog.Infof("原路径:%+v 新路径:%+v", ids, path)
  121. err = s.DB().Model(&entity.User{}).
  122. Where("id", row.Id).
  123. Updates(map[string]interface{}{
  124. "parent_ids": jsonData,
  125. }).Error
  126. if err != nil {
  127. return err
  128. }
  129. }
  130. }
  131. core.JobLog.Infof("更新所有用户PATH 用户总数:%d 信息完成", count)
  132. return nil
  133. }