Browse Source

1. 增加 批量增减联系人标签 接口
2. 优化账号查询、退出、登录接口

boweniac 7 months ago
parent
commit
0db49c9d5e

+ 1 - 1
desc/wechat/label_relationship.api

@@ -194,7 +194,7 @@ service Wechat {
 
     // Batch Update label relationships information | 批量更新联系人所有 LabelRelationship
     @handler batchUpdateLabelRelationships
-    post /label_relationship/Batch_update_contact_labels (BatchLabelRelationshipsInfo) returns (BaseMsgResp)
+    post /label_relationship/batch_update_contact_labels (BatchLabelRelationshipsInfo) returns (BaseMsgResp)
 
     // Delete label relationship information | 删除LabelRelationship信息
     @handler deleteLabelRelationship

+ 1 - 1
internal/handler/routes.go

@@ -243,7 +243,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				},
 				{
 					Method:  http.MethodPost,
-					Path:    "/label_relationship/Batch_update_contact_labels",
+					Path:    "/label_relationship/batch_update_contact_labels",
 					Handler: label_relationship.BatchUpdateLabelRelationshipsHandler(serverCtx),
 				},
 				{

+ 72 - 7
internal/logic/Wx/get_wx_list_logic.go

@@ -2,8 +2,13 @@ package Wx
 
 import (
 	"context"
+	"math/rand"
+	"strconv"
+	"time"
+	"wechat-api/ent"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/wx"
+	"wechat-api/hook"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -31,6 +36,12 @@ func NewGetWxListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWxLi
 func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, error) {
 	organizationId := l.ctx.Value("organizationId").(uint64)
 
+	servers, err := l.svcCtx.DB.Server.Query().All(l.ctx)
+	serverSet := make(map[uint64]*ent.Server, len(servers))
+	for _, s := range servers {
+		serverSet[s.ID] = s
+	}
+
 	var predicates []predicate.Wx
 	predicates = append(predicates, wx.OrganizationIDEQ(organizationId))
 	if req.Port != nil {
@@ -53,6 +64,60 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 	resp.Data.Total = data.PageDetails.Total
 
 	for _, v := range data.List {
+		// 创建 hookClient 客户端
+		serverInfo := serverSet[v.ServerID]
+		hookClient := hook.NewHook(serverInfo.PrivateIP, serverInfo.AdminPort, v.Port)
+
+		// 获取登录状态
+		loginInfo, err := hookClient.IsLoginStatus()
+		var loginStatus uint8 = 0
+		if err != nil {
+			l.Error("退出登录失败", err)
+		} else {
+			if loginInfo.Onlinestatus == "3" {
+				loginStatus = 1
+			}
+		}
+
+		processID := v.ProcessID
+		wxid := v.Wxid
+		account := v.Account
+		nickname := v.Nickname
+		tel := v.Tel
+		headBig := v.HeadBig
+
+		if loginStatus == 1 {
+			// 如果处于登录状态,获取登录信息
+			wxInfo, _ := hookClient.GetSelfLoginInfo()
+			if err != nil {
+				l.Error("退出登录失败", err)
+			} else {
+				processID = wxInfo.ProcessID
+				wxid = wxInfo.Wxid
+				account = wxInfo.Account
+				nickname = wxInfo.Nickname
+				tel = wxInfo.Tel
+				headBig = wxInfo.HeadBig
+				_ = l.svcCtx.DB.Wx.UpdateOneID(v.ID).
+					SetNotNilStatus(&loginStatus).
+					SetNotNilProcessID(&wxInfo.ProcessID).
+					SetNotNilWxid(&wxInfo.Wxid).
+					SetNotNilAccount(&wxInfo.Account).
+					SetNotNilNickname(&wxInfo.Nickname).
+					SetNotNilTel(&wxInfo.Tel).
+					SetNotNilHeadBig(&wxInfo.HeadBig).
+					Exec(l.ctx)
+			}
+		} else {
+			if loginStatus != v.Status {
+				wxid = strconv.Itoa(rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000000))
+				_ = l.svcCtx.DB.Wx.UpdateOneID(v.ID).
+					SetNotNilStatus(&loginStatus).
+					SetWxid(wxid).
+					Exec(l.ctx)
+			}
+		}
+
 		var agent types.AgentInfo
 		if v.Edges.Agent != nil {
 			agent = types.AgentInfo{
@@ -76,16 +141,16 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
 					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
 				},
-				Status:         &v.Status,
+				Status:         &loginStatus,
 				ServerId:       &v.ServerID,
 				Port:           &v.Port,
-				ProcessId:      &v.ProcessID,
+				ProcessId:      &processID,
 				Callback:       &v.Callback,
-				Wxid:           &v.Wxid,
-				Account:        &v.Account,
-				Nickname:       &v.Nickname,
-				Tel:            &v.Tel,
-				HeadBig:        &v.HeadBig,
+				Wxid:           &wxid,
+				Account:        &account,
+				Nickname:       &nickname,
+				Tel:            &tel,
+				HeadBig:        &headBig,
 				OrganizationId: &v.OrganizationID,
 				AgentId:        &v.AgentID,
 				AgentInfo:      &agent,

+ 9 - 4
internal/logic/Wxhook/logout_logic.go

@@ -3,6 +3,9 @@ package Wxhook
 import (
 	"context"
 	"github.com/suyuan32/simple-admin-common/enum/errorcode"
+	"math/rand"
+	"strconv"
+	"time"
 	"wechat-api/hook"
 
 	"wechat-api/internal/svc"
@@ -30,21 +33,23 @@ func (l *LogoutLogic) Logout(req *types.IDReq) (resp *types.BaseMsgResp, err err
 		l.Error("查询微信信息失败", err)
 		return
 	}
-
 	serverInfo, err := l.svcCtx.DB.Server.Get(l.ctx, wxInfo.ServerID)
 	if err != nil {
 		l.Error("查询服务器信息失败", err)
 		return
 	}
-
 	hookClient := hook.NewHook(serverInfo.PrivateIP, serverInfo.AdminPort, wxInfo.Port)
 	logout, err := hookClient.Logout()
 	if err != nil {
 		l.Error("退出登录失败", err)
 		return
 	}
-
-	l.svcCtx.DB.Wx.UpdateOne(wxInfo).SetStatus(0).Save(l.ctx)
+	//  在下面生成一个随机数
+	tmpWxid := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000000)
+	l.svcCtx.DB.Wx.UpdateOne(wxInfo).
+		SetStatus(0).
+		SetWxid(strconv.Itoa(tmpWxid)).
+		Save(l.ctx)
 
 	resp = &types.BaseMsgResp{
 		Msg: logout.Msg,

+ 4 - 0
internal/logic/Wxhook/refresh_login_q_r_logic.go

@@ -3,6 +3,7 @@ package Wxhook
 import (
 	"context"
 	"github.com/zeromicro/go-zero/core/errorx"
+	"time"
 	"wechat-api/hook"
 
 	"wechat-api/internal/svc"
@@ -52,6 +53,9 @@ func (l *RefreshLoginQRLogic) RefreshLoginQR(req *types.RefreshLoginQRReq) (resp
 		}
 	}
 
+	// 间隔一秒钟
+	time.Sleep(1 * time.Second)
+
 	loginStatus, err := hookClient.IsLoginStatus()
 	if err != nil {
 		l.Error("查询登录状态失败", err)

+ 224 - 97
internal/logic/label_relationship/batch_update_label_relationships_logic.go

@@ -2,8 +2,17 @@ package label_relationship
 
 import (
 	"context"
+	"fmt"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/custom_types"
+	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/soptask"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
 
 	"github.com/zeromicro/go-zero/core/logx"
 )
@@ -22,103 +31,221 @@ func NewBatchUpdateLabelRelationshipsLogic(ctx context.Context, svcCtx *svc.Serv
 }
 
 func (l *BatchUpdateLabelRelationshipsLogic) BatchUpdateLabelRelationships(req *types.BatchLabelRelationshipsInfo) (resp *types.BaseMsgResp, err error) {
-	//organizationId := l.ctx.Value("organizationId").(uint64)
-	//// 开始事务
-	//tx, err := l.svcCtx.DB.Tx(context.Background())
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	// 遍历所有联系人
+	for _, contactId := range req.ContactIds {
+		// 开始事务
+		tx, err := l.svcCtx.DB.Tx(context.Background())
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+		// 获取联系人信息
+		c, err := tx.Contact.Query().Where(contact.ID(contactId), contact.OrganizationIDEQ(organizationId)).Only(l.ctx)
+		// 获取联系人当前已关联的标签
+		currentLabelRelationships, err := tx.LabelRelationship.Query().Where(labelrelationship.ContactID(contactId)).All(l.ctx)
+		if err != nil {
+			_ = tx.Rollback()
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+
+		// 提取当前标签ID
+		var currentLabelIds []uint64
+		for _, relationship := range currentLabelRelationships {
+			currentLabelIds = append(currentLabelIds, relationship.LabelID)
+		}
+
+		// 对比新旧标签ID,找出需要新增和移除的标签
+		changeLabelIds, finalLabelIds := compareLabelIdsForIncrement(req.LabelIds, currentLabelIds, req.UpdateType)
+		// 如果 req.UpdateType 为空,或 req.UpdateType 的值为 “all” 时
+		if req.UpdateType == -1 {
+			// 删除需要移除的标签关系
+			for _, id := range changeLabelIds {
+				_, err := tx.LabelRelationship.
+					Delete().
+					Where(
+						labelrelationship.ContactID(contactId),
+						labelrelationship.LabelID(id),
+					).
+					Exec(l.ctx)
+				if err != nil {
+					_ = tx.Rollback()
+					return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+				}
+			}
+		} else {
+			// 创建需要新增的标签关系
+			for _, id := range changeLabelIds {
+				_, _ = tx.LabelRelationship.Create().
+					SetLabelID(id).
+					SetContactID(contactId).
+					SetOrganizationID(organizationId).
+					Save(l.ctx)
+				//if err != nil {
+				//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+				//}
+			}
+		}
+
+		// 获取所有 status 为 3 且 bot_wxid_list 包含 c.wx_wxid 的 sop_task
+		sopTasks, err := tx.SopTask.Query().Where(soptask.Status(3), soptask.OrganizationIDEQ(organizationId)).All(l.ctx)
+		if err != nil {
+			_ = tx.Rollback()
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+
+		var filteredSopTasks []*ent.SopTask
+		for _, task := range sopTasks {
+			for _, botWxid := range task.BotWxidList {
+				if botWxid == c.WxWxid {
+					filteredSopTasks = append(filteredSopTasks, task)
+					break
+				}
+			}
+		}
+
+		// 获取所有 filteredSopTasks 的 sop_stages
+		var sopStages []*ent.SopStage
+		for _, task := range filteredSopTasks {
+			stages, err := task.QueryTaskStages().All(l.ctx)
+			if err != nil {
+				_ = tx.Rollback()
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+			sopStages = append(sopStages, stages...)
+		}
+		err = AddLabelRelationships(tx, sopStages, *c, finalLabelIds, organizationId, l.ctx, l.Logger)
+
+		if err != nil {
+			_ = tx.Rollback()
+			return nil, err
+		}
+		// 所有操作成功,提交事务
+		err = tx.Commit()
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}
+
+func AddLabelRelationships(tx *ent.Tx, sopStages []*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, organizationId uint64, ctx context.Context, logger logx.Logger) (err error) {
+	for _, stage := range sopStages {
+		if stage.ConditionType == 1 && isLabelIdListMatchFilter(currentLabelIds, stage.ConditionOperator, stage.ConditionList) {
+			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
+			_, err = tx.MessageRecords.Query().
+				Where(
+					messagerecords.ContactWxid(contact.Wxid),
+					messagerecords.SourceType(3),
+					messagerecords.SourceID(stage.ID),
+					messagerecords.SubSourceID(0),
+				).
+				Only(ctx)
+			if err == nil {
+				continue
+			}
+			// 判断ActionMessage是否为空
+			sourceType := 3
+			if stage.ActionMessage != nil {
+				for i, message := range stage.ActionMessage {
+					meta := custom_types.Meta{}
+					if message.Meta != nil {
+						meta.Filename = message.Meta.Filename
+					}
+					_, _ = tx.MessageRecords.Create().
+						SetNotNilBotWxid(&contact.WxWxid).
+						SetNotNilContactID(&contact.ID).
+						SetNotNilContactType(&contact.Type).
+						SetNotNilContactWxid(&contact.Wxid).
+						SetNotNilContentType(&message.Type).
+						SetNotNilContent(&message.Content).
+						SetMeta(meta).
+						SetNotNilSourceType(&sourceType).
+						SetNotNilSourceID(&stage.ID).
+						SetSubSourceID(uint64(i)).
+						SetOrganizationID(organizationId).
+						Save(ctx)
+
+					//if err != nil {
+					//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+					//}
+				}
+			}
+			if stage.ActionLabel != nil {
+				fmt.Printf("---------------stage.ActionLabel----------------: %+v\n\n", stage.ActionLabel)
+				// 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
+				var newLabelIds []uint64
+				// 创建一个映射,用于快速查找 currentLabelIds 中的元素
+				currentLabelIdSet := make(map[uint64]struct{})
+				for _, id := range currentLabelIds {
+					currentLabelIdSet[id] = struct{}{}
+				}
+
+				// 遍历 addLabelIds,找出不在 currentLabelIds 中的元素
+				for _, id := range stage.ActionLabel {
+					if _, exists := currentLabelIdSet[id]; !exists {
+						newLabelIds = append(newLabelIds, id)
+					}
+				}
+
+				if len(newLabelIds) == 0 {
+					return nil
+				}
+				// 创建需要新增的标签关系
+				fmt.Printf("---------------newLabelIds----------------: %+v\n\n", newLabelIds)
+				for _, id := range newLabelIds {
+					_, err = tx.LabelRelationship.Create().
+						SetLabelID(id).
+						SetContactID(contact.ID).
+						SetOrganizationID(organizationId).
+						Save(ctx)
+					if err != nil {
+						fmt.Printf("---------------err----------------: %+v\n\n", err)
+					}
+				}
+				// 合并 currentLabelIds 和 newLabelIds
+				currentLabelIds = append(currentLabelIds, newLabelIds...)
+				// 递归调用 AddLabelRelationships
+				_ = AddLabelRelationships(tx, sopStages, contact, currentLabelIds, organizationId, ctx, logger)
+				return
+			}
+		}
+	}
+	// 所有操作成功,提交事务
+	//err = tx.Commit()
 	//if err != nil {
-	//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
 	//}
-	//
-	//// 遍历所有联系人
-	//for _, contactId := range req.ContactIds {
-	//	// 获取联系人信息
-	//	c, err := tx.Contact.Query().Where(contact.ID(contactId), contact.OrganizationIDEQ(organizationId)).Only(l.ctx)
-	//	// 获取联系人当前已关联的标签
-	//	currentLabelRelationships, err := tx.LabelRelationship.Query().Where(labelrelationship.ContactID(contactId)).All(l.ctx)
-	//	if err != nil {
-	//		_ = tx.Rollback()
-	//		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//	}
-	//
-	//	// 提取当前标签ID
-	//	var currentLabelIds []uint64
-	//	for _, relationship := range currentLabelRelationships {
-	//		currentLabelIds = append(currentLabelIds, relationship.LabelID)
-	//	}
-	//
-	//	// 对比新旧标签ID,找出需要新增和移除的标签
-	//	addLabelIds, removeLabelIds := compareLabelIds(req.LabelIds, currentLabelIds)
-	//
-	//	// 如果 req.UpdateType 为空,或 req.UpdateType 的值为 “all” 时
-	//	if req.UpdateType == nil || *req.UpdateType == "all" {
-	//		// 删除需要移除的标签关系
-	//		for _, id := range removeLabelIds {
-	//			_, err := tx.LabelRelationship.
-	//				Delete().
-	//				Where(
-	//					labelrelationship.ContactID(*req.ContactId),
-	//					labelrelationship.LabelID(id),
-	//				).
-	//				Exec(l.ctx)
-	//			if err != nil {
-	//				_ = tx.Rollback()
-	//				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//			}
-	//		}
-	//	}
-	//
-	//	// 创建需要新增的标签关系
-	//	for _, id := range addLabelIds {
-	//		_, _ = tx.LabelRelationship.Create().
-	//			SetLabelID(id).
-	//			SetContactID(*req.ContactId).
-	//			SetOrganizationID(organizationId).
-	//			Save(l.ctx)
-	//		//if err != nil {
-	//		//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//		//}
-	//	}
-	//
-	//	// 获取所有 status 为 3 且 bot_wxid_list 包含 c.wx_wxid 的 sop_task
-	//	sopTasks, err := tx.SopTask.Query().Where(soptask.Status(3), soptask.OrganizationIDEQ(organizationId)).All(l.ctx)
-	//	if err != nil {
-	//		_ = tx.Rollback()
-	//		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//	}
-	//
-	//	var filteredSopTasks []*ent.SopTask
-	//	for _, task := range sopTasks {
-	//		for _, botWxid := range task.BotWxidList {
-	//			if botWxid == c.WxWxid {
-	//				filteredSopTasks = append(filteredSopTasks, task)
-	//				break
-	//			}
-	//		}
-	//	}
-	//
-	//	// 获取所有 filteredSopTasks 的 sop_stages
-	//	var sopStages []*ent.SopStage
-	//	for _, task := range filteredSopTasks {
-	//		stages, err := task.QueryTaskStages().All(l.ctx)
-	//		if err != nil {
-	//			_ = tx.Rollback()
-	//			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//		}
-	//		sopStages = append(sopStages, stages...)
-	//	}
-	//	err = l.AddLabelRelationships(sopStages, *c, req.LabelIds, organizationId)
-	//
-	//	if err != nil {
-	//		_ = tx.Rollback()
-	//		return nil, err
-	//	}
-	//	// 所有操作成功,提交事务
-	//	err = tx.Commit()
-	//	if err != nil {
-	//		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	//	}
-	//}
-	//
-	//return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
-	return nil, nil
+	return nil
+}
+
+// compareLabelIds compares the new label ids with the current ones and returns the ids to be added and removed
+func compareLabelIdsForIncrement(newLabelIds []uint64, currentLabelIds []uint64, updateType int) (changeLabelIds []uint64, finalLabelIds []uint64) {
+	currentLabelIdsSet := make(map[uint64]struct{}, len(currentLabelIds))
+	for _, id := range currentLabelIds {
+		currentLabelIdsSet[id] = struct{}{}
+	}
+
+	for _, id := range newLabelIds {
+		if updateType == 1 {
+			if _, ok := currentLabelIdsSet[id]; ok {
+				delete(currentLabelIdsSet, id)
+			} else {
+				changeLabelIds = append(changeLabelIds, id)
+				finalLabelIds = append(finalLabelIds, id)
+			}
+		} else {
+			if _, ok := currentLabelIdsSet[id]; ok {
+				delete(currentLabelIdsSet, id)
+				changeLabelIds = append(changeLabelIds, id)
+			}
+		}
+	}
+
+	for id := range currentLabelIdsSet {
+		finalLabelIds = append(finalLabelIds, id)
+	}
+
+	return
 }