label_import_logic.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package label
  2. import (
  3. "context"
  4. "encoding/json"
  5. "entgo.io/ent/dialect/sql"
  6. "github.com/zeromicro/go-zero/core/errorx"
  7. "strings"
  8. "time"
  9. "wechat-api/ent"
  10. "wechat-api/ent/label"
  11. "wechat-api/internal/svc"
  12. "wechat-api/internal/types"
  13. "github.com/zeromicro/go-zero/core/logx"
  14. )
  15. type LabelImportLogic struct {
  16. logx.Logger
  17. ctx context.Context
  18. svcCtx *svc.ServiceContext
  19. }
  20. func NewLabelImportLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LabelImportLogic {
  21. return &LabelImportLogic{
  22. Logger: logx.WithContext(ctx),
  23. ctx: ctx,
  24. svcCtx: svcCtx}
  25. }
  26. func (l *LabelImportLogic) LabelImport(req *types.LabelImportReq) (resp *types.LabelImportResp, err error) {
  27. // todo: add your logic here and delete this line
  28. organizationId := l.ctx.Value("organizationId").(uint64)
  29. contentString := req.Content
  30. contentList := splitContent(contentString)
  31. if len(contentList) > 200 {
  32. return nil, errorx.NewInvalidArgumentError("有效标签数量不能超过200个")
  33. }
  34. existingLabels, err := l.svcCtx.DB.Label.Query().
  35. Where(
  36. label.NameIn(contentList...),
  37. label.OrganizationID(organizationId),
  38. ).
  39. Select(label.FieldName).
  40. All(l.ctx)
  41. if err != nil {
  42. return nil, err
  43. }
  44. //var toInsert []string
  45. existMap := make(map[string]bool, len(existingLabels))
  46. for _, tag := range existingLabels {
  47. existMap[tag.Name] = true
  48. }
  49. labelCreates := make([]*ent.LabelCreate, 0)
  50. inserted := make([]string, 0)
  51. existed := make([]string, 0)
  52. failed := make([]string, 0)
  53. insertNames := make([]string, 0) // 新增:用于失败时记录哪些尝试插入的标签
  54. for _, tag := range contentList {
  55. if existMap[tag] {
  56. existed = append(existed, tag)
  57. continue
  58. } else {
  59. labelCreates = append(labelCreates, l.svcCtx.DB.Label.Create().
  60. SetName(tag).
  61. SetType(*req.Type).
  62. SetStatus(1).
  63. SetOrganizationID(organizationId).
  64. SetFrom(1).
  65. SetMode(1).
  66. SetConditions(`{}`).
  67. SetCreatedAt(time.Now()).
  68. SetUpdatedAt(time.Now()),
  69. )
  70. }
  71. inserted = append(inserted, tag)
  72. insertNames = append(insertNames, tag) // 新增:记录本次尝试插入的标签
  73. }
  74. if len(labelCreates) > 0 {
  75. tx, err := l.svcCtx.DB.Tx(l.ctx)
  76. if err != nil {
  77. logx.Errorf("开启事务失败:%v", err)
  78. return nil, err
  79. }
  80. err = tx.Label.CreateBulk(labelCreates...).
  81. OnConflict(sql.ConflictColumns(label.FieldName, label.FieldOrganizationID)).
  82. DoNothing().
  83. Exec(l.ctx)
  84. if err != nil {
  85. rollbackErr := tx.Rollback()
  86. if rollbackErr != nil {
  87. logx.Errorf("标签插入失败,且回滚失败:%v;回滚错误:%v", err, rollbackErr)
  88. } else {
  89. logx.Errorf("标签插入失败:%v", err)
  90. }
  91. failed = insertNames
  92. jsonBad, _ := json.Marshal(insertNames)
  93. logx.Errorf("标签批量插入失败:%v,失败数据:%s", err, string(jsonBad))
  94. //return nil, err
  95. }
  96. if err := tx.Commit(); err != nil {
  97. logx.Errorf("提交事务失败:%v", err)
  98. return nil, err
  99. }
  100. }
  101. return &types.LabelImportResp{
  102. BaseDataInfo: types.BaseDataInfo{Code: 0, Msg: "success"},
  103. Data: types.LabelImportInfo{
  104. Inserted: len(inserted),
  105. Existed: len(existed),
  106. Failed: len(failed),
  107. },
  108. }, nil
  109. }
  110. // 去重 & 切分内容:
  111. func splitContent(content string) []string {
  112. // 先统一换行符为 \n
  113. content = strings.ReplaceAll(content, "\r\n", "\n")
  114. content = strings.ReplaceAll(content, "\r", "\n")
  115. // 再按 \n 分割
  116. lines := strings.Split(content, "\n")
  117. // 去除每行空格,并过滤空行
  118. unique := make(map[string]struct{})
  119. for _, line := range lines {
  120. tag := strings.TrimSpace(line)
  121. if tag != "" {
  122. unique[tag] = struct{}{}
  123. }
  124. }
  125. result := make([]string, 0, len(unique))
  126. for tag := range unique {
  127. result = append(result, tag)
  128. }
  129. return result
  130. }
  131. func nonEmptySlice(s []string) []string {
  132. if len(s) == 0 {
  133. return []string{}
  134. }
  135. return s
  136. }