Browse Source

Merge branch 'master' of git.ascrm.cn:scrm/wechat-api

DESKTOP-53URE31\USER 6 months ago
parent
commit
8af9c76c71
55 changed files with 3248 additions and 715 deletions
  1. 87 29
      crontask/send_msg.go
  2. 5 1
      desc/wechat/batch_msg.api
  3. 21 15
      desc/wechat/category.api
  4. 3 0
      desc/wechat/contact.api
  5. 18 0
      desc/wechat/employee.api
  6. 18 0
      desc/wechat/label.api
  7. 6 0
      desc/wechat/message_records.api
  8. 26 18
      desc/wechat/token.api
  9. 69 0
      desc/wechat/wx.api
  10. 24 2
      ent/batchmsg.go
  11. 16 0
      ent/batchmsg/batchmsg.go
  12. 135 0
      ent/batchmsg/where.go
  13. 156 0
      ent/batchmsg_create.go
  14. 104 0
      ent/batchmsg_update.go
  15. 2 4
      ent/client.go
  16. 1 12
      ent/messagerecords.go
  17. 0 16
      ent/messagerecords/messagerecords.go
  18. 0 55
      ent/messagerecords/where.go
  19. 2 89
      ent/messagerecords_create.go
  20. 4 68
      ent/messagerecords_update.go
  21. 14 9
      ent/migrate/schema.go
  22. 457 104
      ent/mutation.go
  23. 1 5
      ent/runtime/runtime.go
  24. 2 0
      ent/schema/batch_msg.go
  25. 1 4
      ent/schema/message_records.go
  26. 12 0
      ent/schema/wx.go
  27. 144 24
      ent/set_not_nil.go
  28. 55 0
      ent/wx.go
  29. 12 0
      ent/wx/wx.go
  30. 212 0
      ent/wx_create.go
  31. 161 0
      ent/wx_update.go
  32. 44 0
      internal/handler/Wx/get_wx_allow_block_list_handler.go
  33. 44 0
      internal/handler/Wx/update_block_and_allow_list_handler.go
  34. 44 0
      internal/handler/employee/get_employee_detail_handler.go
  35. 44 0
      internal/handler/employee/get_employee_search_handler.go
  36. 44 0
      internal/handler/employee/get_employee_search_test_handler.go
  37. 44 0
      internal/handler/label/get_label_batch_select_list_handler.go
  38. 124 75
      internal/handler/routes.go
  39. 1 1
      internal/logic/WechatServer/update_server_logic.go
  40. 10 6
      internal/logic/Wx/check_wx_logic.go
  41. 141 0
      internal/logic/Wx/get_wx_allow_block_list_logic.go
  42. 0 5
      internal/logic/Wx/get_wx_list_logic.go
  43. 53 0
      internal/logic/Wx/update_block_and_allow_list_logic.go
  44. 114 33
      internal/logic/batch_msg/create_batch_msg_logic.go
  45. 13 0
      internal/logic/batch_msg/get_batch_msg_by_id_logic.go
  46. 3 0
      internal/logic/contact/get_contact_list_logic.go
  47. 137 0
      internal/logic/employee/get_employee_detail_logic.go
  48. 9 9
      internal/logic/employee/get_employee_list_logic.go
  49. 150 0
      internal/logic/employee/get_employee_search_logic.go
  50. 150 0
      internal/logic/employee/get_employee_search_test_logic.go
  51. 81 0
      internal/logic/label/get_label_batch_select_list_logic.go
  52. 9 2
      internal/logic/message_records/get_message_records_list_logic.go
  53. 0 9
      internal/logic/sop_task/get_sop_task_record_list_logic.go
  54. 34 4
      internal/logic/sop_task/sop_task_stop_logic.go
  55. 187 116
      internal/types/types.go

+ 87 - 29
crontask/send_msg.go

@@ -4,17 +4,16 @@ import (
 	"encoding/json"
 	"net/url"
 	"path"
-	"strings"
 	"time"
 	"wechat-api/ent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/custom_types"
-	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/msg"
 	"wechat-api/ent/wx"
 	"wechat-api/hook"
+	"wechat-api/internal/utils/dberrorhandler"
 )
 
 func (l *CronTask) sendMsg() {
@@ -30,42 +29,69 @@ func (l *CronTask) sendMsg() {
 		l.Logger.Info("batch start: ", batch.BatchNo)
 		// 如果 批次 status 为 0,则先产生待发送消息
 		if batch.Status == 0 {
-			userlist := make([]*ent.Contact, 0)
-			if batch.Tag == "all" {
+			userList := make([]*ent.Contact, 0)
+			groupList := make([]*ent.Contact, 0)
+			tagMap := make(map[string][]uint64)
+			err = json.Unmarshal([]byte(batch.Tagids), &tagMap)
+			if err != nil {
+				continue
+			}
+
+			l.Logger.Infof("send_msg.go batch.Tagids = %v\n", tagMap)
+
+			var allContact, allGroup, ok bool
+			var contactTags, groupTags []uint64
+			if contactTags, ok = tagMap["contact_tag"]; ok {
+				allContact = hasAll(contactTags, 0)
+				l.Logger.Infof("contactTags=%v", contactTags)
+			}
+			if groupTags, ok = tagMap["group_tag"]; ok {
+				allGroup = hasAll(groupTags, 0)
+				l.Logger.Infof("groupTags=%v", groupTags)
+			}
+
+			var err error
+			if allContact && allGroup {
 				// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为1或2的数据
-				userlist, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(batch.Fromwxid), contact.TypeIn(1, 2)).All(l.ctx)
+				userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(batch.Fromwxid), contact.TypeIn(1, 2)).All(l.ctx)
 				if err != nil {
 					l.Logger.Errorf("userlist err: %v", err)
 					continue
 				}
 			} else {
-
-				tags := strings.Split(batch.Tag, ",")
-
-				// 获取 label 表中 name 为 tags的记录
-				labids, err := l.svcCtx.DB.Label.Query().Where(label.NameIn(tags...)).IDs(l.ctx)
-				if err != nil {
-					l.Logger.Errorf("labids err: %v", err)
-					continue
-				}
-				// 获取 label_relationship 表中,label_id 等于 labids 的 contact_id
-				labelrelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.LabelIDIn(labids...)).All(l.ctx)
-				if err != nil {
-					l.Logger.Errorf("labelrelationships err: %v", err)
-					continue
-				}
-				contact_ids := make([]uint64, 0)
-				for _, labelrelationship := range labelrelationships {
-					contact_ids = append(contact_ids, labelrelationship.ContactID)
+				if allContact { // 所有联系人
+					// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为1的数据
+					userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(batch.Fromwxid), contact.TypeEQ(1)).All(l.ctx)
+					if err != nil {
+						l.Logger.Errorf("userList err: %v", err)
+						continue
+					}
+				} else { //获取指定标签的联系人
+					userList, err = getContactList(l, contactTags, batch.Fromwxid, 1)
+					if err != nil {
+						l.Logger.Errorf("userList err: %v", err)
+						continue
+					}
 				}
-				if len(contact_ids) > 0 {
-					// 获取 contact 表中 wx_wxid 等于 req.Fromwxid 并且 id 等于 contact_ids 并且 type 为1或2 的数据
-					userlist, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(batch.Fromwxid), contact.IDIn(contact_ids...), contact.TypeIn(1, 2)).All(l.ctx)
+
+				if allGroup { //所有群
+					// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为2的数据
+					groupList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(batch.Fromwxid), contact.TypeEQ(2)).All(l.ctx)
+					if err != nil {
+						l.Logger.Errorf("groupList err: %v", err)
+						continue
+					}
+				} else { //获取指定标签的群
+					groupList, err = getContactList(l, groupTags, batch.Fromwxid, 2)
 					if err != nil {
-						l.Logger.Errorf("userlist err: %v", err)
+						l.Logger.Errorf("groupList err: %v", err)
 						continue
 					}
 				}
+
+				if len(groupList) > 0 {
+					userList = append(userList, groupList...)
+				}
 			}
 
 			// 这里是待插入到 msg 表的数据
@@ -73,14 +99,14 @@ func (l *CronTask) sendMsg() {
 
 			// 这里是把 batch.Msg 转换为 json 数组
 			msgArray := make([]custom_types.Action, 0)
-			err := json.Unmarshal([]byte(batch.Msg), &msgArray)
+			err = json.Unmarshal([]byte(batch.Msg), &msgArray)
 			l.Logger.Infof("msgArray length= %v, err:%v", len(msgArray), err)
 			if err != nil {
 				// json 解析失败
 				msgArray = make([]custom_types.Action, 0)
 			}
 
-			for _, user := range userlist {
+			for _, user := range userList {
 				// 这里改动主要是 batch_msg 目前支持批量添加图文,导致 batch_msg 的 msg 字段为 json
 				// msg 里包括文字和图片,msgtype=1 为文字, msgtype=2 为图片
 				// 每一条文字或者图片 都是一条单独的消息
@@ -221,3 +247,35 @@ func getFileName(photoUrl string) string {
 	}
 	return path.Base(u.Path)
 }
+
+func hasAll(array []uint64, target uint64) bool {
+	for _, val := range array {
+		if val == 0 {
+			return true
+		}
+	}
+	return false
+}
+
+func getContactList(l *CronTask, labels []uint64, fromWxId string, stype int) ([]*ent.Contact, error) {
+	// 获取 label_relationship 表中,label_id 等于 labids 的 contact_id
+	labelrelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.LabelIDIn(labels...)).All(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
+	contact_ids := make([]uint64, 0, len(labelrelationships))
+	for _, labelrelationship := range labelrelationships {
+		contact_ids = append(contact_ids, labelrelationship.ContactID)
+	}
+	userList := make([]*ent.Contact, 0)
+
+	if len(contact_ids) > 0 {
+		// 获取 contact 表中 wx_wxid 等于 req.Fromwxid 并且 id 等于 contact_ids 并且 type 为1或2 的数据
+		userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(fromWxId), contact.IDIn(contact_ids...), contact.TypeEQ(stype)).All(l.ctx)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
+		}
+	}
+
+	return userList, nil
+}

+ 5 - 1
desc/wechat/batch_msg.api

@@ -40,8 +40,12 @@ type (
         // 结束时间 
         StopTime  *int64 `json:"stopTime,optional"`
 
+	    // 发送时间
+		SendTime *int64 `json:"sendTime,optional"`
+
         // 标签列表
-        Labels  []string `json:"labels,optional"`
+        Labels  []uint64 `json:"labels,optional"`
+		GroupLabels  []uint64 `json:"groupLabels,optional"`
 
 		// 标签列表
 		Type  *int32 `json:"type,optional"`

+ 21 - 15
desc/wechat/category.api

@@ -46,25 +46,11 @@ type (
 )
 
 @server(
-    jwt: Auth
     group: category
-    middleware: Authority
 )
 
 service Wechat {
-    // Create category information | 创建Category
-    @handler createCategory
-    post /category/create (CategoryInfo) returns (BaseMsgResp)
-
-    // Update category information | 更新Category
-    @handler updateCategory
-    post /category/update (CategoryInfo) returns (BaseMsgResp)
-
-    // Delete category information | 删除Category信息
-    @handler deleteCategory
-    post /category/delete (IDsReq) returns (BaseMsgResp)
-
-    // Get category list | 获取Category列表
+	// Get category list | 获取Category列表
     @handler getCategoryList
     post /category/list (CategoryListReq) returns (CategoryListResp)
 
@@ -72,3 +58,23 @@ service Wechat {
     @handler getCategoryById
     post /category (IDReq) returns (CategoryInfoResp)
 }
+
+@server(
+	jwt: Auth
+	group: category
+	middleware: Authority
+)
+
+service Wechat {
+	// Create category information | 创建Category
+	@handler createCategory
+	post /category/create (CategoryInfo) returns (BaseMsgResp)
+
+	// Update category information | 更新Category
+	@handler updateCategory
+	post /category/update (CategoryInfo) returns (BaseMsgResp)
+
+	// Delete category information | 删除Category信息
+	@handler deleteCategory
+	post /category/delete (IDsReq) returns (BaseMsgResp)
+}

+ 3 - 0
desc/wechat/contact.api

@@ -34,6 +34,9 @@ type (
         // 微信账号 
         Account  *string `json:"account,optional"`
 
+        // 昵称
+        Nickname  *string `json:"nickname,optional"`
+
         // 联系人类型:1好友,2群组,3公众号,4企业微信联系人
         Type  *int `json:"type,optional"`
     }

+ 18 - 0
desc/wechat/employee.api

@@ -98,6 +98,24 @@ type (
 )
 
 @server(
+	group: employee
+)
+
+service Wechat {
+	// Get employee list | 获取Employee列表
+	@handler getEmployeeSearch
+	post /employee/search (EmployeeListReq) returns (EmployeeListResp)
+
+	// Get employee list | 获取Employee列表
+	@handler getEmployeeSearchTest
+	post /employee/search/test (EmployeeListReq) returns (EmployeeListResp)
+
+	// Get employee by ID | 通过ID获取Employee
+	@handler getEmployeeDetail
+	post /employee/detail (IDReq) returns (EmployeeInfoResp)
+}
+
+@server(
     jwt: Auth
     group: employee
     middleware: Authority

+ 18 - 0
desc/wechat/label.api

@@ -11,6 +11,20 @@ type (
         Data []LabelSelectListInfo `json:"data"`
     }
 
+    // The response data of label list | Label群发列表数据
+    LabelBatchSelectListResp {
+        BaseDataInfo
+
+        // Label list data | Label列表数据
+        Data LabelBatchSelectListData `json:"data"`
+    }
+
+    // The response data of label list | Label群发列表数据
+    LabelBatchSelectListData {
+        Contact []LabelSelectListInfo `json:"contact"`
+        Group []LabelSelectListInfo `json:"group"`
+    }
+
     // The response data of label list | Label列表数据
     LabelListResp {
         BaseDataInfo
@@ -91,6 +105,10 @@ service Wechat {
     @handler getLabelSelectList
     post /label/select_list (LabelListReq) returns (LabelSelectListResp)
 
+    // Get label select list | 获取Label群发列表
+    @handler getLabelBatchSelectList
+    post /label/batch_select_list (LabelListReq) returns (LabelBatchSelectListResp)
+
     // Get label contacts | 获取Label联系人
     @handler getLabelContacts
     post /label/contacts (LabelListReq) returns (LabelListResp)

+ 6 - 0
desc/wechat/message_records.api

@@ -74,6 +74,12 @@ type (
         // 机器人微信 id 
         BotWxid  *string `json:"botWxid,optional"`
 
+        // 消息类型:源类型 1 点发 2 群发 3 SOP 阶段 4 SOP 节点
+        SourceType  *int `json:"sourceType,optional"`
+
+        // 消息源ID:
+        SourceId  *uint64 `json:"sourceId,optional"`
+
         // 接收方微信 id 
         ContactWxid  *string `json:"contactWxid,optional"`
 

+ 26 - 18
desc/wechat/token.api

@@ -76,27 +76,35 @@ type (
 )
 
 service Wechat {
-    // Create token information | 创建Token
-    @handler createToken
-    post /token/create (TokenInfo) returns (BaseMsgResp)
+	// Check if token and mac are valid | 检查token和mac的合法性
+	@handler checkToken
+	post /token/check (CheckTokenReq) returns (CheckTokenResp)
+}
 
-    // Update token information | 更新Token
-    @handler updateToken
-    post /token/update (TokenInfo) returns (BaseMsgResp)
+@server(
+	group: token
+	jwt: Auth
+	middleware: Authority
+)
 
-    // Delete token information | 删除Token信息
-    @handler deleteToken
-    post /token/delete (IDsReq) returns (BaseMsgResp)
+service Wechat {
+	// Create token information | 创建Token
+	@handler createToken
+	post /token/third/create (TokenInfo) returns (BaseMsgResp)
 
-    // Get token list | 获取Token列表
-    @handler getTokenList
-    post /token/list (TokenListReq) returns (TokenListResp)
+	// Update token information | 更新Token
+	@handler updateToken
+	post /token/third/update (TokenInfo) returns (BaseMsgResp)
 
-    // Get token by ID | 通过ID获取Token
-    @handler getTokenById
-    post /token (IDReq) returns (TokenInfoResp)
+	// Delete token information | 删除Token信息
+	@handler deleteToken
+	post /token/third/delete (IDsReq) returns (BaseMsgResp)
 
-	// Check if token and mac are valid | 检查token和mac的合法性
-	@handler checkToken
-	post /token/check (CheckTokenReq) returns (CheckTokenResp)
+	// Get token list | 获取Token列表
+	@handler getTokenList
+	post /token/third/list (TokenListReq) returns (TokenListResp)
+
+	// Get token by ID | 通过ID获取Token
+	@handler getTokenById
+	post /token/third/detail (IDReq) returns (TokenInfoResp)
 }

+ 69 - 0
desc/wechat/wx.api

@@ -1,5 +1,6 @@
 import "../base.api"
 import "./agent.api"
+import "./label_relationship.api"
 
 type (
     // The response data of wx information | Wx信息
@@ -56,8 +57,36 @@ type (
 
         // 大模型服务密钥
         ApiKey *string `json:"apiKey,optional"`
+
+        // 白名单
+        AllowList []ContactInfo `json:"allowList,optional"`
+
+        // 群白名单
+        GroupAllowList []ContactInfo `json:"groupAllowList,optional"`
+
+        // 黑名单
+        BlockList []ContactInfo `json:"blockList,optional"`
+
+        // 群黑名单
+        GroupBlockList []ContactInfo `json:"groupBlockList,optional"`
     }
 
+    UpdateBlockAndAllowListReq {
+            BaseIDInfo
+
+            // 白名单
+            AllowList []string `json:"allowList,optional"`
+
+            // 群白名单
+            GroupAllowList []string `json:"groupAllowList,optional"`
+
+            // 黑名单
+            BlockList []string `json:"blockList,optional"`
+
+            // 群黑名单
+            GroupBlockList []string `json:"groupBlockList,optional"`
+        }
+
     // The response data of wx list | Wx列表数据
     WxListResp {
         BaseDataInfo
@@ -104,6 +133,38 @@ type (
         // Wx information | Wx数据
         Data WxInfo `json:"data"`
     }
+
+    // 获取黑白名单列表返回体
+    AllowBlockListResp {
+        BaseDataInfo
+
+        // Wx information | Wx数据
+        Data AllowBlockListRespData `json:"data"`
+    }
+
+    // AllowBlockListRespData
+    AllowBlockListRespData {
+        // 白名单
+        AllowList []*AllowBlockData `json:"allowList,optional"`
+
+        // 群白名单
+        GroupAllowList []*AllowBlockData `json:"groupAllowList,optional"`
+
+        // 黑名单
+        BlockList []*AllowBlockData `json:"blockList,optional"`
+
+        // 群黑名单
+        GroupBlockList []*AllowBlockData `json:"groupBlockList,optional"`
+    }
+
+    // AllowBlockData
+    AllowBlockData {
+        // 微信id 公众号微信ID
+        Wxid  string `json:"wxid,optional"`
+
+        // 微信昵称 群备注名称
+        Nickname  string `json:"nickname,optional"`
+    }
 )
 
 @server(
@@ -125,6 +186,10 @@ service Wechat {
     @handler updateWx
     post /wx/update (WxInfo) returns (BaseMsgResp)
 
+    // Update wx information | 更新黑白名单
+    @handler updateBlockAndAllowList
+    post /wx/updateBlockAndAllowList (UpdateBlockAndAllowListReq) returns (BaseMsgResp)
+
     // Delete wx information | 删除Wx信息
     @handler deleteWx
     post /wx/delete (IDReq) returns (BaseMsgResp)
@@ -133,6 +198,10 @@ service Wechat {
     @handler getWxList
     post /wx/list (WxListReq) returns (WxListResp)
 
+    // Get wx allow and block list | 获取黑白名单列表
+    @handler getWxAllowBlockList
+    post /wx/getWxAllowBlockList (IDReq) returns (AllowBlockListResp)
+
     // Get wx by ID | 通过ID获取Wx
     @handler getWxById
     post /wx (IDReq) returns (WxInfoResp)

+ 24 - 2
ent/batchmsg.go

@@ -35,6 +35,8 @@ type BatchMsg struct {
 	Msg string `json:"msg,omitempty"`
 	// 发送规则 all 全部 tag1,tag2 按tag发送
 	Tag string `json:"tag,omitempty"`
+	// 要发送的tagids
+	Tagids string `json:"tagids,omitempty"`
 	// 总数
 	Total int32 `json:"total,omitempty"`
 	// 成功数量
@@ -45,6 +47,8 @@ type BatchMsg struct {
 	StartTime time.Time `json:"start_time,omitempty"`
 	// 结束时间
 	StopTime time.Time `json:"stop_time,omitempty"`
+	// 发送时间
+	SendTime time.Time `json:"send_time,omitempty"`
 	// 发送类型 1-群发消息 2-群发朋友圈
 	Type int32 `json:"type,omitempty"`
 	// organization_id | 租户ID
@@ -59,9 +63,9 @@ func (*BatchMsg) scanValues(columns []string) ([]any, error) {
 		switch columns[i] {
 		case batchmsg.FieldID, batchmsg.FieldStatus, batchmsg.FieldTotal, batchmsg.FieldSuccess, batchmsg.FieldFail, batchmsg.FieldType, batchmsg.FieldOrganizationID:
 			values[i] = new(sql.NullInt64)
-		case batchmsg.FieldBatchNo, batchmsg.FieldTaskName, batchmsg.FieldFromwxid, batchmsg.FieldMsg, batchmsg.FieldTag:
+		case batchmsg.FieldBatchNo, batchmsg.FieldTaskName, batchmsg.FieldFromwxid, batchmsg.FieldMsg, batchmsg.FieldTag, batchmsg.FieldTagids:
 			values[i] = new(sql.NullString)
-		case batchmsg.FieldCreatedAt, batchmsg.FieldUpdatedAt, batchmsg.FieldDeletedAt, batchmsg.FieldStartTime, batchmsg.FieldStopTime:
+		case batchmsg.FieldCreatedAt, batchmsg.FieldUpdatedAt, batchmsg.FieldDeletedAt, batchmsg.FieldStartTime, batchmsg.FieldStopTime, batchmsg.FieldSendTime:
 			values[i] = new(sql.NullTime)
 		default:
 			values[i] = new(sql.UnknownType)
@@ -138,6 +142,12 @@ func (bm *BatchMsg) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				bm.Tag = value.String
 			}
+		case batchmsg.FieldTagids:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field tagids", values[i])
+			} else if value.Valid {
+				bm.Tagids = value.String
+			}
 		case batchmsg.FieldTotal:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field total", values[i])
@@ -168,6 +178,12 @@ func (bm *BatchMsg) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				bm.StopTime = value.Time
 			}
+		case batchmsg.FieldSendTime:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field send_time", values[i])
+			} else if value.Valid {
+				bm.SendTime = value.Time
+			}
 		case batchmsg.FieldType:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field type", values[i])
@@ -243,6 +259,9 @@ func (bm *BatchMsg) String() string {
 	builder.WriteString("tag=")
 	builder.WriteString(bm.Tag)
 	builder.WriteString(", ")
+	builder.WriteString("tagids=")
+	builder.WriteString(bm.Tagids)
+	builder.WriteString(", ")
 	builder.WriteString("total=")
 	builder.WriteString(fmt.Sprintf("%v", bm.Total))
 	builder.WriteString(", ")
@@ -258,6 +277,9 @@ func (bm *BatchMsg) String() string {
 	builder.WriteString("stop_time=")
 	builder.WriteString(bm.StopTime.Format(time.ANSIC))
 	builder.WriteString(", ")
+	builder.WriteString("send_time=")
+	builder.WriteString(bm.SendTime.Format(time.ANSIC))
+	builder.WriteString(", ")
 	builder.WriteString("type=")
 	builder.WriteString(fmt.Sprintf("%v", bm.Type))
 	builder.WriteString(", ")

+ 16 - 0
ent/batchmsg/batchmsg.go

@@ -32,6 +32,8 @@ const (
 	FieldMsg = "msg"
 	// FieldTag holds the string denoting the tag field in the database.
 	FieldTag = "tag"
+	// FieldTagids holds the string denoting the tagids field in the database.
+	FieldTagids = "tagids"
 	// FieldTotal holds the string denoting the total field in the database.
 	FieldTotal = "total"
 	// FieldSuccess holds the string denoting the success field in the database.
@@ -42,6 +44,8 @@ const (
 	FieldStartTime = "start_time"
 	// FieldStopTime holds the string denoting the stop_time field in the database.
 	FieldStopTime = "stop_time"
+	// FieldSendTime holds the string denoting the send_time field in the database.
+	FieldSendTime = "send_time"
 	// FieldType holds the string denoting the type field in the database.
 	FieldType = "type"
 	// FieldOrganizationID holds the string denoting the organization_id field in the database.
@@ -62,11 +66,13 @@ var Columns = []string{
 	FieldFromwxid,
 	FieldMsg,
 	FieldTag,
+	FieldTagids,
 	FieldTotal,
 	FieldSuccess,
 	FieldFail,
 	FieldStartTime,
 	FieldStopTime,
+	FieldSendTime,
 	FieldType,
 	FieldOrganizationID,
 }
@@ -154,6 +160,11 @@ func ByTag(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldTag, opts...).ToFunc()
 }
 
+// ByTagids orders the results by the tagids field.
+func ByTagids(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTagids, opts...).ToFunc()
+}
+
 // ByTotal orders the results by the total field.
 func ByTotal(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldTotal, opts...).ToFunc()
@@ -179,6 +190,11 @@ func ByStopTime(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldStopTime, opts...).ToFunc()
 }
 
+// BySendTime orders the results by the send_time field.
+func BySendTime(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldSendTime, opts...).ToFunc()
+}
+
 // ByType orders the results by the type field.
 func ByType(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldType, opts...).ToFunc()

+ 135 - 0
ent/batchmsg/where.go

@@ -99,6 +99,11 @@ func Tag(v string) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldTag, v))
 }
 
+// Tagids applies equality check predicate on the "tagids" field. It's identical to TagidsEQ.
+func Tagids(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldTagids, v))
+}
+
 // Total applies equality check predicate on the "total" field. It's identical to TotalEQ.
 func Total(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldTotal, v))
@@ -124,6 +129,11 @@ func StopTime(v time.Time) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldStopTime, v))
 }
 
+// SendTime applies equality check predicate on the "send_time" field. It's identical to SendTimeEQ.
+func SendTime(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldSendTime, v))
+}
+
 // Type applies equality check predicate on the "type" field. It's identical to TypeEQ.
 func Type(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldType, v))
@@ -689,6 +699,81 @@ func TagContainsFold(v string) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldContainsFold(FieldTag, v))
 }
 
+// TagidsEQ applies the EQ predicate on the "tagids" field.
+func TagidsEQ(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldTagids, v))
+}
+
+// TagidsNEQ applies the NEQ predicate on the "tagids" field.
+func TagidsNEQ(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNEQ(FieldTagids, v))
+}
+
+// TagidsIn applies the In predicate on the "tagids" field.
+func TagidsIn(vs ...string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldIn(FieldTagids, vs...))
+}
+
+// TagidsNotIn applies the NotIn predicate on the "tagids" field.
+func TagidsNotIn(vs ...string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNotIn(FieldTagids, vs...))
+}
+
+// TagidsGT applies the GT predicate on the "tagids" field.
+func TagidsGT(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGT(FieldTagids, v))
+}
+
+// TagidsGTE applies the GTE predicate on the "tagids" field.
+func TagidsGTE(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGTE(FieldTagids, v))
+}
+
+// TagidsLT applies the LT predicate on the "tagids" field.
+func TagidsLT(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLT(FieldTagids, v))
+}
+
+// TagidsLTE applies the LTE predicate on the "tagids" field.
+func TagidsLTE(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLTE(FieldTagids, v))
+}
+
+// TagidsContains applies the Contains predicate on the "tagids" field.
+func TagidsContains(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldContains(FieldTagids, v))
+}
+
+// TagidsHasPrefix applies the HasPrefix predicate on the "tagids" field.
+func TagidsHasPrefix(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldHasPrefix(FieldTagids, v))
+}
+
+// TagidsHasSuffix applies the HasSuffix predicate on the "tagids" field.
+func TagidsHasSuffix(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldHasSuffix(FieldTagids, v))
+}
+
+// TagidsIsNil applies the IsNil predicate on the "tagids" field.
+func TagidsIsNil() predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldIsNull(FieldTagids))
+}
+
+// TagidsNotNil applies the NotNil predicate on the "tagids" field.
+func TagidsNotNil() predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNotNull(FieldTagids))
+}
+
+// TagidsEqualFold applies the EqualFold predicate on the "tagids" field.
+func TagidsEqualFold(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEqualFold(FieldTagids, v))
+}
+
+// TagidsContainsFold applies the ContainsFold predicate on the "tagids" field.
+func TagidsContainsFold(v string) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldContainsFold(FieldTagids, v))
+}
+
 // TotalEQ applies the EQ predicate on the "total" field.
 func TotalEQ(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldTotal, v))
@@ -939,6 +1024,56 @@ func StopTimeNotNil() predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldNotNull(FieldStopTime))
 }
 
+// SendTimeEQ applies the EQ predicate on the "send_time" field.
+func SendTimeEQ(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldSendTime, v))
+}
+
+// SendTimeNEQ applies the NEQ predicate on the "send_time" field.
+func SendTimeNEQ(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNEQ(FieldSendTime, v))
+}
+
+// SendTimeIn applies the In predicate on the "send_time" field.
+func SendTimeIn(vs ...time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldIn(FieldSendTime, vs...))
+}
+
+// SendTimeNotIn applies the NotIn predicate on the "send_time" field.
+func SendTimeNotIn(vs ...time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNotIn(FieldSendTime, vs...))
+}
+
+// SendTimeGT applies the GT predicate on the "send_time" field.
+func SendTimeGT(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGT(FieldSendTime, v))
+}
+
+// SendTimeGTE applies the GTE predicate on the "send_time" field.
+func SendTimeGTE(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGTE(FieldSendTime, v))
+}
+
+// SendTimeLT applies the LT predicate on the "send_time" field.
+func SendTimeLT(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLT(FieldSendTime, v))
+}
+
+// SendTimeLTE applies the LTE predicate on the "send_time" field.
+func SendTimeLTE(v time.Time) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLTE(FieldSendTime, v))
+}
+
+// SendTimeIsNil applies the IsNil predicate on the "send_time" field.
+func SendTimeIsNil() predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldIsNull(FieldSendTime))
+}
+
+// SendTimeNotNil applies the NotNil predicate on the "send_time" field.
+func SendTimeNotNil() predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNotNull(FieldSendTime))
+}
+
 // TypeEQ applies the EQ predicate on the "type" field.
 func TypeEQ(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldType, v))

+ 156 - 0
ent/batchmsg_create.go

@@ -148,6 +148,20 @@ func (bmc *BatchMsgCreate) SetNillableTag(s *string) *BatchMsgCreate {
 	return bmc
 }
 
+// SetTagids sets the "tagids" field.
+func (bmc *BatchMsgCreate) SetTagids(s string) *BatchMsgCreate {
+	bmc.mutation.SetTagids(s)
+	return bmc
+}
+
+// SetNillableTagids sets the "tagids" field if the given value is not nil.
+func (bmc *BatchMsgCreate) SetNillableTagids(s *string) *BatchMsgCreate {
+	if s != nil {
+		bmc.SetTagids(*s)
+	}
+	return bmc
+}
+
 // SetTotal sets the "total" field.
 func (bmc *BatchMsgCreate) SetTotal(i int32) *BatchMsgCreate {
 	bmc.mutation.SetTotal(i)
@@ -218,6 +232,20 @@ func (bmc *BatchMsgCreate) SetNillableStopTime(t *time.Time) *BatchMsgCreate {
 	return bmc
 }
 
+// SetSendTime sets the "send_time" field.
+func (bmc *BatchMsgCreate) SetSendTime(t time.Time) *BatchMsgCreate {
+	bmc.mutation.SetSendTime(t)
+	return bmc
+}
+
+// SetNillableSendTime sets the "send_time" field if the given value is not nil.
+func (bmc *BatchMsgCreate) SetNillableSendTime(t *time.Time) *BatchMsgCreate {
+	if t != nil {
+		bmc.SetSendTime(*t)
+	}
+	return bmc
+}
+
 // SetType sets the "type" field.
 func (bmc *BatchMsgCreate) SetType(i int32) *BatchMsgCreate {
 	bmc.mutation.SetType(i)
@@ -387,6 +415,10 @@ func (bmc *BatchMsgCreate) createSpec() (*BatchMsg, *sqlgraph.CreateSpec) {
 		_spec.SetField(batchmsg.FieldTag, field.TypeString, value)
 		_node.Tag = value
 	}
+	if value, ok := bmc.mutation.Tagids(); ok {
+		_spec.SetField(batchmsg.FieldTagids, field.TypeString, value)
+		_node.Tagids = value
+	}
 	if value, ok := bmc.mutation.Total(); ok {
 		_spec.SetField(batchmsg.FieldTotal, field.TypeInt32, value)
 		_node.Total = value
@@ -407,6 +439,10 @@ func (bmc *BatchMsgCreate) createSpec() (*BatchMsg, *sqlgraph.CreateSpec) {
 		_spec.SetField(batchmsg.FieldStopTime, field.TypeTime, value)
 		_node.StopTime = value
 	}
+	if value, ok := bmc.mutation.SendTime(); ok {
+		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
+		_node.SendTime = value
+	}
 	if value, ok := bmc.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 		_node.Type = value
@@ -611,6 +647,24 @@ func (u *BatchMsgUpsert) ClearTag() *BatchMsgUpsert {
 	return u
 }
 
+// SetTagids sets the "tagids" field.
+func (u *BatchMsgUpsert) SetTagids(v string) *BatchMsgUpsert {
+	u.Set(batchmsg.FieldTagids, v)
+	return u
+}
+
+// UpdateTagids sets the "tagids" field to the value that was provided on create.
+func (u *BatchMsgUpsert) UpdateTagids() *BatchMsgUpsert {
+	u.SetExcluded(batchmsg.FieldTagids)
+	return u
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (u *BatchMsgUpsert) ClearTagids() *BatchMsgUpsert {
+	u.SetNull(batchmsg.FieldTagids)
+	return u
+}
+
 // SetTotal sets the "total" field.
 func (u *BatchMsgUpsert) SetTotal(v int32) *BatchMsgUpsert {
 	u.Set(batchmsg.FieldTotal, v)
@@ -719,6 +773,24 @@ func (u *BatchMsgUpsert) ClearStopTime() *BatchMsgUpsert {
 	return u
 }
 
+// SetSendTime sets the "send_time" field.
+func (u *BatchMsgUpsert) SetSendTime(v time.Time) *BatchMsgUpsert {
+	u.Set(batchmsg.FieldSendTime, v)
+	return u
+}
+
+// UpdateSendTime sets the "send_time" field to the value that was provided on create.
+func (u *BatchMsgUpsert) UpdateSendTime() *BatchMsgUpsert {
+	u.SetExcluded(batchmsg.FieldSendTime)
+	return u
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (u *BatchMsgUpsert) ClearSendTime() *BatchMsgUpsert {
+	u.SetNull(batchmsg.FieldSendTime)
+	return u
+}
+
 // SetType sets the "type" field.
 func (u *BatchMsgUpsert) SetType(v int32) *BatchMsgUpsert {
 	u.Set(batchmsg.FieldType, v)
@@ -980,6 +1052,27 @@ func (u *BatchMsgUpsertOne) ClearTag() *BatchMsgUpsertOne {
 	})
 }
 
+// SetTagids sets the "tagids" field.
+func (u *BatchMsgUpsertOne) SetTagids(v string) *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetTagids(v)
+	})
+}
+
+// UpdateTagids sets the "tagids" field to the value that was provided on create.
+func (u *BatchMsgUpsertOne) UpdateTagids() *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateTagids()
+	})
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (u *BatchMsgUpsertOne) ClearTagids() *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.ClearTagids()
+	})
+}
+
 // SetTotal sets the "total" field.
 func (u *BatchMsgUpsertOne) SetTotal(v int32) *BatchMsgUpsertOne {
 	return u.Update(func(s *BatchMsgUpsert) {
@@ -1106,6 +1199,27 @@ func (u *BatchMsgUpsertOne) ClearStopTime() *BatchMsgUpsertOne {
 	})
 }
 
+// SetSendTime sets the "send_time" field.
+func (u *BatchMsgUpsertOne) SetSendTime(v time.Time) *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetSendTime(v)
+	})
+}
+
+// UpdateSendTime sets the "send_time" field to the value that was provided on create.
+func (u *BatchMsgUpsertOne) UpdateSendTime() *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateSendTime()
+	})
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (u *BatchMsgUpsertOne) ClearSendTime() *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.ClearSendTime()
+	})
+}
+
 // SetType sets the "type" field.
 func (u *BatchMsgUpsertOne) SetType(v int32) *BatchMsgUpsertOne {
 	return u.Update(func(s *BatchMsgUpsert) {
@@ -1540,6 +1654,27 @@ func (u *BatchMsgUpsertBulk) ClearTag() *BatchMsgUpsertBulk {
 	})
 }
 
+// SetTagids sets the "tagids" field.
+func (u *BatchMsgUpsertBulk) SetTagids(v string) *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetTagids(v)
+	})
+}
+
+// UpdateTagids sets the "tagids" field to the value that was provided on create.
+func (u *BatchMsgUpsertBulk) UpdateTagids() *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateTagids()
+	})
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (u *BatchMsgUpsertBulk) ClearTagids() *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.ClearTagids()
+	})
+}
+
 // SetTotal sets the "total" field.
 func (u *BatchMsgUpsertBulk) SetTotal(v int32) *BatchMsgUpsertBulk {
 	return u.Update(func(s *BatchMsgUpsert) {
@@ -1666,6 +1801,27 @@ func (u *BatchMsgUpsertBulk) ClearStopTime() *BatchMsgUpsertBulk {
 	})
 }
 
+// SetSendTime sets the "send_time" field.
+func (u *BatchMsgUpsertBulk) SetSendTime(v time.Time) *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetSendTime(v)
+	})
+}
+
+// UpdateSendTime sets the "send_time" field to the value that was provided on create.
+func (u *BatchMsgUpsertBulk) UpdateSendTime() *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateSendTime()
+	})
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (u *BatchMsgUpsertBulk) ClearSendTime() *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.ClearSendTime()
+	})
+}
+
 // SetType sets the "type" field.
 func (u *BatchMsgUpsertBulk) SetType(v int32) *BatchMsgUpsertBulk {
 	return u.Update(func(s *BatchMsgUpsert) {

+ 104 - 0
ent/batchmsg_update.go

@@ -181,6 +181,26 @@ func (bmu *BatchMsgUpdate) ClearTag() *BatchMsgUpdate {
 	return bmu
 }
 
+// SetTagids sets the "tagids" field.
+func (bmu *BatchMsgUpdate) SetTagids(s string) *BatchMsgUpdate {
+	bmu.mutation.SetTagids(s)
+	return bmu
+}
+
+// SetNillableTagids sets the "tagids" field if the given value is not nil.
+func (bmu *BatchMsgUpdate) SetNillableTagids(s *string) *BatchMsgUpdate {
+	if s != nil {
+		bmu.SetTagids(*s)
+	}
+	return bmu
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (bmu *BatchMsgUpdate) ClearTagids() *BatchMsgUpdate {
+	bmu.mutation.ClearTagids()
+	return bmu
+}
+
 // SetTotal sets the "total" field.
 func (bmu *BatchMsgUpdate) SetTotal(i int32) *BatchMsgUpdate {
 	bmu.mutation.ResetTotal()
@@ -302,6 +322,26 @@ func (bmu *BatchMsgUpdate) ClearStopTime() *BatchMsgUpdate {
 	return bmu
 }
 
+// SetSendTime sets the "send_time" field.
+func (bmu *BatchMsgUpdate) SetSendTime(t time.Time) *BatchMsgUpdate {
+	bmu.mutation.SetSendTime(t)
+	return bmu
+}
+
+// SetNillableSendTime sets the "send_time" field if the given value is not nil.
+func (bmu *BatchMsgUpdate) SetNillableSendTime(t *time.Time) *BatchMsgUpdate {
+	if t != nil {
+		bmu.SetSendTime(*t)
+	}
+	return bmu
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (bmu *BatchMsgUpdate) ClearSendTime() *BatchMsgUpdate {
+	bmu.mutation.ClearSendTime()
+	return bmu
+}
+
 // SetType sets the "type" field.
 func (bmu *BatchMsgUpdate) SetType(i int32) *BatchMsgUpdate {
 	bmu.mutation.ResetType()
@@ -467,6 +507,12 @@ func (bmu *BatchMsgUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if bmu.mutation.TagCleared() {
 		_spec.ClearField(batchmsg.FieldTag, field.TypeString)
 	}
+	if value, ok := bmu.mutation.Tagids(); ok {
+		_spec.SetField(batchmsg.FieldTagids, field.TypeString, value)
+	}
+	if bmu.mutation.TagidsCleared() {
+		_spec.ClearField(batchmsg.FieldTagids, field.TypeString)
+	}
 	if value, ok := bmu.mutation.Total(); ok {
 		_spec.SetField(batchmsg.FieldTotal, field.TypeInt32, value)
 	}
@@ -506,6 +552,12 @@ func (bmu *BatchMsgUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if bmu.mutation.StopTimeCleared() {
 		_spec.ClearField(batchmsg.FieldStopTime, field.TypeTime)
 	}
+	if value, ok := bmu.mutation.SendTime(); ok {
+		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
+	}
+	if bmu.mutation.SendTimeCleared() {
+		_spec.ClearField(batchmsg.FieldSendTime, field.TypeTime)
+	}
 	if value, ok := bmu.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 	}
@@ -694,6 +746,26 @@ func (bmuo *BatchMsgUpdateOne) ClearTag() *BatchMsgUpdateOne {
 	return bmuo
 }
 
+// SetTagids sets the "tagids" field.
+func (bmuo *BatchMsgUpdateOne) SetTagids(s string) *BatchMsgUpdateOne {
+	bmuo.mutation.SetTagids(s)
+	return bmuo
+}
+
+// SetNillableTagids sets the "tagids" field if the given value is not nil.
+func (bmuo *BatchMsgUpdateOne) SetNillableTagids(s *string) *BatchMsgUpdateOne {
+	if s != nil {
+		bmuo.SetTagids(*s)
+	}
+	return bmuo
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (bmuo *BatchMsgUpdateOne) ClearTagids() *BatchMsgUpdateOne {
+	bmuo.mutation.ClearTagids()
+	return bmuo
+}
+
 // SetTotal sets the "total" field.
 func (bmuo *BatchMsgUpdateOne) SetTotal(i int32) *BatchMsgUpdateOne {
 	bmuo.mutation.ResetTotal()
@@ -815,6 +887,26 @@ func (bmuo *BatchMsgUpdateOne) ClearStopTime() *BatchMsgUpdateOne {
 	return bmuo
 }
 
+// SetSendTime sets the "send_time" field.
+func (bmuo *BatchMsgUpdateOne) SetSendTime(t time.Time) *BatchMsgUpdateOne {
+	bmuo.mutation.SetSendTime(t)
+	return bmuo
+}
+
+// SetNillableSendTime sets the "send_time" field if the given value is not nil.
+func (bmuo *BatchMsgUpdateOne) SetNillableSendTime(t *time.Time) *BatchMsgUpdateOne {
+	if t != nil {
+		bmuo.SetSendTime(*t)
+	}
+	return bmuo
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (bmuo *BatchMsgUpdateOne) ClearSendTime() *BatchMsgUpdateOne {
+	bmuo.mutation.ClearSendTime()
+	return bmuo
+}
+
 // SetType sets the "type" field.
 func (bmuo *BatchMsgUpdateOne) SetType(i int32) *BatchMsgUpdateOne {
 	bmuo.mutation.ResetType()
@@ -1010,6 +1102,12 @@ func (bmuo *BatchMsgUpdateOne) sqlSave(ctx context.Context) (_node *BatchMsg, er
 	if bmuo.mutation.TagCleared() {
 		_spec.ClearField(batchmsg.FieldTag, field.TypeString)
 	}
+	if value, ok := bmuo.mutation.Tagids(); ok {
+		_spec.SetField(batchmsg.FieldTagids, field.TypeString, value)
+	}
+	if bmuo.mutation.TagidsCleared() {
+		_spec.ClearField(batchmsg.FieldTagids, field.TypeString)
+	}
 	if value, ok := bmuo.mutation.Total(); ok {
 		_spec.SetField(batchmsg.FieldTotal, field.TypeInt32, value)
 	}
@@ -1049,6 +1147,12 @@ func (bmuo *BatchMsgUpdateOne) sqlSave(ctx context.Context) (_node *BatchMsg, er
 	if bmuo.mutation.StopTimeCleared() {
 		_spec.ClearField(batchmsg.FieldStopTime, field.TypeTime)
 	}
+	if value, ok := bmuo.mutation.SendTime(); ok {
+		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
+	}
+	if bmuo.mutation.SendTimeCleared() {
+		_spec.ClearField(batchmsg.FieldSendTime, field.TypeTime)
+	}
 	if value, ok := bmuo.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 	}

+ 2 - 4
ent/client.go

@@ -1853,14 +1853,12 @@ func (c *MessageRecordsClient) QueryMessageContact(mr *MessageRecords) *ContactQ
 
 // Hooks returns the client hooks.
 func (c *MessageRecordsClient) Hooks() []Hook {
-	hooks := c.hooks.MessageRecords
-	return append(hooks[:len(hooks):len(hooks)], messagerecords.Hooks[:]...)
+	return c.hooks.MessageRecords
 }
 
 // Interceptors returns the client interceptors.
 func (c *MessageRecordsClient) Interceptors() []Interceptor {
-	inters := c.inters.MessageRecords
-	return append(inters[:len(inters):len(inters)], messagerecords.Interceptors[:]...)
+	return c.inters.MessageRecords
 }
 
 func (c *MessageRecordsClient) mutate(ctx context.Context, m *MessageRecordsMutation) (Value, error) {

+ 1 - 12
ent/messagerecords.go

@@ -28,8 +28,6 @@ type MessageRecords struct {
 	UpdatedAt time.Time `json:"updated_at,omitempty"`
 	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
 	Status uint8 `json:"status,omitempty"`
-	// Delete Time | 删除日期
-	DeletedAt time.Time `json:"deleted_at,omitempty"`
 	// 机器人微信 id
 	BotWxid string `json:"bot_wxid,omitempty"`
 	// 联系人 id
@@ -119,7 +117,7 @@ func (*MessageRecords) scanValues(columns []string) ([]any, error) {
 			values[i] = new(sql.NullInt64)
 		case messagerecords.FieldBotWxid, messagerecords.FieldContactWxid, messagerecords.FieldContent, messagerecords.FieldErrorDetail:
 			values[i] = new(sql.NullString)
-		case messagerecords.FieldCreatedAt, messagerecords.FieldUpdatedAt, messagerecords.FieldDeletedAt, messagerecords.FieldSendTime:
+		case messagerecords.FieldCreatedAt, messagerecords.FieldUpdatedAt, messagerecords.FieldSendTime:
 			values[i] = new(sql.NullTime)
 		default:
 			values[i] = new(sql.UnknownType)
@@ -160,12 +158,6 @@ func (mr *MessageRecords) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				mr.Status = uint8(value.Int64)
 			}
-		case messagerecords.FieldDeletedAt:
-			if value, ok := values[i].(*sql.NullTime); !ok {
-				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
-			} else if value.Valid {
-				mr.DeletedAt = value.Time
-			}
 		case messagerecords.FieldBotWxid:
 			if value, ok := values[i].(*sql.NullString); !ok {
 				return fmt.Errorf("unexpected type %T for field bot_wxid", values[i])
@@ -306,9 +298,6 @@ func (mr *MessageRecords) String() string {
 	builder.WriteString("status=")
 	builder.WriteString(fmt.Sprintf("%v", mr.Status))
 	builder.WriteString(", ")
-	builder.WriteString("deleted_at=")
-	builder.WriteString(mr.DeletedAt.Format(time.ANSIC))
-	builder.WriteString(", ")
 	builder.WriteString("bot_wxid=")
 	builder.WriteString(mr.BotWxid)
 	builder.WriteString(", ")

+ 0 - 16
ent/messagerecords/messagerecords.go

@@ -5,7 +5,6 @@ package messagerecords
 import (
 	"time"
 
-	"entgo.io/ent"
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
 )
@@ -21,8 +20,6 @@ const (
 	FieldUpdatedAt = "updated_at"
 	// FieldStatus holds the string denoting the status field in the database.
 	FieldStatus = "status"
-	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
-	FieldDeletedAt = "deleted_at"
 	// FieldBotWxid holds the string denoting the bot_wxid field in the database.
 	FieldBotWxid = "bot_wxid"
 	// FieldContactID holds the string denoting the contact_id field in the database.
@@ -86,7 +83,6 @@ var Columns = []string{
 	FieldCreatedAt,
 	FieldUpdatedAt,
 	FieldStatus,
-	FieldDeletedAt,
 	FieldBotWxid,
 	FieldContactID,
 	FieldContactType,
@@ -112,14 +108,7 @@ func ValidColumn(column string) bool {
 	return false
 }
 
-// Note that the variables below are initialized by the runtime
-// package on the initialization of the application. Therefore,
-// it should be imported in the main as follows:
-//
-//	import _ "wechat-api/ent/runtime"
 var (
-	Hooks        [1]ent.Hook
-	Interceptors [1]ent.Interceptor
 	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
 	DefaultCreatedAt func() time.Time
 	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
@@ -171,11 +160,6 @@ func ByStatus(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldStatus, opts...).ToFunc()
 }
 
-// ByDeletedAt orders the results by the deleted_at field.
-func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
-	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
-}
-
 // ByBotWxid orders the results by the bot_wxid field.
 func ByBotWxid(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldBotWxid, opts...).ToFunc()

+ 0 - 55
ent/messagerecords/where.go

@@ -70,11 +70,6 @@ func Status(v uint8) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldStatus, v))
 }
 
-// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
-func DeletedAt(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldEQ(FieldDeletedAt, v))
-}
-
 // BotWxid applies equality check predicate on the "bot_wxid" field. It's identical to BotWxidEQ.
 func BotWxid(v string) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldBotWxid, v))
@@ -265,56 +260,6 @@ func StatusNotNil() predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNotNull(FieldStatus))
 }
 
-// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
-func DeletedAtEQ(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldEQ(FieldDeletedAt, v))
-}
-
-// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
-func DeletedAtNEQ(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldNEQ(FieldDeletedAt, v))
-}
-
-// DeletedAtIn applies the In predicate on the "deleted_at" field.
-func DeletedAtIn(vs ...time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldIn(FieldDeletedAt, vs...))
-}
-
-// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
-func DeletedAtNotIn(vs ...time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldNotIn(FieldDeletedAt, vs...))
-}
-
-// DeletedAtGT applies the GT predicate on the "deleted_at" field.
-func DeletedAtGT(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGT(FieldDeletedAt, v))
-}
-
-// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
-func DeletedAtGTE(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGTE(FieldDeletedAt, v))
-}
-
-// DeletedAtLT applies the LT predicate on the "deleted_at" field.
-func DeletedAtLT(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLT(FieldDeletedAt, v))
-}
-
-// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
-func DeletedAtLTE(v time.Time) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLTE(FieldDeletedAt, v))
-}
-
-// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
-func DeletedAtIsNil() predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldIsNull(FieldDeletedAt))
-}
-
-// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
-func DeletedAtNotNil() predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldNotNull(FieldDeletedAt))
-}
-
 // BotWxidEQ applies the EQ predicate on the "bot_wxid" field.
 func BotWxidEQ(v string) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldBotWxid, v))

+ 2 - 89
ent/messagerecords_create.go

@@ -68,20 +68,6 @@ func (mrc *MessageRecordsCreate) SetNillableStatus(u *uint8) *MessageRecordsCrea
 	return mrc
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (mrc *MessageRecordsCreate) SetDeletedAt(t time.Time) *MessageRecordsCreate {
-	mrc.mutation.SetDeletedAt(t)
-	return mrc
-}
-
-// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
-func (mrc *MessageRecordsCreate) SetNillableDeletedAt(t *time.Time) *MessageRecordsCreate {
-	if t != nil {
-		mrc.SetDeletedAt(*t)
-	}
-	return mrc
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (mrc *MessageRecordsCreate) SetBotWxid(s string) *MessageRecordsCreate {
 	mrc.mutation.SetBotWxid(s)
@@ -326,9 +312,7 @@ func (mrc *MessageRecordsCreate) Mutation() *MessageRecordsMutation {
 
 // Save creates the MessageRecords in the database.
 func (mrc *MessageRecordsCreate) Save(ctx context.Context) (*MessageRecords, error) {
-	if err := mrc.defaults(); err != nil {
-		return nil, err
-	}
+	mrc.defaults()
 	return withHooks(ctx, mrc.sqlSave, mrc.mutation, mrc.hooks)
 }
 
@@ -355,18 +339,12 @@ func (mrc *MessageRecordsCreate) ExecX(ctx context.Context) {
 }
 
 // defaults sets the default values of the builder before save.
-func (mrc *MessageRecordsCreate) defaults() error {
+func (mrc *MessageRecordsCreate) defaults() {
 	if _, ok := mrc.mutation.CreatedAt(); !ok {
-		if messagerecords.DefaultCreatedAt == nil {
-			return fmt.Errorf("ent: uninitialized messagerecords.DefaultCreatedAt (forgotten import ent/runtime?)")
-		}
 		v := messagerecords.DefaultCreatedAt()
 		mrc.mutation.SetCreatedAt(v)
 	}
 	if _, ok := mrc.mutation.UpdatedAt(); !ok {
-		if messagerecords.DefaultUpdatedAt == nil {
-			return fmt.Errorf("ent: uninitialized messagerecords.DefaultUpdatedAt (forgotten import ent/runtime?)")
-		}
 		v := messagerecords.DefaultUpdatedAt()
 		mrc.mutation.SetUpdatedAt(v)
 	}
@@ -410,7 +388,6 @@ func (mrc *MessageRecordsCreate) defaults() error {
 		v := messagerecords.DefaultOrganizationID
 		mrc.mutation.SetOrganizationID(v)
 	}
-	return nil
 }
 
 // check runs all checks and user-defined validators on the builder.
@@ -487,10 +464,6 @@ func (mrc *MessageRecordsCreate) createSpec() (*MessageRecords, *sqlgraph.Create
 		_spec.SetField(messagerecords.FieldStatus, field.TypeUint8, value)
 		_node.Status = value
 	}
-	if value, ok := mrc.mutation.DeletedAt(); ok {
-		_spec.SetField(messagerecords.FieldDeletedAt, field.TypeTime, value)
-		_node.DeletedAt = value
-	}
 	if value, ok := mrc.mutation.BotWxid(); ok {
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 		_node.BotWxid = value
@@ -670,24 +643,6 @@ func (u *MessageRecordsUpsert) ClearStatus() *MessageRecordsUpsert {
 	return u
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (u *MessageRecordsUpsert) SetDeletedAt(v time.Time) *MessageRecordsUpsert {
-	u.Set(messagerecords.FieldDeletedAt, v)
-	return u
-}
-
-// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
-func (u *MessageRecordsUpsert) UpdateDeletedAt() *MessageRecordsUpsert {
-	u.SetExcluded(messagerecords.FieldDeletedAt)
-	return u
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (u *MessageRecordsUpsert) ClearDeletedAt() *MessageRecordsUpsert {
-	u.SetNull(messagerecords.FieldDeletedAt)
-	return u
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (u *MessageRecordsUpsert) SetBotWxid(v string) *MessageRecordsUpsert {
 	u.Set(messagerecords.FieldBotWxid, v)
@@ -997,27 +952,6 @@ func (u *MessageRecordsUpsertOne) ClearStatus() *MessageRecordsUpsertOne {
 	})
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (u *MessageRecordsUpsertOne) SetDeletedAt(v time.Time) *MessageRecordsUpsertOne {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.SetDeletedAt(v)
-	})
-}
-
-// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
-func (u *MessageRecordsUpsertOne) UpdateDeletedAt() *MessageRecordsUpsertOne {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.UpdateDeletedAt()
-	})
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (u *MessageRecordsUpsertOne) ClearDeletedAt() *MessageRecordsUpsertOne {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.ClearDeletedAt()
-	})
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (u *MessageRecordsUpsertOne) SetBotWxid(v string) *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
@@ -1529,27 +1463,6 @@ func (u *MessageRecordsUpsertBulk) ClearStatus() *MessageRecordsUpsertBulk {
 	})
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (u *MessageRecordsUpsertBulk) SetDeletedAt(v time.Time) *MessageRecordsUpsertBulk {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.SetDeletedAt(v)
-	})
-}
-
-// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
-func (u *MessageRecordsUpsertBulk) UpdateDeletedAt() *MessageRecordsUpsertBulk {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.UpdateDeletedAt()
-	})
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (u *MessageRecordsUpsertBulk) ClearDeletedAt() *MessageRecordsUpsertBulk {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.ClearDeletedAt()
-	})
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (u *MessageRecordsUpsertBulk) SetBotWxid(v string) *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {

+ 4 - 68
ent/messagerecords_update.go

@@ -65,26 +65,6 @@ func (mru *MessageRecordsUpdate) ClearStatus() *MessageRecordsUpdate {
 	return mru
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (mru *MessageRecordsUpdate) SetDeletedAt(t time.Time) *MessageRecordsUpdate {
-	mru.mutation.SetDeletedAt(t)
-	return mru
-}
-
-// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
-func (mru *MessageRecordsUpdate) SetNillableDeletedAt(t *time.Time) *MessageRecordsUpdate {
-	if t != nil {
-		mru.SetDeletedAt(*t)
-	}
-	return mru
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (mru *MessageRecordsUpdate) ClearDeletedAt() *MessageRecordsUpdate {
-	mru.mutation.ClearDeletedAt()
-	return mru
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (mru *MessageRecordsUpdate) SetBotWxid(s string) *MessageRecordsUpdate {
 	mru.mutation.SetBotWxid(s)
@@ -413,9 +393,7 @@ func (mru *MessageRecordsUpdate) ClearMessageContact() *MessageRecordsUpdate {
 
 // Save executes the query and returns the number of nodes affected by the update operation.
 func (mru *MessageRecordsUpdate) Save(ctx context.Context) (int, error) {
-	if err := mru.defaults(); err != nil {
-		return 0, err
-	}
+	mru.defaults()
 	return withHooks(ctx, mru.sqlSave, mru.mutation, mru.hooks)
 }
 
@@ -442,15 +420,11 @@ func (mru *MessageRecordsUpdate) ExecX(ctx context.Context) {
 }
 
 // defaults sets the default values of the builder before save.
-func (mru *MessageRecordsUpdate) defaults() error {
+func (mru *MessageRecordsUpdate) defaults() {
 	if _, ok := mru.mutation.UpdatedAt(); !ok {
-		if messagerecords.UpdateDefaultUpdatedAt == nil {
-			return fmt.Errorf("ent: uninitialized messagerecords.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
-		}
 		v := messagerecords.UpdateDefaultUpdatedAt()
 		mru.mutation.SetUpdatedAt(v)
 	}
-	return nil
 }
 
 func (mru *MessageRecordsUpdate) sqlSave(ctx context.Context) (n int, err error) {
@@ -474,12 +448,6 @@ func (mru *MessageRecordsUpdate) sqlSave(ctx context.Context) (n int, err error)
 	if mru.mutation.StatusCleared() {
 		_spec.ClearField(messagerecords.FieldStatus, field.TypeUint8)
 	}
-	if value, ok := mru.mutation.DeletedAt(); ok {
-		_spec.SetField(messagerecords.FieldDeletedAt, field.TypeTime, value)
-	}
-	if mru.mutation.DeletedAtCleared() {
-		_spec.ClearField(messagerecords.FieldDeletedAt, field.TypeTime)
-	}
 	if value, ok := mru.mutation.BotWxid(); ok {
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 	}
@@ -671,26 +639,6 @@ func (mruo *MessageRecordsUpdateOne) ClearStatus() *MessageRecordsUpdateOne {
 	return mruo
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (mruo *MessageRecordsUpdateOne) SetDeletedAt(t time.Time) *MessageRecordsUpdateOne {
-	mruo.mutation.SetDeletedAt(t)
-	return mruo
-}
-
-// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
-func (mruo *MessageRecordsUpdateOne) SetNillableDeletedAt(t *time.Time) *MessageRecordsUpdateOne {
-	if t != nil {
-		mruo.SetDeletedAt(*t)
-	}
-	return mruo
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (mruo *MessageRecordsUpdateOne) ClearDeletedAt() *MessageRecordsUpdateOne {
-	mruo.mutation.ClearDeletedAt()
-	return mruo
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (mruo *MessageRecordsUpdateOne) SetBotWxid(s string) *MessageRecordsUpdateOne {
 	mruo.mutation.SetBotWxid(s)
@@ -1032,9 +980,7 @@ func (mruo *MessageRecordsUpdateOne) Select(field string, fields ...string) *Mes
 
 // Save executes the query and returns the updated MessageRecords entity.
 func (mruo *MessageRecordsUpdateOne) Save(ctx context.Context) (*MessageRecords, error) {
-	if err := mruo.defaults(); err != nil {
-		return nil, err
-	}
+	mruo.defaults()
 	return withHooks(ctx, mruo.sqlSave, mruo.mutation, mruo.hooks)
 }
 
@@ -1061,15 +1007,11 @@ func (mruo *MessageRecordsUpdateOne) ExecX(ctx context.Context) {
 }
 
 // defaults sets the default values of the builder before save.
-func (mruo *MessageRecordsUpdateOne) defaults() error {
+func (mruo *MessageRecordsUpdateOne) defaults() {
 	if _, ok := mruo.mutation.UpdatedAt(); !ok {
-		if messagerecords.UpdateDefaultUpdatedAt == nil {
-			return fmt.Errorf("ent: uninitialized messagerecords.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
-		}
 		v := messagerecords.UpdateDefaultUpdatedAt()
 		mruo.mutation.SetUpdatedAt(v)
 	}
-	return nil
 }
 
 func (mruo *MessageRecordsUpdateOne) sqlSave(ctx context.Context) (_node *MessageRecords, err error) {
@@ -1110,12 +1052,6 @@ func (mruo *MessageRecordsUpdateOne) sqlSave(ctx context.Context) (_node *Messag
 	if mruo.mutation.StatusCleared() {
 		_spec.ClearField(messagerecords.FieldStatus, field.TypeUint8)
 	}
-	if value, ok := mruo.mutation.DeletedAt(); ok {
-		_spec.SetField(messagerecords.FieldDeletedAt, field.TypeTime, value)
-	}
-	if mruo.mutation.DeletedAtCleared() {
-		_spec.ClearField(messagerecords.FieldDeletedAt, field.TypeTime)
-	}
 	if value, ok := mruo.mutation.BotWxid(); ok {
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 	}

+ 14 - 9
ent/migrate/schema.go

@@ -49,11 +49,13 @@ var (
 		{Name: "fromwxid", Type: field.TypeString, Nullable: true, Comment: "发送方微信ID"},
 		{Name: "msg", Type: field.TypeString, Nullable: true, Comment: "内容"},
 		{Name: "tag", Type: field.TypeString, Nullable: true, Comment: "发送规则 all 全部 tag1,tag2 按tag发送"},
+		{Name: "tagids", Type: field.TypeString, Nullable: true, Comment: "要发送的tagids"},
 		{Name: "total", Type: field.TypeInt32, Nullable: true, Comment: "总数"},
 		{Name: "success", Type: field.TypeInt32, Nullable: true, Comment: "成功数量"},
 		{Name: "fail", Type: field.TypeInt32, Nullable: true, Comment: "失败数量"},
 		{Name: "start_time", Type: field.TypeTime, Nullable: true, Comment: "开始时间"},
 		{Name: "stop_time", Type: field.TypeTime, Nullable: true, Comment: "结束时间"},
+		{Name: "send_time", Type: field.TypeTime, Nullable: true, Comment: "发送时间"},
 		{Name: "type", Type: field.TypeInt32, Nullable: true, Comment: "发送类型 1-群发消息 2-群发朋友圈"},
 		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
 	}
@@ -71,7 +73,7 @@ var (
 			{
 				Name:    "batchmsg_type",
 				Unique:  false,
-				Columns: []*schema.Column{BatchMsgColumns[15]},
+				Columns: []*schema.Column{BatchMsgColumns[17]},
 			},
 		},
 	}
@@ -296,7 +298,6 @@ var (
 		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
 		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
 		{Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
-		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
 		{Name: "bot_wxid", Type: field.TypeString, Comment: "机器人微信 id"},
 		{Name: "contact_type", Type: field.TypeInt, Comment: "类型:1好友,2群组,3企业微信联系人", Default: 1},
 		{Name: "contact_wxid", Type: field.TypeString, Comment: "接收方微信 id", Default: ""},
@@ -319,19 +320,19 @@ var (
 		ForeignKeys: []*schema.ForeignKey{
 			{
 				Symbol:     "message_records_contact_contact_messages",
-				Columns:    []*schema.Column{MessageRecordsColumns[15]},
+				Columns:    []*schema.Column{MessageRecordsColumns[14]},
 				RefColumns: []*schema.Column{ContactColumns[0]},
 				OnDelete:   schema.SetNull,
 			},
 			{
 				Symbol:     "message_records_sop_node_node_messages",
-				Columns:    []*schema.Column{MessageRecordsColumns[16]},
+				Columns:    []*schema.Column{MessageRecordsColumns[15]},
 				RefColumns: []*schema.Column{SopNodeColumns[0]},
 				OnDelete:   schema.SetNull,
 			},
 			{
 				Symbol:     "message_records_sop_stage_stage_messages",
-				Columns:    []*schema.Column{MessageRecordsColumns[17]},
+				Columns:    []*schema.Column{MessageRecordsColumns[16]},
 				RefColumns: []*schema.Column{SopStageColumns[0]},
 				OnDelete:   schema.SetNull,
 			},
@@ -340,7 +341,7 @@ var (
 			{
 				Name:    "messagerecords_source_type",
 				Unique:  false,
-				Columns: []*schema.Column{MessageRecordsColumns[13]},
+				Columns: []*schema.Column{MessageRecordsColumns[12]},
 			},
 		},
 	}
@@ -625,6 +626,10 @@ var (
 		{Name: "organization_id", Type: field.TypeUint64, Nullable: true, Comment: "机构 ID", Default: 1},
 		{Name: "api_base", Type: field.TypeString, Nullable: true, Comment: "大模型服务地址", Default: ""},
 		{Name: "api_key", Type: field.TypeString, Nullable: true, Comment: "大模型服务密钥", Default: ""},
+		{Name: "allow_list", Type: field.TypeJSON, Comment: "白名单"},
+		{Name: "group_allow_list", Type: field.TypeJSON, Comment: "群白名单"},
+		{Name: "block_list", Type: field.TypeJSON, Comment: "黑名单"},
+		{Name: "group_block_list", Type: field.TypeJSON, Comment: "群黑名单"},
 		{Name: "agent_id", Type: field.TypeUint64, Comment: "模式ID", Default: 0},
 		{Name: "server_id", Type: field.TypeUint64, Nullable: true, Comment: "服务器id", Default: 0},
 	}
@@ -636,13 +641,13 @@ var (
 		ForeignKeys: []*schema.ForeignKey{
 			{
 				Symbol:     "wx_agent_wx_agent",
-				Columns:    []*schema.Column{WxColumns[16]},
+				Columns:    []*schema.Column{WxColumns[20]},
 				RefColumns: []*schema.Column{AgentColumns[0]},
 				OnDelete:   schema.NoAction,
 			},
 			{
 				Symbol:     "wx_server_wxs",
-				Columns:    []*schema.Column{WxColumns[17]},
+				Columns:    []*schema.Column{WxColumns[21]},
 				RefColumns: []*schema.Column{ServerColumns[0]},
 				OnDelete:   schema.SetNull,
 			},
@@ -651,7 +656,7 @@ var (
 			{
 				Name:    "wx_server_id_port",
 				Unique:  true,
-				Columns: []*schema.Column{WxColumns[17], WxColumns[5]},
+				Columns: []*schema.Column{WxColumns[21], WxColumns[5]},
 			},
 			{
 				Name:    "wx_wxid",

+ 457 - 104
ent/mutation.go

@@ -1194,6 +1194,7 @@ type BatchMsgMutation struct {
 	fromwxid           *string
 	msg                *string
 	tag                *string
+	tagids             *string
 	total              *int32
 	addtotal           *int32
 	success            *int32
@@ -1202,6 +1203,7 @@ type BatchMsgMutation struct {
 	addfail            *int32
 	start_time         *time.Time
 	stop_time          *time.Time
+	send_time          *time.Time
 	_type              *int32
 	add_type           *int32
 	organization_id    *uint64
@@ -1752,6 +1754,55 @@ func (m *BatchMsgMutation) ResetTag() {
 	delete(m.clearedFields, batchmsg.FieldTag)
 }
 
+// SetTagids sets the "tagids" field.
+func (m *BatchMsgMutation) SetTagids(s string) {
+	m.tagids = &s
+}
+
+// Tagids returns the value of the "tagids" field in the mutation.
+func (m *BatchMsgMutation) Tagids() (r string, exists bool) {
+	v := m.tagids
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldTagids returns the old "tagids" field's value of the BatchMsg entity.
+// If the BatchMsg object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *BatchMsgMutation) OldTagids(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldTagids is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldTagids requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldTagids: %w", err)
+	}
+	return oldValue.Tagids, nil
+}
+
+// ClearTagids clears the value of the "tagids" field.
+func (m *BatchMsgMutation) ClearTagids() {
+	m.tagids = nil
+	m.clearedFields[batchmsg.FieldTagids] = struct{}{}
+}
+
+// TagidsCleared returns if the "tagids" field was cleared in this mutation.
+func (m *BatchMsgMutation) TagidsCleared() bool {
+	_, ok := m.clearedFields[batchmsg.FieldTagids]
+	return ok
+}
+
+// ResetTagids resets all changes to the "tagids" field.
+func (m *BatchMsgMutation) ResetTagids() {
+	m.tagids = nil
+	delete(m.clearedFields, batchmsg.FieldTagids)
+}
+
 // SetTotal sets the "total" field.
 func (m *BatchMsgMutation) SetTotal(i int32) {
 	m.total = &i
@@ -2060,6 +2111,55 @@ func (m *BatchMsgMutation) ResetStopTime() {
 	delete(m.clearedFields, batchmsg.FieldStopTime)
 }
 
+// SetSendTime sets the "send_time" field.
+func (m *BatchMsgMutation) SetSendTime(t time.Time) {
+	m.send_time = &t
+}
+
+// SendTime returns the value of the "send_time" field in the mutation.
+func (m *BatchMsgMutation) SendTime() (r time.Time, exists bool) {
+	v := m.send_time
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldSendTime returns the old "send_time" field's value of the BatchMsg entity.
+// If the BatchMsg object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *BatchMsgMutation) OldSendTime(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldSendTime is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldSendTime requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldSendTime: %w", err)
+	}
+	return oldValue.SendTime, nil
+}
+
+// ClearSendTime clears the value of the "send_time" field.
+func (m *BatchMsgMutation) ClearSendTime() {
+	m.send_time = nil
+	m.clearedFields[batchmsg.FieldSendTime] = struct{}{}
+}
+
+// SendTimeCleared returns if the "send_time" field was cleared in this mutation.
+func (m *BatchMsgMutation) SendTimeCleared() bool {
+	_, ok := m.clearedFields[batchmsg.FieldSendTime]
+	return ok
+}
+
+// ResetSendTime resets all changes to the "send_time" field.
+func (m *BatchMsgMutation) ResetSendTime() {
+	m.send_time = nil
+	delete(m.clearedFields, batchmsg.FieldSendTime)
+}
+
 // SetType sets the "type" field.
 func (m *BatchMsgMutation) SetType(i int32) {
 	m._type = &i
@@ -2220,7 +2320,7 @@ func (m *BatchMsgMutation) Type() string {
 // order to get all numeric fields that were incremented/decremented, call
 // AddedFields().
 func (m *BatchMsgMutation) Fields() []string {
-	fields := make([]string, 0, 16)
+	fields := make([]string, 0, 18)
 	if m.created_at != nil {
 		fields = append(fields, batchmsg.FieldCreatedAt)
 	}
@@ -2248,6 +2348,9 @@ func (m *BatchMsgMutation) Fields() []string {
 	if m.tag != nil {
 		fields = append(fields, batchmsg.FieldTag)
 	}
+	if m.tagids != nil {
+		fields = append(fields, batchmsg.FieldTagids)
+	}
 	if m.total != nil {
 		fields = append(fields, batchmsg.FieldTotal)
 	}
@@ -2263,6 +2366,9 @@ func (m *BatchMsgMutation) Fields() []string {
 	if m.stop_time != nil {
 		fields = append(fields, batchmsg.FieldStopTime)
 	}
+	if m.send_time != nil {
+		fields = append(fields, batchmsg.FieldSendTime)
+	}
 	if m._type != nil {
 		fields = append(fields, batchmsg.FieldType)
 	}
@@ -2295,6 +2401,8 @@ func (m *BatchMsgMutation) Field(name string) (ent.Value, bool) {
 		return m.Msg()
 	case batchmsg.FieldTag:
 		return m.Tag()
+	case batchmsg.FieldTagids:
+		return m.Tagids()
 	case batchmsg.FieldTotal:
 		return m.Total()
 	case batchmsg.FieldSuccess:
@@ -2305,6 +2413,8 @@ func (m *BatchMsgMutation) Field(name string) (ent.Value, bool) {
 		return m.StartTime()
 	case batchmsg.FieldStopTime:
 		return m.StopTime()
+	case batchmsg.FieldSendTime:
+		return m.SendTime()
 	case batchmsg.FieldType:
 		return m.GetType()
 	case batchmsg.FieldOrganizationID:
@@ -2336,6 +2446,8 @@ func (m *BatchMsgMutation) OldField(ctx context.Context, name string) (ent.Value
 		return m.OldMsg(ctx)
 	case batchmsg.FieldTag:
 		return m.OldTag(ctx)
+	case batchmsg.FieldTagids:
+		return m.OldTagids(ctx)
 	case batchmsg.FieldTotal:
 		return m.OldTotal(ctx)
 	case batchmsg.FieldSuccess:
@@ -2346,6 +2458,8 @@ func (m *BatchMsgMutation) OldField(ctx context.Context, name string) (ent.Value
 		return m.OldStartTime(ctx)
 	case batchmsg.FieldStopTime:
 		return m.OldStopTime(ctx)
+	case batchmsg.FieldSendTime:
+		return m.OldSendTime(ctx)
 	case batchmsg.FieldType:
 		return m.OldType(ctx)
 	case batchmsg.FieldOrganizationID:
@@ -2422,6 +2536,13 @@ func (m *BatchMsgMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetTag(v)
 		return nil
+	case batchmsg.FieldTagids:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetTagids(v)
+		return nil
 	case batchmsg.FieldTotal:
 		v, ok := value.(int32)
 		if !ok {
@@ -2457,6 +2578,13 @@ func (m *BatchMsgMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetStopTime(v)
 		return nil
+	case batchmsg.FieldSendTime:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetSendTime(v)
+		return nil
 	case batchmsg.FieldType:
 		v, ok := value.(int32)
 		if !ok {
@@ -2597,6 +2725,9 @@ func (m *BatchMsgMutation) ClearedFields() []string {
 	if m.FieldCleared(batchmsg.FieldTag) {
 		fields = append(fields, batchmsg.FieldTag)
 	}
+	if m.FieldCleared(batchmsg.FieldTagids) {
+		fields = append(fields, batchmsg.FieldTagids)
+	}
 	if m.FieldCleared(batchmsg.FieldTotal) {
 		fields = append(fields, batchmsg.FieldTotal)
 	}
@@ -2612,6 +2743,9 @@ func (m *BatchMsgMutation) ClearedFields() []string {
 	if m.FieldCleared(batchmsg.FieldStopTime) {
 		fields = append(fields, batchmsg.FieldStopTime)
 	}
+	if m.FieldCleared(batchmsg.FieldSendTime) {
+		fields = append(fields, batchmsg.FieldSendTime)
+	}
 	if m.FieldCleared(batchmsg.FieldType) {
 		fields = append(fields, batchmsg.FieldType)
 	}
@@ -2650,6 +2784,9 @@ func (m *BatchMsgMutation) ClearField(name string) error {
 	case batchmsg.FieldTag:
 		m.ClearTag()
 		return nil
+	case batchmsg.FieldTagids:
+		m.ClearTagids()
+		return nil
 	case batchmsg.FieldTotal:
 		m.ClearTotal()
 		return nil
@@ -2665,6 +2802,9 @@ func (m *BatchMsgMutation) ClearField(name string) error {
 	case batchmsg.FieldStopTime:
 		m.ClearStopTime()
 		return nil
+	case batchmsg.FieldSendTime:
+		m.ClearSendTime()
+		return nil
 	case batchmsg.FieldType:
 		m.ClearType()
 		return nil
@@ -2703,6 +2843,9 @@ func (m *BatchMsgMutation) ResetField(name string) error {
 	case batchmsg.FieldTag:
 		m.ResetTag()
 		return nil
+	case batchmsg.FieldTagids:
+		m.ResetTagids()
+		return nil
 	case batchmsg.FieldTotal:
 		m.ResetTotal()
 		return nil
@@ -2718,6 +2861,9 @@ func (m *BatchMsgMutation) ResetField(name string) error {
 	case batchmsg.FieldStopTime:
 		m.ResetStopTime()
 		return nil
+	case batchmsg.FieldSendTime:
+		m.ResetSendTime()
+		return nil
 	case batchmsg.FieldType:
 		m.ResetType()
 		return nil
@@ -10034,7 +10180,6 @@ type MessageRecordsMutation struct {
 	updated_at             *time.Time
 	status                 *uint8
 	addstatus              *int8
-	deleted_at             *time.Time
 	bot_wxid               *string
 	contact_type           *int
 	addcontact_type        *int
@@ -10307,55 +10452,6 @@ func (m *MessageRecordsMutation) ResetStatus() {
 	delete(m.clearedFields, messagerecords.FieldStatus)
 }
 
-// SetDeletedAt sets the "deleted_at" field.
-func (m *MessageRecordsMutation) SetDeletedAt(t time.Time) {
-	m.deleted_at = &t
-}
-
-// DeletedAt returns the value of the "deleted_at" field in the mutation.
-func (m *MessageRecordsMutation) DeletedAt() (r time.Time, exists bool) {
-	v := m.deleted_at
-	if v == nil {
-		return
-	}
-	return *v, true
-}
-
-// OldDeletedAt returns the old "deleted_at" field's value of the MessageRecords entity.
-// If the MessageRecords object wasn't provided to the builder, the object is fetched from the database.
-// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
-func (m *MessageRecordsMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) {
-	if !m.op.Is(OpUpdateOne) {
-		return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations")
-	}
-	if m.id == nil || m.oldValue == nil {
-		return v, errors.New("OldDeletedAt requires an ID field in the mutation")
-	}
-	oldValue, err := m.oldValue(ctx)
-	if err != nil {
-		return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err)
-	}
-	return oldValue.DeletedAt, nil
-}
-
-// ClearDeletedAt clears the value of the "deleted_at" field.
-func (m *MessageRecordsMutation) ClearDeletedAt() {
-	m.deleted_at = nil
-	m.clearedFields[messagerecords.FieldDeletedAt] = struct{}{}
-}
-
-// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation.
-func (m *MessageRecordsMutation) DeletedAtCleared() bool {
-	_, ok := m.clearedFields[messagerecords.FieldDeletedAt]
-	return ok
-}
-
-// ResetDeletedAt resets all changes to the "deleted_at" field.
-func (m *MessageRecordsMutation) ResetDeletedAt() {
-	m.deleted_at = nil
-	delete(m.clearedFields, messagerecords.FieldDeletedAt)
-}
-
 // SetBotWxid sets the "bot_wxid" field.
 func (m *MessageRecordsMutation) SetBotWxid(s string) {
 	m.bot_wxid = &s
@@ -11137,7 +11233,7 @@ func (m *MessageRecordsMutation) Type() string {
 // order to get all numeric fields that were incremented/decremented, call
 // AddedFields().
 func (m *MessageRecordsMutation) Fields() []string {
-	fields := make([]string, 0, 17)
+	fields := make([]string, 0, 16)
 	if m.created_at != nil {
 		fields = append(fields, messagerecords.FieldCreatedAt)
 	}
@@ -11147,9 +11243,6 @@ func (m *MessageRecordsMutation) Fields() []string {
 	if m.status != nil {
 		fields = append(fields, messagerecords.FieldStatus)
 	}
-	if m.deleted_at != nil {
-		fields = append(fields, messagerecords.FieldDeletedAt)
-	}
 	if m.bot_wxid != nil {
 		fields = append(fields, messagerecords.FieldBotWxid)
 	}
@@ -11203,8 +11296,6 @@ func (m *MessageRecordsMutation) Field(name string) (ent.Value, bool) {
 		return m.UpdatedAt()
 	case messagerecords.FieldStatus:
 		return m.Status()
-	case messagerecords.FieldDeletedAt:
-		return m.DeletedAt()
 	case messagerecords.FieldBotWxid:
 		return m.BotWxid()
 	case messagerecords.FieldContactID:
@@ -11246,8 +11337,6 @@ func (m *MessageRecordsMutation) OldField(ctx context.Context, name string) (ent
 		return m.OldUpdatedAt(ctx)
 	case messagerecords.FieldStatus:
 		return m.OldStatus(ctx)
-	case messagerecords.FieldDeletedAt:
-		return m.OldDeletedAt(ctx)
 	case messagerecords.FieldBotWxid:
 		return m.OldBotWxid(ctx)
 	case messagerecords.FieldContactID:
@@ -11304,13 +11393,6 @@ func (m *MessageRecordsMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetStatus(v)
 		return nil
-	case messagerecords.FieldDeletedAt:
-		v, ok := value.(time.Time)
-		if !ok {
-			return fmt.Errorf("unexpected type %T for field %s", value, name)
-		}
-		m.SetDeletedAt(v)
-		return nil
 	case messagerecords.FieldBotWxid:
 		v, ok := value.(string)
 		if !ok {
@@ -11498,9 +11580,6 @@ func (m *MessageRecordsMutation) ClearedFields() []string {
 	if m.FieldCleared(messagerecords.FieldStatus) {
 		fields = append(fields, messagerecords.FieldStatus)
 	}
-	if m.FieldCleared(messagerecords.FieldDeletedAt) {
-		fields = append(fields, messagerecords.FieldDeletedAt)
-	}
 	if m.FieldCleared(messagerecords.FieldContactID) {
 		fields = append(fields, messagerecords.FieldContactID)
 	}
@@ -11536,9 +11615,6 @@ func (m *MessageRecordsMutation) ClearField(name string) error {
 	case messagerecords.FieldStatus:
 		m.ClearStatus()
 		return nil
-	case messagerecords.FieldDeletedAt:
-		m.ClearDeletedAt()
-		return nil
 	case messagerecords.FieldContactID:
 		m.ClearContactID()
 		return nil
@@ -11574,9 +11650,6 @@ func (m *MessageRecordsMutation) ResetField(name string) error {
 	case messagerecords.FieldStatus:
 		m.ResetStatus()
 		return nil
-	case messagerecords.FieldDeletedAt:
-		m.ResetDeletedAt()
-		return nil
 	case messagerecords.FieldBotWxid:
 		m.ResetBotWxid()
 		return nil
@@ -20009,34 +20082,42 @@ func (m *WorkExperienceMutation) ResetEdge(name string) error {
 // WxMutation represents an operation that mutates the Wx nodes in the graph.
 type WxMutation struct {
 	config
-	op                 Op
-	typ                string
-	id                 *uint64
-	created_at         *time.Time
-	updated_at         *time.Time
-	status             *uint8
-	addstatus          *int8
-	deleted_at         *time.Time
-	port               *string
-	process_id         *string
-	callback           *string
-	wxid               *string
-	account            *string
-	nickname           *string
-	tel                *string
-	head_big           *string
-	organization_id    *uint64
-	addorganization_id *int64
-	api_base           *string
-	api_key            *string
-	clearedFields      map[string]struct{}
-	server             *uint64
-	clearedserver      bool
-	agent              *uint64
-	clearedagent       bool
-	done               bool
-	oldValue           func(context.Context) (*Wx, error)
-	predicates         []predicate.Wx
+	op                     Op
+	typ                    string
+	id                     *uint64
+	created_at             *time.Time
+	updated_at             *time.Time
+	status                 *uint8
+	addstatus              *int8
+	deleted_at             *time.Time
+	port                   *string
+	process_id             *string
+	callback               *string
+	wxid                   *string
+	account                *string
+	nickname               *string
+	tel                    *string
+	head_big               *string
+	organization_id        *uint64
+	addorganization_id     *int64
+	api_base               *string
+	api_key                *string
+	allow_list             *[]string
+	appendallow_list       []string
+	group_allow_list       *[]string
+	appendgroup_allow_list []string
+	block_list             *[]string
+	appendblock_list       []string
+	group_block_list       *[]string
+	appendgroup_block_list []string
+	clearedFields          map[string]struct{}
+	server                 *uint64
+	clearedserver          bool
+	agent                  *uint64
+	clearedagent           bool
+	done                   bool
+	oldValue               func(context.Context) (*Wx, error)
+	predicates             []predicate.Wx
 }
 
 var _ ent.Mutation = (*WxMutation)(nil)
@@ -20875,6 +20956,210 @@ func (m *WxMutation) ResetAPIKey() {
 	delete(m.clearedFields, wx.FieldAPIKey)
 }
 
+// SetAllowList sets the "allow_list" field.
+func (m *WxMutation) SetAllowList(s []string) {
+	m.allow_list = &s
+	m.appendallow_list = nil
+}
+
+// AllowList returns the value of the "allow_list" field in the mutation.
+func (m *WxMutation) AllowList() (r []string, exists bool) {
+	v := m.allow_list
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldAllowList returns the old "allow_list" field's value of the Wx entity.
+// If the Wx object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *WxMutation) OldAllowList(ctx context.Context) (v []string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldAllowList is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldAllowList requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldAllowList: %w", err)
+	}
+	return oldValue.AllowList, nil
+}
+
+// AppendAllowList adds s to the "allow_list" field.
+func (m *WxMutation) AppendAllowList(s []string) {
+	m.appendallow_list = append(m.appendallow_list, s...)
+}
+
+// AppendedAllowList returns the list of values that were appended to the "allow_list" field in this mutation.
+func (m *WxMutation) AppendedAllowList() ([]string, bool) {
+	if len(m.appendallow_list) == 0 {
+		return nil, false
+	}
+	return m.appendallow_list, true
+}
+
+// ResetAllowList resets all changes to the "allow_list" field.
+func (m *WxMutation) ResetAllowList() {
+	m.allow_list = nil
+	m.appendallow_list = nil
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (m *WxMutation) SetGroupAllowList(s []string) {
+	m.group_allow_list = &s
+	m.appendgroup_allow_list = nil
+}
+
+// GroupAllowList returns the value of the "group_allow_list" field in the mutation.
+func (m *WxMutation) GroupAllowList() (r []string, exists bool) {
+	v := m.group_allow_list
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldGroupAllowList returns the old "group_allow_list" field's value of the Wx entity.
+// If the Wx object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *WxMutation) OldGroupAllowList(ctx context.Context) (v []string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldGroupAllowList is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldGroupAllowList requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldGroupAllowList: %w", err)
+	}
+	return oldValue.GroupAllowList, nil
+}
+
+// AppendGroupAllowList adds s to the "group_allow_list" field.
+func (m *WxMutation) AppendGroupAllowList(s []string) {
+	m.appendgroup_allow_list = append(m.appendgroup_allow_list, s...)
+}
+
+// AppendedGroupAllowList returns the list of values that were appended to the "group_allow_list" field in this mutation.
+func (m *WxMutation) AppendedGroupAllowList() ([]string, bool) {
+	if len(m.appendgroup_allow_list) == 0 {
+		return nil, false
+	}
+	return m.appendgroup_allow_list, true
+}
+
+// ResetGroupAllowList resets all changes to the "group_allow_list" field.
+func (m *WxMutation) ResetGroupAllowList() {
+	m.group_allow_list = nil
+	m.appendgroup_allow_list = nil
+}
+
+// SetBlockList sets the "block_list" field.
+func (m *WxMutation) SetBlockList(s []string) {
+	m.block_list = &s
+	m.appendblock_list = nil
+}
+
+// BlockList returns the value of the "block_list" field in the mutation.
+func (m *WxMutation) BlockList() (r []string, exists bool) {
+	v := m.block_list
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldBlockList returns the old "block_list" field's value of the Wx entity.
+// If the Wx object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *WxMutation) OldBlockList(ctx context.Context) (v []string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldBlockList is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldBlockList requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldBlockList: %w", err)
+	}
+	return oldValue.BlockList, nil
+}
+
+// AppendBlockList adds s to the "block_list" field.
+func (m *WxMutation) AppendBlockList(s []string) {
+	m.appendblock_list = append(m.appendblock_list, s...)
+}
+
+// AppendedBlockList returns the list of values that were appended to the "block_list" field in this mutation.
+func (m *WxMutation) AppendedBlockList() ([]string, bool) {
+	if len(m.appendblock_list) == 0 {
+		return nil, false
+	}
+	return m.appendblock_list, true
+}
+
+// ResetBlockList resets all changes to the "block_list" field.
+func (m *WxMutation) ResetBlockList() {
+	m.block_list = nil
+	m.appendblock_list = nil
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (m *WxMutation) SetGroupBlockList(s []string) {
+	m.group_block_list = &s
+	m.appendgroup_block_list = nil
+}
+
+// GroupBlockList returns the value of the "group_block_list" field in the mutation.
+func (m *WxMutation) GroupBlockList() (r []string, exists bool) {
+	v := m.group_block_list
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldGroupBlockList returns the old "group_block_list" field's value of the Wx entity.
+// If the Wx object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *WxMutation) OldGroupBlockList(ctx context.Context) (v []string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldGroupBlockList is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldGroupBlockList requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldGroupBlockList: %w", err)
+	}
+	return oldValue.GroupBlockList, nil
+}
+
+// AppendGroupBlockList adds s to the "group_block_list" field.
+func (m *WxMutation) AppendGroupBlockList(s []string) {
+	m.appendgroup_block_list = append(m.appendgroup_block_list, s...)
+}
+
+// AppendedGroupBlockList returns the list of values that were appended to the "group_block_list" field in this mutation.
+func (m *WxMutation) AppendedGroupBlockList() ([]string, bool) {
+	if len(m.appendgroup_block_list) == 0 {
+		return nil, false
+	}
+	return m.appendgroup_block_list, true
+}
+
+// ResetGroupBlockList resets all changes to the "group_block_list" field.
+func (m *WxMutation) ResetGroupBlockList() {
+	m.group_block_list = nil
+	m.appendgroup_block_list = nil
+}
+
 // ClearServer clears the "server" edge to the Server entity.
 func (m *WxMutation) ClearServer() {
 	m.clearedserver = true
@@ -20963,7 +21248,7 @@ func (m *WxMutation) Type() string {
 // order to get all numeric fields that were incremented/decremented, call
 // AddedFields().
 func (m *WxMutation) Fields() []string {
-	fields := make([]string, 0, 17)
+	fields := make([]string, 0, 21)
 	if m.created_at != nil {
 		fields = append(fields, wx.FieldCreatedAt)
 	}
@@ -21015,6 +21300,18 @@ func (m *WxMutation) Fields() []string {
 	if m.api_key != nil {
 		fields = append(fields, wx.FieldAPIKey)
 	}
+	if m.allow_list != nil {
+		fields = append(fields, wx.FieldAllowList)
+	}
+	if m.group_allow_list != nil {
+		fields = append(fields, wx.FieldGroupAllowList)
+	}
+	if m.block_list != nil {
+		fields = append(fields, wx.FieldBlockList)
+	}
+	if m.group_block_list != nil {
+		fields = append(fields, wx.FieldGroupBlockList)
+	}
 	return fields
 }
 
@@ -21057,6 +21354,14 @@ func (m *WxMutation) Field(name string) (ent.Value, bool) {
 		return m.APIBase()
 	case wx.FieldAPIKey:
 		return m.APIKey()
+	case wx.FieldAllowList:
+		return m.AllowList()
+	case wx.FieldGroupAllowList:
+		return m.GroupAllowList()
+	case wx.FieldBlockList:
+		return m.BlockList()
+	case wx.FieldGroupBlockList:
+		return m.GroupBlockList()
 	}
 	return nil, false
 }
@@ -21100,6 +21405,14 @@ func (m *WxMutation) OldField(ctx context.Context, name string) (ent.Value, erro
 		return m.OldAPIBase(ctx)
 	case wx.FieldAPIKey:
 		return m.OldAPIKey(ctx)
+	case wx.FieldAllowList:
+		return m.OldAllowList(ctx)
+	case wx.FieldGroupAllowList:
+		return m.OldGroupAllowList(ctx)
+	case wx.FieldBlockList:
+		return m.OldBlockList(ctx)
+	case wx.FieldGroupBlockList:
+		return m.OldGroupBlockList(ctx)
 	}
 	return nil, fmt.Errorf("unknown Wx field %s", name)
 }
@@ -21228,6 +21541,34 @@ func (m *WxMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetAPIKey(v)
 		return nil
+	case wx.FieldAllowList:
+		v, ok := value.([]string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetAllowList(v)
+		return nil
+	case wx.FieldGroupAllowList:
+		v, ok := value.([]string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetGroupAllowList(v)
+		return nil
+	case wx.FieldBlockList:
+		v, ok := value.([]string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetBlockList(v)
+		return nil
+	case wx.FieldGroupBlockList:
+		v, ok := value.([]string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetGroupBlockList(v)
+		return nil
 	}
 	return fmt.Errorf("unknown Wx field %s", name)
 }
@@ -21394,6 +21735,18 @@ func (m *WxMutation) ResetField(name string) error {
 	case wx.FieldAPIKey:
 		m.ResetAPIKey()
 		return nil
+	case wx.FieldAllowList:
+		m.ResetAllowList()
+		return nil
+	case wx.FieldGroupAllowList:
+		m.ResetGroupAllowList()
+		return nil
+	case wx.FieldBlockList:
+		m.ResetBlockList()
+		return nil
+	case wx.FieldGroupBlockList:
+		m.ResetGroupBlockList()
+		return nil
 	}
 	return fmt.Errorf("unknown Wx field %s", name)
 }

+ 1 - 5
ent/runtime/runtime.go

@@ -115,7 +115,7 @@ func init() {
 	// batchmsg.DefaultTaskName holds the default value on creation for the task_name field.
 	batchmsg.DefaultTaskName = batchmsgDescTaskName.Default.(string)
 	// batchmsgDescOrganizationID is the schema descriptor for organization_id field.
-	batchmsgDescOrganizationID := batchmsgFields[12].Descriptor()
+	batchmsgDescOrganizationID := batchmsgFields[14].Descriptor()
 	// batchmsg.OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
 	batchmsg.OrganizationIDValidator = batchmsgDescOrganizationID.Validators[0].(func(uint64) error)
 	categoryMixin := schema.Category{}.Mixin()
@@ -459,10 +459,6 @@ func init() {
 	// message.DefaultContent holds the default value on creation for the content field.
 	message.DefaultContent = messageDescContent.Default.(string)
 	messagerecordsMixin := schema.MessageRecords{}.Mixin()
-	messagerecordsMixinHooks2 := messagerecordsMixin[2].Hooks()
-	messagerecords.Hooks[0] = messagerecordsMixinHooks2[0]
-	messagerecordsMixinInters2 := messagerecordsMixin[2].Interceptors()
-	messagerecords.Interceptors[0] = messagerecordsMixinInters2[0]
 	messagerecordsMixinFields0 := messagerecordsMixin[0].Fields()
 	_ = messagerecordsMixinFields0
 	messagerecordsMixinFields1 := messagerecordsMixin[1].Fields()

+ 2 - 0
ent/schema/batch_msg.go

@@ -23,11 +23,13 @@ func (BatchMsg) Fields() []ent.Field {
 		field.String("fromwxid").Optional().Comment("发送方微信ID"),
 		field.String("msg").Optional().Comment("内容"),
 		field.String("tag").Optional().Comment("发送规则 all 全部 tag1,tag2 按tag发送"),
+		field.String("tagids").Optional().Comment("要发送的tagids"),
 		field.Int32("total").Optional().Comment("总数"),
 		field.Int32("success").Optional().Comment("成功数量"),
 		field.Int32("fail").Optional().Comment("失败数量"),
 		field.Time("start_time").Optional().Comment("开始时间"),
 		field.Time("stop_time").Optional().Comment("结束时间"),
+		field.Time("send_time").Optional().Comment("发送时间"),
 		field.Int32("type").Optional().Comment("发送类型 1-群发消息 2-群发朋友圈"),
 		field.Uint64("organization_id").Positive().Comment("organization_id | 租户ID"),
 	}

+ 1 - 4
ent/schema/message_records.go

@@ -1,9 +1,6 @@
 package schema
 
 import (
-	"wechat-api/ent/custom_types"
-	"wechat-api/ent/schema/localmixin"
-
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/entsql"
 	"entgo.io/ent/schema"
@@ -11,6 +8,7 @@ import (
 	"entgo.io/ent/schema/field"
 	"entgo.io/ent/schema/index"
 	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+	"wechat-api/ent/custom_types"
 )
 
 type MessageRecords struct {
@@ -65,7 +63,6 @@ func (MessageRecords) Mixin() []ent.Mixin {
 	return []ent.Mixin{
 		mixins.IDMixin{},
 		mixins.StatusMixin{},
-		localmixin.SoftDeleteMixin{},
 	}
 }
 

+ 12 - 0
ent/schema/wx.go

@@ -58,6 +58,18 @@ func (Wx) Fields() []ent.Field {
 		field.String("api_key").Optional().Default("").
 			Annotations(entsql.WithComments(true)).
 			Comment("大模型服务密钥"),
+		field.JSON("allow_list", []string{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("白名单"),
+		field.JSON("group_allow_list", []string{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("群白名单"),
+		field.JSON("block_list", []string{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("黑名单"),
+		field.JSON("group_block_list", []string{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("群黑名单"),
 	}
 }
 

+ 144 - 24
ent/set_not_nil.go

@@ -440,6 +440,30 @@ func (bm *BatchMsgCreate) SetNotNilTag(value *string) *BatchMsgCreate {
 }
 
 // set field if value's pointer is not nil.
+func (bm *BatchMsgUpdate) SetNotNilTagids(value *string) *BatchMsgUpdate {
+	if value != nil {
+		return bm.SetTagids(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
+func (bm *BatchMsgUpdateOne) SetNotNilTagids(value *string) *BatchMsgUpdateOne {
+	if value != nil {
+		return bm.SetTagids(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
+func (bm *BatchMsgCreate) SetNotNilTagids(value *string) *BatchMsgCreate {
+	if value != nil {
+		return bm.SetTagids(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
 func (bm *BatchMsgUpdate) SetNotNilTotal(value *int32) *BatchMsgUpdate {
 	if value != nil {
 		return bm.SetTotal(*value)
@@ -560,6 +584,30 @@ func (bm *BatchMsgCreate) SetNotNilStopTime(value *time.Time) *BatchMsgCreate {
 }
 
 // set field if value's pointer is not nil.
+func (bm *BatchMsgUpdate) SetNotNilSendTime(value *time.Time) *BatchMsgUpdate {
+	if value != nil {
+		return bm.SetSendTime(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
+func (bm *BatchMsgUpdateOne) SetNotNilSendTime(value *time.Time) *BatchMsgUpdateOne {
+	if value != nil {
+		return bm.SetSendTime(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
+func (bm *BatchMsgCreate) SetNotNilSendTime(value *time.Time) *BatchMsgCreate {
+	if value != nil {
+		return bm.SetSendTime(*value)
+	}
+	return bm
+}
+
+// set field if value's pointer is not nil.
 func (bm *BatchMsgUpdate) SetNotNilType(value *int32) *BatchMsgUpdate {
 	if value != nil {
 		return bm.SetType(*value)
@@ -2168,30 +2216,6 @@ func (mr *MessageRecordsCreate) SetNotNilStatus(value *uint8) *MessageRecordsCre
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdate) SetNotNilDeletedAt(value *time.Time) *MessageRecordsUpdate {
-	if value != nil {
-		return mr.SetDeletedAt(*value)
-	}
-	return mr
-}
-
-// set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdateOne) SetNotNilDeletedAt(value *time.Time) *MessageRecordsUpdateOne {
-	if value != nil {
-		return mr.SetDeletedAt(*value)
-	}
-	return mr
-}
-
-// set field if value's pointer is not nil.
-func (mr *MessageRecordsCreate) SetNotNilDeletedAt(value *time.Time) *MessageRecordsCreate {
-	if value != nil {
-		return mr.SetDeletedAt(*value)
-	}
-	return mr
-}
-
-// set field if value's pointer is not nil.
 func (mr *MessageRecordsUpdate) SetNotNilBotWxid(value *string) *MessageRecordsUpdate {
 	if value != nil {
 		return mr.SetBotWxid(*value)
@@ -4494,3 +4518,99 @@ func (w *WxCreate) SetNotNilAPIKey(value *string) *WxCreate {
 	}
 	return w
 }
+
+// set field if value's pointer is not nil.
+func (w *WxUpdate) SetNotNilAllowList(value []string) *WxUpdate {
+	if value != nil {
+		return w.SetAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdateOne) SetNotNilAllowList(value []string) *WxUpdateOne {
+	if value != nil {
+		return w.SetAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxCreate) SetNotNilAllowList(value []string) *WxCreate {
+	if value != nil {
+		return w.SetAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdate) SetNotNilGroupAllowList(value []string) *WxUpdate {
+	if value != nil {
+		return w.SetGroupAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdateOne) SetNotNilGroupAllowList(value []string) *WxUpdateOne {
+	if value != nil {
+		return w.SetGroupAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxCreate) SetNotNilGroupAllowList(value []string) *WxCreate {
+	if value != nil {
+		return w.SetGroupAllowList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdate) SetNotNilBlockList(value []string) *WxUpdate {
+	if value != nil {
+		return w.SetBlockList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdateOne) SetNotNilBlockList(value []string) *WxUpdateOne {
+	if value != nil {
+		return w.SetBlockList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxCreate) SetNotNilBlockList(value []string) *WxCreate {
+	if value != nil {
+		return w.SetBlockList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdate) SetNotNilGroupBlockList(value []string) *WxUpdate {
+	if value != nil {
+		return w.SetGroupBlockList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxUpdateOne) SetNotNilGroupBlockList(value []string) *WxUpdateOne {
+	if value != nil {
+		return w.SetGroupBlockList(value)
+	}
+	return w
+}
+
+// set field if value's pointer is not nil.
+func (w *WxCreate) SetNotNilGroupBlockList(value []string) *WxCreate {
+	if value != nil {
+		return w.SetGroupBlockList(value)
+	}
+	return w
+}

+ 55 - 0
ent/wx.go

@@ -3,6 +3,7 @@
 package ent
 
 import (
+	"encoding/json"
 	"fmt"
 	"strings"
 	"time"
@@ -53,6 +54,14 @@ type Wx struct {
 	APIBase string `json:"api_base,omitempty"`
 	// 大模型服务密钥
 	APIKey string `json:"api_key,omitempty"`
+	// 白名单
+	AllowList []string `json:"allow_list,omitempty"`
+	// 群白名单
+	GroupAllowList []string `json:"group_allow_list,omitempty"`
+	// 黑名单
+	BlockList []string `json:"block_list,omitempty"`
+	// 群黑名单
+	GroupBlockList []string `json:"group_block_list,omitempty"`
 	// Edges holds the relations/edges for other nodes in the graph.
 	// The values are being populated by the WxQuery when eager-loading is set.
 	Edges        WxEdges `json:"edges"`
@@ -97,6 +106,8 @@ func (*Wx) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
 	for i := range columns {
 		switch columns[i] {
+		case wx.FieldAllowList, wx.FieldGroupAllowList, wx.FieldBlockList, wx.FieldGroupBlockList:
+			values[i] = new([]byte)
 		case wx.FieldID, wx.FieldStatus, wx.FieldServerID, wx.FieldOrganizationID, wx.FieldAgentID:
 			values[i] = new(sql.NullInt64)
 		case wx.FieldPort, wx.FieldProcessID, wx.FieldCallback, wx.FieldWxid, wx.FieldAccount, wx.FieldNickname, wx.FieldTel, wx.FieldHeadBig, wx.FieldAPIBase, wx.FieldAPIKey:
@@ -226,6 +237,38 @@ func (w *Wx) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				w.APIKey = value.String
 			}
+		case wx.FieldAllowList:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field allow_list", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &w.AllowList); err != nil {
+					return fmt.Errorf("unmarshal field allow_list: %w", err)
+				}
+			}
+		case wx.FieldGroupAllowList:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field group_allow_list", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &w.GroupAllowList); err != nil {
+					return fmt.Errorf("unmarshal field group_allow_list: %w", err)
+				}
+			}
+		case wx.FieldBlockList:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field block_list", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &w.BlockList); err != nil {
+					return fmt.Errorf("unmarshal field block_list: %w", err)
+				}
+			}
+		case wx.FieldGroupBlockList:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field group_block_list", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &w.GroupBlockList); err != nil {
+					return fmt.Errorf("unmarshal field group_block_list: %w", err)
+				}
+			}
 		default:
 			w.selectValues.Set(columns[i], values[i])
 		}
@@ -322,6 +365,18 @@ func (w *Wx) String() string {
 	builder.WriteString(", ")
 	builder.WriteString("api_key=")
 	builder.WriteString(w.APIKey)
+	builder.WriteString(", ")
+	builder.WriteString("allow_list=")
+	builder.WriteString(fmt.Sprintf("%v", w.AllowList))
+	builder.WriteString(", ")
+	builder.WriteString("group_allow_list=")
+	builder.WriteString(fmt.Sprintf("%v", w.GroupAllowList))
+	builder.WriteString(", ")
+	builder.WriteString("block_list=")
+	builder.WriteString(fmt.Sprintf("%v", w.BlockList))
+	builder.WriteString(", ")
+	builder.WriteString("group_block_list=")
+	builder.WriteString(fmt.Sprintf("%v", w.GroupBlockList))
 	builder.WriteByte(')')
 	return builder.String()
 }

+ 12 - 0
ent/wx/wx.go

@@ -49,6 +49,14 @@ const (
 	FieldAPIBase = "api_base"
 	// FieldAPIKey holds the string denoting the api_key field in the database.
 	FieldAPIKey = "api_key"
+	// FieldAllowList holds the string denoting the allow_list field in the database.
+	FieldAllowList = "allow_list"
+	// FieldGroupAllowList holds the string denoting the group_allow_list field in the database.
+	FieldGroupAllowList = "group_allow_list"
+	// FieldBlockList holds the string denoting the block_list field in the database.
+	FieldBlockList = "block_list"
+	// FieldGroupBlockList holds the string denoting the group_block_list field in the database.
+	FieldGroupBlockList = "group_block_list"
 	// EdgeServer holds the string denoting the server edge name in mutations.
 	EdgeServer = "server"
 	// EdgeAgent holds the string denoting the agent edge name in mutations.
@@ -91,6 +99,10 @@ var Columns = []string{
 	FieldAgentID,
 	FieldAPIBase,
 	FieldAPIKey,
+	FieldAllowList,
+	FieldGroupAllowList,
+	FieldBlockList,
+	FieldGroupBlockList,
 }
 
 // ValidColumn reports if the column name is valid (part of the table columns).

+ 212 - 0
ent/wx_create.go

@@ -262,6 +262,30 @@ func (wc *WxCreate) SetNillableAPIKey(s *string) *WxCreate {
 	return wc
 }
 
+// SetAllowList sets the "allow_list" field.
+func (wc *WxCreate) SetAllowList(s []string) *WxCreate {
+	wc.mutation.SetAllowList(s)
+	return wc
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (wc *WxCreate) SetGroupAllowList(s []string) *WxCreate {
+	wc.mutation.SetGroupAllowList(s)
+	return wc
+}
+
+// SetBlockList sets the "block_list" field.
+func (wc *WxCreate) SetBlockList(s []string) *WxCreate {
+	wc.mutation.SetBlockList(s)
+	return wc
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (wc *WxCreate) SetGroupBlockList(s []string) *WxCreate {
+	wc.mutation.SetGroupBlockList(s)
+	return wc
+}
+
 // SetID sets the "id" field.
 func (wc *WxCreate) SetID(u uint64) *WxCreate {
 	wc.mutation.SetID(u)
@@ -423,6 +447,18 @@ func (wc *WxCreate) check() error {
 	if _, ok := wc.mutation.AgentID(); !ok {
 		return &ValidationError{Name: "agent_id", err: errors.New(`ent: missing required field "Wx.agent_id"`)}
 	}
+	if _, ok := wc.mutation.AllowList(); !ok {
+		return &ValidationError{Name: "allow_list", err: errors.New(`ent: missing required field "Wx.allow_list"`)}
+	}
+	if _, ok := wc.mutation.GroupAllowList(); !ok {
+		return &ValidationError{Name: "group_allow_list", err: errors.New(`ent: missing required field "Wx.group_allow_list"`)}
+	}
+	if _, ok := wc.mutation.BlockList(); !ok {
+		return &ValidationError{Name: "block_list", err: errors.New(`ent: missing required field "Wx.block_list"`)}
+	}
+	if _, ok := wc.mutation.GroupBlockList(); !ok {
+		return &ValidationError{Name: "group_block_list", err: errors.New(`ent: missing required field "Wx.group_block_list"`)}
+	}
 	if _, ok := wc.mutation.AgentID(); !ok {
 		return &ValidationError{Name: "agent", err: errors.New(`ent: missing required edge "Wx.agent"`)}
 	}
@@ -519,6 +555,22 @@ func (wc *WxCreate) createSpec() (*Wx, *sqlgraph.CreateSpec) {
 		_spec.SetField(wx.FieldAPIKey, field.TypeString, value)
 		_node.APIKey = value
 	}
+	if value, ok := wc.mutation.AllowList(); ok {
+		_spec.SetField(wx.FieldAllowList, field.TypeJSON, value)
+		_node.AllowList = value
+	}
+	if value, ok := wc.mutation.GroupAllowList(); ok {
+		_spec.SetField(wx.FieldGroupAllowList, field.TypeJSON, value)
+		_node.GroupAllowList = value
+	}
+	if value, ok := wc.mutation.BlockList(); ok {
+		_spec.SetField(wx.FieldBlockList, field.TypeJSON, value)
+		_node.BlockList = value
+	}
+	if value, ok := wc.mutation.GroupBlockList(); ok {
+		_spec.SetField(wx.FieldGroupBlockList, field.TypeJSON, value)
+		_node.GroupBlockList = value
+	}
 	if nodes := wc.mutation.ServerIDs(); len(nodes) > 0 {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,
@@ -845,6 +897,54 @@ func (u *WxUpsert) ClearAPIKey() *WxUpsert {
 	return u
 }
 
+// SetAllowList sets the "allow_list" field.
+func (u *WxUpsert) SetAllowList(v []string) *WxUpsert {
+	u.Set(wx.FieldAllowList, v)
+	return u
+}
+
+// UpdateAllowList sets the "allow_list" field to the value that was provided on create.
+func (u *WxUpsert) UpdateAllowList() *WxUpsert {
+	u.SetExcluded(wx.FieldAllowList)
+	return u
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (u *WxUpsert) SetGroupAllowList(v []string) *WxUpsert {
+	u.Set(wx.FieldGroupAllowList, v)
+	return u
+}
+
+// UpdateGroupAllowList sets the "group_allow_list" field to the value that was provided on create.
+func (u *WxUpsert) UpdateGroupAllowList() *WxUpsert {
+	u.SetExcluded(wx.FieldGroupAllowList)
+	return u
+}
+
+// SetBlockList sets the "block_list" field.
+func (u *WxUpsert) SetBlockList(v []string) *WxUpsert {
+	u.Set(wx.FieldBlockList, v)
+	return u
+}
+
+// UpdateBlockList sets the "block_list" field to the value that was provided on create.
+func (u *WxUpsert) UpdateBlockList() *WxUpsert {
+	u.SetExcluded(wx.FieldBlockList)
+	return u
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (u *WxUpsert) SetGroupBlockList(v []string) *WxUpsert {
+	u.Set(wx.FieldGroupBlockList, v)
+	return u
+}
+
+// UpdateGroupBlockList sets the "group_block_list" field to the value that was provided on create.
+func (u *WxUpsert) UpdateGroupBlockList() *WxUpsert {
+	u.SetExcluded(wx.FieldGroupBlockList)
+	return u
+}
+
 // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
 // Using this option is equivalent to using:
 //
@@ -1176,6 +1276,62 @@ func (u *WxUpsertOne) ClearAPIKey() *WxUpsertOne {
 	})
 }
 
+// SetAllowList sets the "allow_list" field.
+func (u *WxUpsertOne) SetAllowList(v []string) *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.SetAllowList(v)
+	})
+}
+
+// UpdateAllowList sets the "allow_list" field to the value that was provided on create.
+func (u *WxUpsertOne) UpdateAllowList() *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateAllowList()
+	})
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (u *WxUpsertOne) SetGroupAllowList(v []string) *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.SetGroupAllowList(v)
+	})
+}
+
+// UpdateGroupAllowList sets the "group_allow_list" field to the value that was provided on create.
+func (u *WxUpsertOne) UpdateGroupAllowList() *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateGroupAllowList()
+	})
+}
+
+// SetBlockList sets the "block_list" field.
+func (u *WxUpsertOne) SetBlockList(v []string) *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.SetBlockList(v)
+	})
+}
+
+// UpdateBlockList sets the "block_list" field to the value that was provided on create.
+func (u *WxUpsertOne) UpdateBlockList() *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateBlockList()
+	})
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (u *WxUpsertOne) SetGroupBlockList(v []string) *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.SetGroupBlockList(v)
+	})
+}
+
+// UpdateGroupBlockList sets the "group_block_list" field to the value that was provided on create.
+func (u *WxUpsertOne) UpdateGroupBlockList() *WxUpsertOne {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateGroupBlockList()
+	})
+}
+
 // Exec executes the query.
 func (u *WxUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1673,6 +1829,62 @@ func (u *WxUpsertBulk) ClearAPIKey() *WxUpsertBulk {
 	})
 }
 
+// SetAllowList sets the "allow_list" field.
+func (u *WxUpsertBulk) SetAllowList(v []string) *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.SetAllowList(v)
+	})
+}
+
+// UpdateAllowList sets the "allow_list" field to the value that was provided on create.
+func (u *WxUpsertBulk) UpdateAllowList() *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateAllowList()
+	})
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (u *WxUpsertBulk) SetGroupAllowList(v []string) *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.SetGroupAllowList(v)
+	})
+}
+
+// UpdateGroupAllowList sets the "group_allow_list" field to the value that was provided on create.
+func (u *WxUpsertBulk) UpdateGroupAllowList() *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateGroupAllowList()
+	})
+}
+
+// SetBlockList sets the "block_list" field.
+func (u *WxUpsertBulk) SetBlockList(v []string) *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.SetBlockList(v)
+	})
+}
+
+// UpdateBlockList sets the "block_list" field to the value that was provided on create.
+func (u *WxUpsertBulk) UpdateBlockList() *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateBlockList()
+	})
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (u *WxUpsertBulk) SetGroupBlockList(v []string) *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.SetGroupBlockList(v)
+	})
+}
+
+// UpdateGroupBlockList sets the "group_block_list" field to the value that was provided on create.
+func (u *WxUpsertBulk) UpdateGroupBlockList() *WxUpsertBulk {
+	return u.Update(func(s *WxUpsert) {
+		s.UpdateGroupBlockList()
+	})
+}
+
 // Exec executes the query.
 func (u *WxUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 161 - 0
ent/wx_update.go

@@ -14,6 +14,7 @@ import (
 
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/dialect/sql/sqljson"
 	"entgo.io/ent/schema/field"
 )
 
@@ -296,6 +297,54 @@ func (wu *WxUpdate) ClearAPIKey() *WxUpdate {
 	return wu
 }
 
+// SetAllowList sets the "allow_list" field.
+func (wu *WxUpdate) SetAllowList(s []string) *WxUpdate {
+	wu.mutation.SetAllowList(s)
+	return wu
+}
+
+// AppendAllowList appends s to the "allow_list" field.
+func (wu *WxUpdate) AppendAllowList(s []string) *WxUpdate {
+	wu.mutation.AppendAllowList(s)
+	return wu
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (wu *WxUpdate) SetGroupAllowList(s []string) *WxUpdate {
+	wu.mutation.SetGroupAllowList(s)
+	return wu
+}
+
+// AppendGroupAllowList appends s to the "group_allow_list" field.
+func (wu *WxUpdate) AppendGroupAllowList(s []string) *WxUpdate {
+	wu.mutation.AppendGroupAllowList(s)
+	return wu
+}
+
+// SetBlockList sets the "block_list" field.
+func (wu *WxUpdate) SetBlockList(s []string) *WxUpdate {
+	wu.mutation.SetBlockList(s)
+	return wu
+}
+
+// AppendBlockList appends s to the "block_list" field.
+func (wu *WxUpdate) AppendBlockList(s []string) *WxUpdate {
+	wu.mutation.AppendBlockList(s)
+	return wu
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (wu *WxUpdate) SetGroupBlockList(s []string) *WxUpdate {
+	wu.mutation.SetGroupBlockList(s)
+	return wu
+}
+
+// AppendGroupBlockList appends s to the "group_block_list" field.
+func (wu *WxUpdate) AppendGroupBlockList(s []string) *WxUpdate {
+	wu.mutation.AppendGroupBlockList(s)
+	return wu
+}
+
 // SetServer sets the "server" edge to the Server entity.
 func (wu *WxUpdate) SetServer(s *Server) *WxUpdate {
 	return wu.SetServerID(s.ID)
@@ -448,6 +497,38 @@ func (wu *WxUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if wu.mutation.APIKeyCleared() {
 		_spec.ClearField(wx.FieldAPIKey, field.TypeString)
 	}
+	if value, ok := wu.mutation.AllowList(); ok {
+		_spec.SetField(wx.FieldAllowList, field.TypeJSON, value)
+	}
+	if value, ok := wu.mutation.AppendedAllowList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldAllowList, value)
+		})
+	}
+	if value, ok := wu.mutation.GroupAllowList(); ok {
+		_spec.SetField(wx.FieldGroupAllowList, field.TypeJSON, value)
+	}
+	if value, ok := wu.mutation.AppendedGroupAllowList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldGroupAllowList, value)
+		})
+	}
+	if value, ok := wu.mutation.BlockList(); ok {
+		_spec.SetField(wx.FieldBlockList, field.TypeJSON, value)
+	}
+	if value, ok := wu.mutation.AppendedBlockList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldBlockList, value)
+		})
+	}
+	if value, ok := wu.mutation.GroupBlockList(); ok {
+		_spec.SetField(wx.FieldGroupBlockList, field.TypeJSON, value)
+	}
+	if value, ok := wu.mutation.AppendedGroupBlockList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldGroupBlockList, value)
+		})
+	}
 	if wu.mutation.ServerCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,
@@ -792,6 +873,54 @@ func (wuo *WxUpdateOne) ClearAPIKey() *WxUpdateOne {
 	return wuo
 }
 
+// SetAllowList sets the "allow_list" field.
+func (wuo *WxUpdateOne) SetAllowList(s []string) *WxUpdateOne {
+	wuo.mutation.SetAllowList(s)
+	return wuo
+}
+
+// AppendAllowList appends s to the "allow_list" field.
+func (wuo *WxUpdateOne) AppendAllowList(s []string) *WxUpdateOne {
+	wuo.mutation.AppendAllowList(s)
+	return wuo
+}
+
+// SetGroupAllowList sets the "group_allow_list" field.
+func (wuo *WxUpdateOne) SetGroupAllowList(s []string) *WxUpdateOne {
+	wuo.mutation.SetGroupAllowList(s)
+	return wuo
+}
+
+// AppendGroupAllowList appends s to the "group_allow_list" field.
+func (wuo *WxUpdateOne) AppendGroupAllowList(s []string) *WxUpdateOne {
+	wuo.mutation.AppendGroupAllowList(s)
+	return wuo
+}
+
+// SetBlockList sets the "block_list" field.
+func (wuo *WxUpdateOne) SetBlockList(s []string) *WxUpdateOne {
+	wuo.mutation.SetBlockList(s)
+	return wuo
+}
+
+// AppendBlockList appends s to the "block_list" field.
+func (wuo *WxUpdateOne) AppendBlockList(s []string) *WxUpdateOne {
+	wuo.mutation.AppendBlockList(s)
+	return wuo
+}
+
+// SetGroupBlockList sets the "group_block_list" field.
+func (wuo *WxUpdateOne) SetGroupBlockList(s []string) *WxUpdateOne {
+	wuo.mutation.SetGroupBlockList(s)
+	return wuo
+}
+
+// AppendGroupBlockList appends s to the "group_block_list" field.
+func (wuo *WxUpdateOne) AppendGroupBlockList(s []string) *WxUpdateOne {
+	wuo.mutation.AppendGroupBlockList(s)
+	return wuo
+}
+
 // SetServer sets the "server" edge to the Server entity.
 func (wuo *WxUpdateOne) SetServer(s *Server) *WxUpdateOne {
 	return wuo.SetServerID(s.ID)
@@ -974,6 +1103,38 @@ func (wuo *WxUpdateOne) sqlSave(ctx context.Context) (_node *Wx, err error) {
 	if wuo.mutation.APIKeyCleared() {
 		_spec.ClearField(wx.FieldAPIKey, field.TypeString)
 	}
+	if value, ok := wuo.mutation.AllowList(); ok {
+		_spec.SetField(wx.FieldAllowList, field.TypeJSON, value)
+	}
+	if value, ok := wuo.mutation.AppendedAllowList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldAllowList, value)
+		})
+	}
+	if value, ok := wuo.mutation.GroupAllowList(); ok {
+		_spec.SetField(wx.FieldGroupAllowList, field.TypeJSON, value)
+	}
+	if value, ok := wuo.mutation.AppendedGroupAllowList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldGroupAllowList, value)
+		})
+	}
+	if value, ok := wuo.mutation.BlockList(); ok {
+		_spec.SetField(wx.FieldBlockList, field.TypeJSON, value)
+	}
+	if value, ok := wuo.mutation.AppendedBlockList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldBlockList, value)
+		})
+	}
+	if value, ok := wuo.mutation.GroupBlockList(); ok {
+		_spec.SetField(wx.FieldGroupBlockList, field.TypeJSON, value)
+	}
+	if value, ok := wuo.mutation.AppendedGroupBlockList(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, wx.FieldGroupBlockList, value)
+		})
+	}
 	if wuo.mutation.ServerCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,

+ 44 - 0
internal/handler/Wx/get_wx_allow_block_list_handler.go

@@ -0,0 +1,44 @@
+package Wx
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Wx"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wx/getWxAllowBlockList Wx GetWxAllowBlockList
+//
+// Get wx allow and block list | 获取黑白名单列表
+//
+// Get wx allow and block list | 获取黑白名单列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: AllowBlockListReq
+//
+// Responses:
+//  200: AllowBlockListResp
+
+func GetWxAllowBlockListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Wx.NewGetWxAllowBlockListLogic(r.Context(), svcCtx)
+		resp, err := l.GetWxAllowBlockList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Wx/update_block_and_allow_list_handler.go

@@ -0,0 +1,44 @@
+package Wx
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Wx"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wx/updateBlockAndAllowList Wx UpdateBlockAndAllowList
+//
+// Update wx information | 更新黑白名单
+//
+// Update wx information | 更新黑白名单
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: WxInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func UpdateBlockAndAllowListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.UpdateBlockAndAllowListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Wx.NewUpdateBlockAndAllowListLogic(r.Context(), svcCtx)
+		resp, err := l.UpdateBlockAndAllowList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/get_employee_detail_handler.go

@@ -0,0 +1,44 @@
+package employee
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/employee"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /employee/detail employee GetEmployeeDetail
+//
+// Get employee by ID | 通过ID获取Employee
+//
+// Get employee by ID | 通过ID获取Employee
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: EmployeeInfoResp
+
+func GetEmployeeDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := employee.NewGetEmployeeDetailLogic(r.Context(), svcCtx)
+		resp, err := l.GetEmployeeDetail(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/get_employee_search_handler.go

@@ -0,0 +1,44 @@
+package employee
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/employee"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /employee/search employee GetEmployeeSearch
+//
+// Get employee list | 获取Employee列表
+//
+// Get employee list | 获取Employee列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: EmployeeListReq
+//
+// Responses:
+//  200: EmployeeListResp
+
+func GetEmployeeSearchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.EmployeeListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := employee.NewGetEmployeeSearchLogic(r.Context(), svcCtx)
+		resp, err := l.GetEmployeeSearch(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/get_employee_search_test_handler.go

@@ -0,0 +1,44 @@
+package employee
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/employee"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /employee/search/test employee GetEmployeeSearchTest
+//
+// Get employee list | 获取Employee列表
+//
+// Get employee list | 获取Employee列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: EmployeeListReq
+//
+// Responses:
+//  200: EmployeeListResp
+
+func GetEmployeeSearchTestHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.EmployeeListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := employee.NewGetEmployeeSearchTestLogic(r.Context(), svcCtx)
+		resp, err := l.GetEmployeeSearchTest(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/label/get_label_batch_select_list_handler.go

@@ -0,0 +1,44 @@
+package label
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/label"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /label/batch_select_list label GetLabelBatchSelectList
+//
+// Get label select list | 获取Label群发列表
+//
+// Get label select list | 获取Label群发列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: LabelListReq
+//
+// Responses:
+//  200: LabelBatchSelectListResp
+
+func GetLabelBatchSelectListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.LabelListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := label.NewGetLabelBatchSelectListLogic(r.Context(), svcCtx)
+		resp, err := l.GetLabelBatchSelectList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 124 - 75
internal/handler/routes.go

@@ -99,6 +99,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				},
 				{
 					Method:  http.MethodPost,
+					Path:    "/wx/updateBlockAndAllowList",
+					Handler: Wx.UpdateBlockAndAllowListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
 					Path:    "/wx/delete",
 					Handler: Wx.DeleteWxHandler(serverCtx),
 				},
@@ -109,6 +114,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				},
 				{
 					Method:  http.MethodPost,
+					Path:    "/wx/getWxAllowBlockList",
+					Handler: Wx.GetWxAllowBlockListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
 					Path:    "/wx",
 					Handler: Wx.GetWxByIdHandler(serverCtx),
 				},
@@ -187,6 +197,50 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/create",
+					Handler: label_relationship.CreateLabelRelationshipHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/update",
+					Handler: label_relationship.UpdateLabelRelationshipHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/update_contact_labels",
+					Handler: label_relationship.UpdateLabelRelationshipsHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/batch_update_contact_labels",
+					Handler: label_relationship.BatchUpdateLabelRelationshipsHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/delete",
+					Handler: label_relationship.DeleteLabelRelationshipHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship/list",
+					Handler: label_relationship.GetLabelRelationshipListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/label_relationship",
+					Handler: label_relationship.GetLabelRelationshipByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
 		[]rest.Route{
 			{
 				Method:  http.MethodPost,
@@ -280,50 +334,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 			[]rest.Route{
 				{
 					Method:  http.MethodPost,
-					Path:    "/label_relationship/create",
-					Handler: label_relationship.CreateLabelRelationshipHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship/update",
-					Handler: label_relationship.UpdateLabelRelationshipHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship/update_contact_labels",
-					Handler: label_relationship.UpdateLabelRelationshipsHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship/batch_update_contact_labels",
-					Handler: label_relationship.BatchUpdateLabelRelationshipsHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship/delete",
-					Handler: label_relationship.DeleteLabelRelationshipHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship/list",
-					Handler: label_relationship.GetLabelRelationshipListHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/label_relationship",
-					Handler: label_relationship.GetLabelRelationshipByIdHandler(serverCtx),
-				},
-			}...,
-		),
-		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
-	)
-
-	server.AddRoutes(
-		rest.WithMiddlewares(
-			[]rest.Middleware{serverCtx.Authority},
-			[]rest.Route{
-				{
-					Method:  http.MethodPost,
 					Path:    "/message/create",
 					Handler: Message.CreateMessageHandler(serverCtx),
 				},
@@ -383,6 +393,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				},
 				{
 					Method:  http.MethodPost,
+					Path:    "/label/batch_select_list",
+					Handler: label.GetLabelBatchSelectListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
 					Path:    "/label/contacts",
 					Handler: label.GetLabelContactsHandler(serverCtx),
 				},
@@ -685,6 +700,26 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		[]rest.Route{
+			{
+				Method:  http.MethodPost,
+				Path:    "/employee/search",
+				Handler: employee.GetEmployeeSearchHandler(serverCtx),
+			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/employee/search/test",
+				Handler: employee.GetEmployeeSearchTestHandler(serverCtx),
+			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/employee/detail",
+				Handler: employee.GetEmployeeDetailHandler(serverCtx),
+			},
+		},
+	)
+
+	server.AddRoutes(
 		rest.WithMiddlewares(
 			[]rest.Middleware{serverCtx.Authority},
 			[]rest.Route{
@@ -804,33 +839,57 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		[]rest.Route{
 			{
 				Method:  http.MethodPost,
-				Path:    "/token/create",
-				Handler: token.CreateTokenHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodPost,
-				Path:    "/token/update",
-				Handler: token.UpdateTokenHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodPost,
-				Path:    "/token/delete",
-				Handler: token.DeleteTokenHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodPost,
-				Path:    "/token/list",
-				Handler: token.GetTokenListHandler(serverCtx),
+				Path:    "/token/check",
+				Handler: token.CheckTokenHandler(serverCtx),
 			},
+		},
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/token/third/create",
+					Handler: token.CreateTokenHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/token/third/update",
+					Handler: token.UpdateTokenHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/token/third/delete",
+					Handler: token.DeleteTokenHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/token/third/list",
+					Handler: token.GetTokenListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/token/third/detail",
+					Handler: token.GetTokenByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		[]rest.Route{
 			{
 				Method:  http.MethodPost,
-				Path:    "/token",
-				Handler: token.GetTokenByIdHandler(serverCtx),
+				Path:    "/category/list",
+				Handler: category.GetCategoryListHandler(serverCtx),
 			},
 			{
 				Method:  http.MethodPost,
-				Path:    "/token/check",
-				Handler: token.CheckTokenHandler(serverCtx),
+				Path:    "/category",
+				Handler: category.GetCategoryByIdHandler(serverCtx),
 			},
 		},
 	)
@@ -854,16 +913,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/category/delete",
 					Handler: category.DeleteCategoryHandler(serverCtx),
 				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/category/list",
-					Handler: category.GetCategoryListHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/category",
-					Handler: category.GetCategoryByIdHandler(serverCtx),
-				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

+ 1 - 1
internal/logic/WechatServer/update_server_logic.go

@@ -41,6 +41,6 @@ func (l *UpdateServerLogic) UpdateServer(req *types.ServerInfo) (*types.BaseMsgR
 		"private_ip": req.PrivateIp,
 		"admin_port": req.AdminPort,
 	}
-	l.svcCtx.Rds.HSet(l.ctx, "server_info", *req.Id, data)
+	l.svcCtx.Rds.HSet(l.ctx, "server_info", req.Id, data)
 	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
 }

+ 10 - 6
internal/logic/Wx/check_wx_logic.go

@@ -104,12 +104,16 @@ func (l *CheckWxLogic) CheckWx(req *types.WxInfo) (resp *types.BaseMsgResp, err
 				Save(l.ctx)
 
 			data := map[string]interface{}{
-				"nickname":  selfInfo.Nickname,
-				"server_id": wxInfo.ServerID,
-				"port":      wxInfo.Port,
-				"api_base":  wxInfo.APIBase,
-				"api_key":   wxInfo.APIKey,
-				"agent_id":  wxInfo.AgentID,
+				"nickname":         selfInfo.Nickname,
+				"server_id":        wxInfo.ServerID,
+				"port":             wxInfo.Port,
+				"api_base":         wxInfo.APIBase,
+				"api_key":          wxInfo.APIKey,
+				"agent_id":         wxInfo.AgentID,
+				"allow_list":       wxInfo.AllowList,
+				"group_allow_list": wxInfo.GroupAllowList,
+				"block_list":       wxInfo.BlockList,
+				"group_block_list": wxInfo.GroupBlockList,
 			}
 			l.svcCtx.Rds.HSet(l.ctx, "wx_info", selfInfo.Wxid, data)
 		}

+ 141 - 0
internal/logic/Wx/get_wx_allow_block_list_logic.go

@@ -0,0 +1,141 @@
+package Wx
+
+import (
+	"context"
+	"wechat-api/ent"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/wx"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWxAllowBlockListLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetWxAllowBlockListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWxAllowBlockListLogic {
+	return &GetWxAllowBlockListLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetWxAllowBlockListLogic) GetWxAllowBlockList(req *types.IDReq) (resp *types.AllowBlockListResp, err error) {
+	isAdmin := l.ctx.Value("isAdmin").(bool)
+	var data *ent.Wx
+	if isAdmin {
+		data, err = l.svcCtx.DB.Wx.Query().
+			Where(
+				wx.IDEQ(req.Id),
+			).
+			Only(l.ctx)
+	} else {
+		organizationId := l.ctx.Value("organizationId").(uint64)
+		data, err = l.svcCtx.DB.Wx.Query().
+			Where(
+				wx.IDEQ(req.Id),                   // Filter by ID
+				wx.OrganizationID(organizationId), // Additional filter by organizationId
+			).
+			Only(l.ctx)
+	}
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	wxid := data.Wxid
+	resp = &types.AllowBlockListResp{}
+	resp.Data = types.AllowBlockListRespData{}
+
+	allowListData := make([]*types.AllowBlockData, 0)
+	if data.AllowList == nil || len(data.AllowList) == 0 || data.AllowList[0] == "ALL" {
+		allowListData = append(allowListData,
+			&types.AllowBlockData{
+				Wxid:     "ALL",
+				Nickname: "全部允许",
+			})
+	} else if len(data.AllowList) > 0 {
+		allowList, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(wxid), contact.WxidIn(data.AllowList...)).All(l.ctx)
+		if allowList != nil {
+			for _, av := range allowList {
+				allowListData = append(allowListData,
+					&types.AllowBlockData{
+						Wxid:     av.Wxid,
+						Nickname: av.Nickname,
+					})
+			}
+		}
+	}
+	resp.Data.AllowList = allowListData
+
+	groupAllowListData := make([]*types.AllowBlockData, 0)
+	if data.GroupAllowList == nil || len(data.GroupAllowList) == 0 || data.GroupAllowList[0] == "ALL" {
+		groupAllowListData = append(groupAllowListData,
+			&types.AllowBlockData{
+				Wxid:     "ALL",
+				Nickname: "全部允许",
+			})
+	} else if len(data.GroupAllowList) > 0 {
+		groupAllowList, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(wxid), contact.WxidIn(data.GroupAllowList...)).All(l.ctx)
+		if groupAllowList != nil {
+			for _, av := range groupAllowList {
+				groupAllowListData = append(groupAllowListData,
+					&types.AllowBlockData{
+						Wxid:     av.Wxid,
+						Nickname: av.Nickname,
+					})
+			}
+		}
+	}
+	resp.Data.GroupAllowList = groupAllowListData
+	blockListData := make([]*types.AllowBlockData, 0)
+	if data.BlockList != nil && len(data.BlockList) > 0 {
+		if data.BlockList[0] == "ALL" {
+			blockListData = append(blockListData,
+				&types.AllowBlockData{
+					Wxid:     "ALL",
+					Nickname: "全部禁用",
+				})
+		} else {
+			blockList, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(wxid), contact.WxidIn(data.BlockList...)).All(l.ctx)
+			if blockList != nil {
+				for _, av := range blockList {
+					blockListData = append(blockListData,
+						&types.AllowBlockData{
+							Wxid:     av.Wxid,
+							Nickname: av.Nickname,
+						})
+				}
+			}
+		}
+	}
+	resp.Data.BlockList = blockListData
+
+	groupBlockListData := make([]*types.AllowBlockData, 0)
+	if data.GroupBlockList != nil && len(data.GroupBlockList) > 0 {
+		if data.GroupBlockList[0] == "ALL" {
+			groupBlockListData = append(groupBlockListData,
+				&types.AllowBlockData{
+					Wxid:     "ALL",
+					Nickname: "全部禁用",
+				})
+		} else {
+			groupBlockList, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(wxid), contact.WxidIn(data.GroupBlockList...)).All(l.ctx)
+			if groupBlockList != nil {
+				for _, av := range groupBlockList {
+					groupBlockListData = append(groupBlockListData,
+						&types.AllowBlockData{
+							Wxid:     av.Wxid,
+							Nickname: av.Nickname,
+						})
+				}
+			}
+		}
+	}
+	resp.Data.GroupBlockList = groupBlockListData
+	return resp, nil
+}

+ 0 - 5
internal/logic/Wx/get_wx_list_logic.go

@@ -3,9 +3,6 @@ package Wx
 import (
 	"context"
 	"github.com/suyuan32/simple-admin-core/rpc/types/core"
-	"math/rand"
-	"strconv"
-	"time"
 	"wechat-api/ent"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/wx"
@@ -133,10 +130,8 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 			}
 		} 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)
 			}
 		}

+ 53 - 0
internal/logic/Wx/update_block_and_allow_list_logic.go

@@ -0,0 +1,53 @@
+package Wx
+
+import (
+	"context"
+	"fmt"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/wx"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateBlockAndAllowListLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewUpdateBlockAndAllowListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateBlockAndAllowListLogic {
+	return &UpdateBlockAndAllowListLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *UpdateBlockAndAllowListLogic) UpdateBlockAndAllowList(req *types.UpdateBlockAndAllowListReq) (resp *types.BaseMsgResp, err error) {
+	err = l.svcCtx.DB.Wx.UpdateOneID(*req.Id).
+		SetNotNilAllowList(req.AllowList).
+		SetNotNilGroupAllowList(req.GroupAllowList).
+		SetNotNilBlockList(req.BlockList).
+		SetNotNilGroupBlockList(req.GroupBlockList).
+		Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	wxinfo, err := l.svcCtx.DB.Wx.Query().
+		Where(
+			wx.IDEQ(*req.Id),
+		).
+		WithAgent().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	fmt.Printf("------------------------wxinfo.Wxid------------------------: %+v\n", wxinfo.Wxid)
+	l.svcCtx.Rds.HDel(l.ctx, "wx_info", wxinfo.Wxid)
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 114 - 33
internal/logic/batch_msg/create_batch_msg_logic.go

@@ -7,10 +7,10 @@ import (
 	"strings"
 	"time"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/label"
 
 	"wechat-api/ent"
 	"wechat-api/ent/contact"
-	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -40,16 +40,24 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 
 	var err error
 
-	all := false
-	for _, labelName := range req.Labels {
-		if strings.EqualFold(labelName, "all") || strings.EqualFold(labelName, "全部") {
-			all = true
-			tagstring := "all"
-			req.Tag = &tagstring
+	var tagstring, tag string
+	allContact, allGroup := false, false
+	tagIdArray := make([]uint64, 0)
+	for _, labelId := range req.Labels {
+		tagIdArray = append(tagIdArray, labelId)
+		if labelId == uint64(0) { //全部
+			allContact = true
+		}
+	}
+	for _, labelId := range req.GroupLabels {
+		tagIdArray = append(tagIdArray, labelId)
+		if labelId == uint64(0) { //全部
+			allGroup = true
 		}
 	}
 
 	startTime := time.Now()
+	sendNow := true
 	// req.StartTimeStr 不为nil并且不为空
 	if req.StartTimeStr != nil && *req.StartTimeStr != "" {
 		// 将 req.StartTimeStr 转换为 req.StartTime
@@ -59,6 +67,7 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 			l.Logger.Errorf("时间字符串转换错误: %v", err)
 			return nil, err
 		}
+		sendNow = false
 	}
 
 	// 把 req.Msg 字符串的内容 json_decode 到 msgArray
@@ -93,63 +102,93 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 		}
 	}
 
-	tagstring := strings.Join(req.Labels, ",")
-	req.Tag = &tagstring
-
-	userlist := make([]*ent.Contact, 0)
+	userList, groupList := make([]*ent.Contact, 0), make([]*ent.Contact, 0)
 
-	if all {
+	tagMap := make(map[string][]uint64)
+	if allContact && allGroup {
 		// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为1或2的数据
-		userlist, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(*req.Fromwxid), contact.TypeIn(1, 2)).All(l.ctx)
+		userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(*req.Fromwxid), contact.TypeIn(1, 2)).All(l.ctx)
 		if err != nil {
 			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 		}
-	} else {
-		// 获取 label 表中 name 为 tags的记录
-		labids, err := l.svcCtx.DB.Label.Query().Where(label.NameIn(req.Labels...)).IDs(l.ctx)
-		if err != nil {
-			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-		}
-		//l.Logger.Infof("CreateBatchMsgLogic labids= %v", labids)
 
-		// 获取 label_relationship 表中,label_id 等于 labids 的 contact_id
-		labelrelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.LabelIDIn(labids...)).All(l.ctx)
+		tagids := make([]uint64, 0, 1)
+		tagids = append(tagids, uint64(0))
+		tagMap["contact_tag"] = tagids
+		tagMap["group_tag"] = tagids
+		tagByte, err := json.Marshal(tagMap)
 		if err != nil {
 			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 		}
-		contact_ids := make([]uint64, 0)
-		for _, labelrelationship := range labelrelationships {
-			contact_ids = append(contact_ids, labelrelationship.ContactID)
+		tagstring = string(tagByte)
+		tag = "全部"
+	} else {
+		if allContact { // 所有联系人
+			// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为1的数据
+			userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(*req.Fromwxid), contact.TypeEQ(1)).All(l.ctx)
+			if err != nil {
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+			tag = "全部联系人"
+		} else {
+			userList, err = getContactList(l, req.Labels, *req.Fromwxid, 1)
+			if err != nil {
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
 		}
-		//l.Logger.Infof("CreateBatchMsgLogic contact_ids= %v", contact_ids)
 
-		if len(contact_ids) > 0 {
-			// 获取 contact 表中 wx_wxid 等于 req.Fromwxid 并且 id 等于 contact_ids 并且 type 为1或2 的数据
-			userlist, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(*req.Fromwxid), contact.IDIn(contact_ids...), contact.TypeIn(1, 2)).All(l.ctx)
+		if allGroup { //所有群
+			// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为2的数据
+			groupList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(*req.Fromwxid), contact.TypeEQ(2)).All(l.ctx)
+			if err != nil {
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+			tag = "全部群"
+		} else {
+			groupList, err = getContactList(l, req.GroupLabels, *req.Fromwxid, 2)
 			if err != nil {
 				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 			}
-			//l.Logger.Infof("CreateBatchMsgLogic userlist= %v", userlist)
 		}
+
+		tagMap["contact_tag"] = req.Labels
+		tagMap["group_tag"] = req.GroupLabels
+		tagByte, err := json.Marshal(tagMap)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+		tagstring = string(tagByte)
+		tagArray := getLabelListByIds(l, req.Labels, req.GroupLabels)
+		if tag != "" {
+			tagArray = append(tagArray, tag)
+		}
+		tag = strings.Join(tagArray, ",")
 	}
 	// 这里是根据userlist 和 批量消息数 获得最终待发送消息总数
-	total := int32(len(userlist)) * int32(len(msgActionList))
+	total := int32(len(userList))*int32(len(msgActionList)) + int32(len(groupList))*int32(len(msgActionList))
 
 	if total == 0 {
-		return &types.BaseMsgResp{Msg: errormsg.TargetNotFound}, nil
+		return &types.BaseMsgResp{Msg: "未查询到收信人,请重新选择", Code: 3}, nil
 	}
 
 	uuid := uuidx.NewUUID()
 	batchNo := uuid.String()
 
+	var sendTime *time.Time
+	if !sendNow {
+		sendTime = &startTime
+	}
+
 	_, err = l.svcCtx.DB.BatchMsg.Create().
 		SetNotNilBatchNo(&batchNo).
 		SetNotNilFromwxid(req.Fromwxid).
 		SetNotNilMsg(req.Msg).
-		SetNotNilTag(req.Tag).
+		SetNotNilTag(&tag).
+		SetNotNilTagids(&tagstring).
 		SetTotal(total).
 		SetNotNilTaskName(req.TaskName).
 		SetNotNilStartTime(&startTime).
+		SetNillableSendTime(sendTime).
 		SetNotNilType(req.Type).
 		SetNotNilOrganizationID(&organizationId).
 		Save(l.ctx)
@@ -160,3 +199,45 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 
 	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
 }
+
+func getContactList(l *CreateBatchMsgLogic, labels []uint64, fromWxId string, stype int) ([]*ent.Contact, error) {
+	// 获取 label_relationship 表中,label_id 等于 labids 的 contact_id
+	labelrelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.LabelIDIn(labels...)).All(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
+	contact_ids := make([]uint64, 0, len(labelrelationships))
+	for _, labelrelationship := range labelrelationships {
+		contact_ids = append(contact_ids, labelrelationship.ContactID)
+	}
+	userList := make([]*ent.Contact, 0)
+
+	if len(contact_ids) > 0 {
+		// 获取 contact 表中 wx_wxid 等于 req.Fromwxid 并且 id 等于 contact_ids 并且 type 为1或2 的数据
+		userList, err = l.svcCtx.DB.Contact.Query().Where(contact.WxWxid(fromWxId), contact.IDIn(contact_ids...), contact.TypeEQ(stype)).All(l.ctx)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
+		}
+	}
+
+	return userList, nil
+}
+
+func getLabelListByIds(l *CreateBatchMsgLogic, labels, groupLabels []uint64) []string {
+	result := make([]string, 0)
+	labels = append(labels, groupLabels...)
+	if len(labels) > 0 {
+		contacts, err := l.svcCtx.DB.Label.Query().Where(
+			label.IDIn(labels...),
+		).Select("name").All(l.ctx)
+		l.Logger.Infof("contacts=%v", contacts)
+		if err != nil {
+			return result
+		}
+		for _, val := range contacts {
+			result = append(result, val.Name)
+		}
+	}
+
+	return result
+}

+ 13 - 0
internal/logic/batch_msg/get_batch_msg_by_id_logic.go

@@ -2,6 +2,7 @@ package batch_msg
 
 import (
 	"context"
+	"encoding/json"
 	"github.com/zeromicro/go-zero/core/errorx"
 	"wechat-api/ent"
 	"wechat-api/ent/batchmsg"
@@ -41,6 +42,15 @@ func (l *GetBatchMsgByIdLogic) GetBatchMsgById(req *types.IDReq) (*types.BatchMs
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	labels, groupLables := make([]uint64, 0), make([]uint64, 0)
+	tagMap := make(map[string][]uint64)
+	err = json.Unmarshal([]byte(data.Tagids), &tagMap)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	labels = tagMap["contact_tag"]
+	groupLables = tagMap["group_tag"]
+
 	return &types.BatchMsgInfoResp{
 		BaseDataInfo: types.BaseDataInfo{
 			Code: 0,
@@ -64,7 +74,10 @@ func (l *GetBatchMsgByIdLogic) GetBatchMsgById(req *types.IDReq) (*types.BatchMs
 			Type:         &data.Type,
 			StartTime:    pointy.GetUnixMilliPointer(data.StartTime.UnixMilli()),
 			StopTime:     pointy.GetUnixMilliPointer(data.StopTime.UnixMilli()),
+			SendTime:     pointy.GetUnixMilliPointer(data.SendTime.UnixMilli()),
 			StartTimeStr: pointy.GetPointer(data.StartTime.Format("2006-01-02 15:04:05")),
+			Labels:       labels,
+			GroupLabels:  groupLables,
 		},
 	}, nil
 }

+ 3 - 0
internal/logic/contact/get_contact_list_logic.go

@@ -69,6 +69,9 @@ func (l *GetContactListLogic) GetContactList(req *types.ContactListReq) (*types.
 	if req.Account != nil {
 		predicates = append(predicates, contact.AccountContains(*req.Account))
 	}
+	if req.Nickname != nil {
+		predicates = append(predicates, contact.NicknameContains(*req.Nickname))
+	}
 	if req.Type != nil {
 		predicates = append(predicates, contact.TypeEQ(*req.Type))
 	}

+ 137 - 0
internal/logic/employee/get_employee_detail_logic.go

@@ -0,0 +1,137 @@
+package employee
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/employeeconfig"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetEmployeeDetailLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetEmployeeDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEmployeeDetailLogic {
+	return &GetEmployeeDetailLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetEmployeeDetailLogic) GetEmployeeDetail(req *types.IDReq) (*types.EmployeeInfoResp, error) {
+	//organizationId := l.ctx.Value("organizationId").(uint64)
+
+	data, err := l.svcCtx.DB.Employee.Query().WithEmWorkExperiences().WithEmTutorial().Where(employee.ID(req.Id)).Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	workExperience := make([]types.WorkExperienceInfo, 0, len(data.Edges.EmWorkExperiences))
+	for _, work := range data.Edges.EmWorkExperiences {
+		workExperience = append(workExperience, types.WorkExperienceInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &work.ID,
+				CreatedAt: pointy.GetPointer(work.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(work.UpdatedAt.UnixMilli()),
+			},
+			EmployeeId:   &work.EmployeeID,
+			Company:      &work.Company,
+			StartDate:    pointy.GetPointer(work.StartDate.UnixMilli()),
+			StartDateStr: pointy.GetPointer(work.StartDate.Format("2006-01-02 15:04:05")),
+			EndDate:      pointy.GetPointer(work.EndDate.UnixMilli()),
+			EndDateStr:   pointy.GetPointer(work.EndDate.Format("2006-01-02 15:04:05")),
+			Experience:   &work.Experience,
+		})
+	}
+
+	tutorial := make([]types.TutorialInfo, 0, len(data.Edges.EmTutorial))
+	for _, tt := range data.Edges.EmTutorial {
+		tutorial = append(tutorial, types.TutorialInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &tt.ID,
+				CreatedAt: pointy.GetPointer(tt.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(tt.UpdatedAt.UnixMilli()),
+			},
+			EmployeeId: &tt.EmployeeID,
+			Content:    &tt.Content,
+			Title:      &tt.Title,
+			Index:      &tt.Index,
+		})
+	}
+
+	// 分别获得 scene 和 switch_in 的列表
+	sceneList := getEmployeeDetail(l, data.Scene)
+	switchInList := getEmployeeDetail(l, data.SwitchIn)
+
+	return &types.EmployeeInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.EmployeeInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &data.ID,
+				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+			},
+			Title:            &data.Title,
+			Avatar:           &data.Avatar,
+			Tags:             &data.Tags,
+			HireCount:        &data.HireCount,
+			ServiceCount:     &data.ServiceCount,
+			AchievementCount: &data.AchievementCount,
+			Intro:            &data.Intro,
+			Estimate:         &data.Estimate,
+			Skill:            &data.Skill,
+			AbilityType:      &data.AbilityType,
+			Scene:            &data.Scene,
+			SceneList:        sceneList,
+			Tutorial:         tutorial,
+			SwitchIn:         &data.SwitchIn,
+			SwitchInList:     switchInList,
+			VideoUrl:         &data.VideoURL,
+			WorkExperience:   workExperience,
+			CategoryId:       &data.CategoryID,
+		},
+	}, nil
+}
+
+func getEmployeeDetail(l *GetEmployeeDetailLogic, ids string) []types.EmployeeConfigInfo {
+	sceneList := make([]types.EmployeeConfigInfo, 0)
+
+	sceneIds := FormatIds(ids)
+
+	if len(sceneIds) == 0 {
+		return sceneList
+	}
+
+	employeeConfigList, err := l.svcCtx.DB.EmployeeConfig.Query().Where(
+		employeeconfig.IDIn(sceneIds...),
+	).All(l.ctx)
+
+	if err == nil && len(employeeConfigList) > 0 {
+		for _, val := range employeeConfigList {
+			sceneList = append(sceneList, types.EmployeeConfigInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &val.ID,
+					CreatedAt: pointy.GetPointer(val.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(val.UpdatedAt.UnixMilli()),
+				},
+				Stype: &val.Stype,
+				Title: &val.Title,
+				Photo: &val.Photo,
+			})
+		}
+	}
+
+	return sceneList
+}

+ 9 - 9
internal/logic/employee/get_employee_list_logic.go

@@ -86,8 +86,8 @@ func (l *GetEmployeeListLogic) GetEmployeeList(req *types.EmployeeListReq) (*typ
 			})
 		}
 
-		sceneList := getEmployeeConfigListByIds(l, v.Scene)
-		switchInList := getEmployeeConfigListByIds(l, v.SwitchIn)
+		//sceneList := getEmployeeConfigListByIds(l, v.Scene)
+		//switchInList := getEmployeeConfigListByIds(l, v.SwitchIn)
 
 		resp.Data.Data = append(resp.Data.Data,
 			types.EmployeeInfo{
@@ -107,13 +107,13 @@ func (l *GetEmployeeListLogic) GetEmployeeList(req *types.EmployeeListReq) (*typ
 				Skill:            &v.Skill,
 				AbilityType:      &v.AbilityType,
 				Scene:            &v.Scene,
-				SceneList:        sceneList,
-				SwitchIn:         &v.SwitchIn,
-				SwitchInList:     switchInList,
-				Tutorial:         tutorial,
-				VideoUrl:         &v.VideoURL,
-				WorkExperience:   workExperience,
-				CategoryId:       &v.CategoryID,
+				//SceneList:        sceneList,
+				SwitchIn: &v.SwitchIn,
+				//SwitchInList:     switchInList,
+				//Tutorial:         tutorial,
+				VideoUrl: &v.VideoURL,
+				//WorkExperience:   workExperience,
+				CategoryId: &v.CategoryID,
 			})
 	}
 

+ 150 - 0
internal/logic/employee/get_employee_search_logic.go

@@ -0,0 +1,150 @@
+package employee
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/employeeconfig"
+	"wechat-api/ent/predicate"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetEmployeeSearchLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetEmployeeSearchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEmployeeSearchLogic {
+	return &GetEmployeeSearchLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetEmployeeSearchLogic) GetEmployeeSearch(req *types.EmployeeListReq) (*types.EmployeeListResp, error) {
+	//organizationId := l.ctx.Value("organizationId").(uint64)
+
+	var predicates []predicate.Employee
+	//predicates = append(predicates, employee.OrganizationIDEQ(organizationId))
+
+	if req.Title != nil && *req.Title != "" {
+		predicates = append(predicates, employee.TitleContains(*req.Title))
+	}
+	if req.CategoryId != nil && *req.CategoryId > 0 {
+		predicates = append(predicates, employee.CategoryIDEQ(*req.CategoryId))
+	}
+	data, err := l.svcCtx.DB.Employee.Query().Where(predicates...).WithEmWorkExperiences().WithEmTutorial().Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.EmployeeListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		workExperience := make([]types.WorkExperienceInfo, 0, len(v.Edges.EmWorkExperiences))
+		for _, work := range v.Edges.EmWorkExperiences {
+			workExperience = append(workExperience, types.WorkExperienceInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &work.ID,
+					CreatedAt: pointy.GetPointer(work.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(work.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId:   &work.EmployeeID,
+				Company:      &work.Company,
+				StartDate:    pointy.GetPointer(work.StartDate.UnixMilli()),
+				StartDateStr: pointy.GetPointer(work.StartDate.Format("2006-01-02 15:04:05")),
+				EndDate:      pointy.GetPointer(work.EndDate.UnixMilli()),
+				EndDateStr:   pointy.GetPointer(work.EndDate.Format("2006-01-02 15:04:05")),
+				Experience:   &work.Experience,
+			})
+		}
+
+		tutorial := make([]types.TutorialInfo, 0, len(v.Edges.EmTutorial))
+		for _, tt := range v.Edges.EmTutorial {
+			tutorial = append(tutorial, types.TutorialInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &tt.ID,
+					CreatedAt: pointy.GetPointer(tt.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(tt.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId: &tt.EmployeeID,
+				Content:    &tt.Content,
+				Title:      &tt.Title,
+				Index:      &tt.Index,
+			})
+		}
+
+		//sceneList := getEmployeeConfig(l, v.Scene)
+		//switchInList := getEmployeeConfig(l, v.SwitchIn)
+
+		resp.Data.Data = append(resp.Data.Data,
+			types.EmployeeInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &v.ID,
+					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+				},
+				Title:            &v.Title,
+				Avatar:           &v.Avatar,
+				Tags:             &v.Tags,
+				HireCount:        &v.HireCount,
+				ServiceCount:     &v.ServiceCount,
+				AchievementCount: &v.AchievementCount,
+				Intro:            &v.Intro,
+				Estimate:         &v.Estimate,
+				Skill:            &v.Skill,
+				AbilityType:      &v.AbilityType,
+				Scene:            &v.Scene,
+				//SceneList:        sceneList,
+				SwitchIn: &v.SwitchIn,
+				//SwitchInList:     switchInList,
+				//Tutorial:         tutorial,
+				VideoUrl: &v.VideoURL,
+				//WorkExperience:   workExperience,
+				CategoryId: &v.CategoryID,
+			})
+	}
+
+	return resp, nil
+}
+
+func getEmployeeConfig(l *GetEmployeeSearchLogic, ids string) []types.EmployeeConfigInfo {
+	sceneList := make([]types.EmployeeConfigInfo, 0)
+
+	sceneIds := FormatIds(ids)
+
+	if len(sceneIds) == 0 {
+		return sceneList
+	}
+
+	employeeConfigList, err := l.svcCtx.DB.EmployeeConfig.Query().Where(
+		employeeconfig.IDIn(sceneIds...),
+	).All(l.ctx)
+
+	if err == nil && len(employeeConfigList) > 0 {
+		for _, val := range employeeConfigList {
+			sceneList = append(sceneList, types.EmployeeConfigInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &val.ID,
+					CreatedAt: pointy.GetPointer(val.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(val.UpdatedAt.UnixMilli()),
+				},
+				Stype: &val.Stype,
+				Title: &val.Title,
+				Photo: &val.Photo,
+			})
+		}
+	}
+
+	return sceneList
+}

+ 150 - 0
internal/logic/employee/get_employee_search_test_logic.go

@@ -0,0 +1,150 @@
+package employee
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/employeeconfig"
+	"wechat-api/ent/predicate"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetEmployeeSearchTestLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetEmployeeSearchTestLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEmployeeSearchTestLogic {
+	return &GetEmployeeSearchTestLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetEmployeeSearchTestLogic) GetEmployeeSearchTest(req *types.EmployeeListReq) (*types.EmployeeListResp, error) {
+	//organizationId := l.ctx.Value("organizationId").(uint64)
+
+	var predicates []predicate.Employee
+	//predicates = append(predicates, employee.OrganizationIDEQ(organizationId))
+
+	if req.Title != nil && *req.Title != "" {
+		predicates = append(predicates, employee.TitleContains(*req.Title))
+	}
+	if req.CategoryId != nil && *req.CategoryId > 0 {
+		predicates = append(predicates, employee.CategoryIDEQ(*req.CategoryId))
+	}
+	data, err := l.svcCtx.DB.Employee.Query().Where(predicates...).WithEmWorkExperiences().WithEmTutorial().Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.EmployeeListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		workExperience := make([]types.WorkExperienceInfo, 0, len(v.Edges.EmWorkExperiences))
+		for _, work := range v.Edges.EmWorkExperiences {
+			workExperience = append(workExperience, types.WorkExperienceInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &work.ID,
+					CreatedAt: pointy.GetPointer(work.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(work.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId:   &work.EmployeeID,
+				Company:      &work.Company,
+				StartDate:    pointy.GetPointer(work.StartDate.UnixMilli()),
+				StartDateStr: pointy.GetPointer(work.StartDate.Format("2006-01-02 15:04:05")),
+				EndDate:      pointy.GetPointer(work.EndDate.UnixMilli()),
+				EndDateStr:   pointy.GetPointer(work.EndDate.Format("2006-01-02 15:04:05")),
+				Experience:   &work.Experience,
+			})
+		}
+
+		tutorial := make([]types.TutorialInfo, 0, len(v.Edges.EmTutorial))
+		for _, tt := range v.Edges.EmTutorial {
+			tutorial = append(tutorial, types.TutorialInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &tt.ID,
+					CreatedAt: pointy.GetPointer(tt.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(tt.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId: &tt.EmployeeID,
+				Content:    &tt.Content,
+				Title:      &tt.Title,
+				Index:      &tt.Index,
+			})
+		}
+
+		sceneList := getEmployeeConfig2(l, v.Scene)
+		switchInList := getEmployeeConfig2(l, v.SwitchIn)
+
+		resp.Data.Data = append(resp.Data.Data,
+			types.EmployeeInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &v.ID,
+					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+				},
+				Title:            &v.Title,
+				Avatar:           &v.Avatar,
+				Tags:             &v.Tags,
+				HireCount:        &v.HireCount,
+				ServiceCount:     &v.ServiceCount,
+				AchievementCount: &v.AchievementCount,
+				Intro:            &v.Intro,
+				Estimate:         &v.Estimate,
+				Skill:            &v.Skill,
+				AbilityType:      &v.AbilityType,
+				Scene:            &v.Scene,
+				SceneList:        sceneList,
+				SwitchIn:         &v.SwitchIn,
+				SwitchInList:     switchInList,
+				Tutorial:         tutorial,
+				VideoUrl:         &v.VideoURL,
+				WorkExperience:   workExperience,
+				CategoryId:       &v.CategoryID,
+			})
+	}
+
+	return resp, nil
+}
+
+func getEmployeeConfig2(l *GetEmployeeSearchTestLogic, ids string) []types.EmployeeConfigInfo {
+	sceneList := make([]types.EmployeeConfigInfo, 0)
+
+	sceneIds := FormatIds(ids)
+
+	if len(sceneIds) == 0 {
+		return sceneList
+	}
+
+	employeeConfigList, err := l.svcCtx.DB.EmployeeConfig.Query().Where(
+		employeeconfig.IDIn(sceneIds...),
+	).All(l.ctx)
+
+	if err == nil && len(employeeConfigList) > 0 {
+		for _, val := range employeeConfigList {
+			sceneList = append(sceneList, types.EmployeeConfigInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &val.ID,
+					CreatedAt: pointy.GetPointer(val.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(val.UpdatedAt.UnixMilli()),
+				},
+				Stype: &val.Stype,
+				Title: &val.Title,
+				Photo: &val.Photo,
+			})
+		}
+	}
+
+	return sceneList
+}

+ 81 - 0
internal/logic/label/get_label_batch_select_list_logic.go

@@ -0,0 +1,81 @@
+package label
+
+import (
+	"context"
+	"fmt"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/label"
+	"wechat-api/ent/predicate"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetLabelBatchSelectListLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetLabelBatchSelectListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLabelBatchSelectListLogic {
+	return &GetLabelBatchSelectListLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetLabelBatchSelectListLogic) GetLabelBatchSelectList(req *types.LabelListReq) (resp *types.LabelBatchSelectListResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+	fmt.Printf("------------------------organizationId------------------------: %+v\n", organizationId)
+	var predicates []predicate.Label
+	predicates = append(predicates, label.OrganizationIDEQ(organizationId))
+	if req.Name != nil {
+		predicates = append(predicates, label.NameContains(*req.Name))
+	}
+	if req.From != nil {
+		predicates = append(predicates, label.FromEQ(*req.From))
+	}
+	if req.Mode != nil {
+		predicates = append(predicates, label.ModeEQ(*req.Mode))
+	}
+
+	data, err := l.svcCtx.DB.Label.Query().Where(predicates...).Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	var allId uint64 = 0
+	allName := "全部"
+	resp = &types.LabelBatchSelectListResp{}
+	var contact []types.LabelSelectListInfo
+	contact = append(contact,
+		types.LabelSelectListInfo{
+			Value: &allId,
+			Label: &allName,
+		})
+	var group []types.LabelSelectListInfo
+	resp.Msg = errormsg.Success
+
+	for _, v := range data.List {
+		if v.Type == 1 {
+			contact = append(contact,
+				types.LabelSelectListInfo{
+					Value: &v.ID,
+					Label: &v.Name,
+				})
+		} else {
+			group = append(group,
+				types.LabelSelectListInfo{
+					Value: &v.ID,
+					Label: &v.Name,
+				})
+		}
+	}
+	resp.Data.Contact = contact
+	resp.Data.Group = group
+
+	return resp, nil
+}

+ 9 - 2
internal/logic/message_records/get_message_records_list_logic.go

@@ -34,8 +34,15 @@ func (l *GetMessageRecordsListLogic) GetMessageRecordsList(req *types.MessageRec
 	// 按机构ID搜
 	predicates = append(predicates, messagerecords.OrganizationIDEQ(organizationId))
 	// 按群发ID搜
-	predicates = append(predicates, messagerecords.SourceIDEQ(*req.BatchMsgId))
-
+	if req.BatchMsgId != nil {
+		predicates = append(predicates, messagerecords.SourceIDEQ(*req.BatchMsgId))
+	}
+	if req.SourceType != nil {
+		predicates = append(predicates, messagerecords.SourceTypeEQ(*req.SourceType))
+	}
+	if req.SourceId != nil {
+		predicates = append(predicates, messagerecords.SourceIDEQ(*req.SourceId))
+	}
 	if req.BotWxid != nil {
 		predicates = append(predicates, messagerecords.BotWxidContains(*req.BotWxid))
 	}

+ 0 - 9
internal/logic/sop_task/get_sop_task_record_list_logic.go

@@ -2,7 +2,6 @@ package sop_task
 
 import (
 	"context"
-	"fmt"
 	"wechat-api/ent"
 	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/soptask"
@@ -38,17 +37,13 @@ func (l *GetSopTaskRecordListLogic) GetSopTaskRecordList(req *types.IDReq) (resp
 	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
-	fmt.Printf("----------------data1----------------: %+v\n", data.Edges.TaskStages)
-	fmt.Printf("----------------data2----------------: %+v\n", data.Edges.TaskStages[0].Edges.StageNodes)
 	var sopTaskRecordList []types.SopTaskRecordInfo
 	for _, s := range data.Edges.TaskStages {
 		// 在message_records 表中统计 source_type=3, source_id=s.ID的记录数,以及其中status=3的记录数
 		sst, _ := l.SopTaskRecord(3, s.ID, s.Name)
-		fmt.Printf("----------------sst----------------: %+v\n", *sst)
 		sopTaskRecordList = append(sopTaskRecordList, *sst)
 		for _, n := range s.Edges.StageNodes {
 			nst, _ := l.SopTaskRecord(4, n.ID, n.Name)
-			fmt.Printf("----------------nst----------------: %+v\n", *nst)
 			sopTaskRecordList = append(sopTaskRecordList, *nst)
 		}
 	}
@@ -61,16 +56,12 @@ func (l *GetSopTaskRecordListLogic) GetSopTaskRecordList(req *types.IDReq) (resp
 }
 
 func (l *GetSopTaskRecordListLogic) SopTaskRecord(sourceType int, sourceId uint64, name string) (resp *types.SopTaskRecordInfo, err error) {
-	fmt.Printf("----------------sourceType----------------: %d\n", sourceType)
-	fmt.Printf("----------------sourceId----------------: %d\n", sourceId)
 	stageTotalCount, _ := l.svcCtx.DB.MessageRecords.Query().
 		Where(messagerecords.SourceType(sourceType), messagerecords.SourceID(sourceId)).
 		Count(l.ctx)
 	stageSuccessCount, _ := l.svcCtx.DB.MessageRecords.Query().
 		Where(messagerecords.SourceTypeEQ(sourceType), messagerecords.SourceID(sourceId), messagerecords.Status(3)).
 		Count(l.ctx)
-	fmt.Printf("----------------stageTotalCount----------------: %d\n", stageTotalCount)
-	fmt.Printf("----------------stageSuccessCount----------------: %d\n", stageSuccessCount)
 	totalCountInt64 := int64(stageTotalCount)
 	successCountInt64 := int64(stageSuccessCount)
 	failureCount := totalCountInt64 - successCountInt64

+ 34 - 4
internal/logic/sop_task/sop_task_stop_logic.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"github.com/suyuan32/simple-admin-common/msg/errormsg"
 	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
 	"wechat-api/internal/utils/dberrorhandler"
 
@@ -28,6 +29,7 @@ func NewSopTaskStopLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SopTa
 
 func (l *SopTaskStopLogic) SopTaskStop(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
 	organizationId := l.ctx.Value("organizationId").(uint64)
+	isAdmin := l.ctx.Value("isAdmin").(bool)
 	// 开始事务
 	tx, err := l.svcCtx.DB.Tx(context.Background())
 	if err != nil {
@@ -47,10 +49,35 @@ func (l *SopTaskStopLogic) SopTaskStop(req *types.IDReq) (resp *types.BaseMsgRes
 	if task.Status != 3 {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
+	if isAdmin || organizationId == 12 {
+		err = tx.SopTask.UpdateOneID(req.Id).
+			SetStatus(1).
+			Exec(l.ctx)
+		sourceInfo, err := l.svcCtx.DB.SopStage.Query().
+			Where(sopstage.TaskID(req.Id)).
+			WithStageNodes().
+			All(l.ctx)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+		for _, stage := range sourceInfo {
+			_, err := tx.MessageRecords.Delete().Where(messagerecords.SourceIDEQ(stage.ID)).Exec(l.ctx)
 
-	err = l.svcCtx.DB.SopTask.UpdateOneID(req.Id).
-		SetStatus(2).
-		Exec(l.ctx)
+			if err != nil {
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+			for _, node := range stage.Edges.StageNodes {
+				_, err := tx.MessageRecords.Delete().Where(messagerecords.SourceIDEQ(node.ID)).Exec(l.ctx)
+				if err != nil {
+					return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+				}
+			}
+		}
+	} else {
+		err = tx.SopTask.UpdateOneID(req.Id).
+			SetStatus(2).
+			Exec(l.ctx)
+	}
 
 	if err != nil {
 		_ = tx.Rollback()
@@ -70,6 +97,9 @@ func (l *SopTaskStopLogic) SopTaskStop(req *types.IDReq) (resp *types.BaseMsgRes
 			}
 		}
 	}
-
+	err = tx.Commit()
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
 	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
 }

+ 187 - 116
internal/types/types.go

@@ -325,6 +325,27 @@ type WxInfo struct {
 	ApiBase *string `json:"apiBase,optional"`
 	// 大模型服务密钥
 	ApiKey *string `json:"apiKey,optional"`
+	// 白名单
+	AllowList []ContactInfo `json:"allowList,optional"`
+	// 群白名单
+	GroupAllowList []ContactInfo `json:"groupAllowList,optional"`
+	// 黑名单
+	BlockList []ContactInfo `json:"blockList,optional"`
+	// 群黑名单
+	GroupBlockList []ContactInfo `json:"groupBlockList,optional"`
+}
+
+// swagger:model UpdateBlockAndAllowListReq
+type UpdateBlockAndAllowListReq struct {
+	BaseIDInfo
+	// 白名单
+	AllowList []string `json:"allowList,optional"`
+	// 群白名单
+	GroupAllowList []string `json:"groupAllowList,optional"`
+	// 黑名单
+	BlockList []string `json:"blockList,optional"`
+	// 群黑名单
+	GroupBlockList []string `json:"groupBlockList,optional"`
 }
 
 // The response data of wx list | Wx列表数据
@@ -369,6 +390,34 @@ type WxInfoResp struct {
 	Data WxInfo `json:"data"`
 }
 
+// 获取黑白名单列表返回体
+// swagger:model AllowBlockListResp
+type AllowBlockListResp struct {
+	BaseDataInfo
+	// Wx information | Wx数据
+	Data AllowBlockListRespData `json:"data"`
+}
+
+// AllowBlockListRespData
+type AllowBlockListRespData struct {
+	// 白名单
+	AllowList []*AllowBlockData `json:"allowList,optional"`
+	// 群白名单
+	GroupAllowList []*AllowBlockData `json:"groupAllowList,optional"`
+	// 黑名单
+	BlockList []*AllowBlockData `json:"blockList,optional"`
+	// 群黑名单
+	GroupBlockList []*AllowBlockData `json:"groupBlockList,optional"`
+}
+
+// AllowBlockData
+type AllowBlockData struct {
+	// 微信id 公众号微信ID
+	Wxid string `json:"wxid,optional"`
+	// 微信昵称 群备注名称
+	Nickname string `json:"nickname,optional"`
+}
+
 // The data of agent information | Agent信息
 // swagger:model AgentInfo
 type AgentInfo struct {
@@ -382,9 +431,8 @@ type AgentInfo struct {
 	// background | 背景介绍
 	Background *string `json:"background,optional"`
 	// examples | 对话案例
-	Examples  *string `json:"examples,optional"`
-	DatasetId *string `json:"dataset_id,optional"`
-	//		Dataset DatasetInfo `json:"dataset,optional"`
+	Examples     *string `json:"examples,optional"`
+	DatasetId    *string `json:"dataset_id,optional"`
 	CollectionId *string `json:"collection_id,optional"`
 }
 
@@ -654,118 +702,6 @@ type DeleteDataReq struct {
 	ID *string `json:"id" validate:"required"`
 }
 
-type LoginQRStatus struct {
-	// 登陆二维码
-	QRCode string `json:"qRCode,optional"`
-	// 登陆二维码状态
-	Status string `json:"status,optional"`
-	// 登陆二维码状态描述
-	StatusDesc string `json:"statusDesc,optional"`
-}
-
-// 刷新登陆二维码请求参数
-// swagger:model RefreshLoginQRReq
-type RefreshLoginQRReq struct {
-	// 服务器id
-	ServerId *uint64 `json:"serverId,optional"`
-	// 端口号
-	Port *string `json:"port,optional"`
-	// 回调地址
-	Callback *string `json:"callback,optional"`
-}
-
-// 刷新登陆二维码返回参数
-// swagger:model RefreshLoginQRResp
-type RefreshLoginQRResp struct {
-	BaseDataInfo
-	// 二维码Base64
-	Data LoginQRStatus `json:"data,optional"`
-}
-
-// 发送微信文本消息请求参数
-// swagger:model SendTextMsgReq
-type SendTextMsgReq struct {
-	// 属主微信id
-	WxWxid *string `json:"senderWxId"`
-	// 微信id 公众号微信ID
-	Wxid *string `json:"receiverWxId"`
-	// 微信文本消息内容
-	Msg *string `json:"msg"`
-}
-
-// 发送微信图片消息请求参数
-// swagger:model SendPicMsgReq
-type SendPicMsgReq struct {
-	// 属主微信id
-	WxWxid *string `json:"wxWxid"`
-	// 微信id 公众号微信ID
-	Wxid *string `json:"wxid"`
-	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
-	Picpath *string `json:"picpath"`
-	// 微信图片自定义名称(此属性只有网络图片有)
-	Diyfilename *string `json:"diyfilename,optional"`
-}
-
-// 发送微信图片(本地)请求参数
-// swagger:model SendPicMsgLocalReq
-type SendPicMsgLocalReq struct {
-	// 属主微信id
-	WxWxid *string `json:"wxWxid"`
-	// 微信id 公众号微信ID
-	Wxid *string `json:"wxid"`
-	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
-	Picpath *string `json:"picpath"`
-}
-
-// The response data of contact list | Contact列表数据
-// swagger:model ContactListResp
-type ContactListResp struct {
-	BaseDataInfo
-	// Contact list data | Contact列表数据
-	Data ContactListInfo `json:"data"`
-}
-
-// Contact list data | Contact列表数据
-// swagger:model ContactListInfo
-type ContactListInfo struct {
-	BaseListInfo
-	// The API list data | Contact列表数据
-	Data []ContactInfo `json:"data"`
-}
-
-// Get contact list request params | Contact列表请求参数
-// swagger:model ContactListReq
-type ContactListReq struct {
-	PageInfo
-	// Label ID list | 标签ID列表
-	LabelIDs []uint64 `json:"labelIDs,optional"`
-	// 属主微信id
-	WxWxid *string `json:"wxWxid,optional"`
-	// 微信id 公众号微信ID
-	Wxid *string `json:"wxid,optional"`
-	// 微信账号
-	Account *string `json:"account,optional"`
-	// 联系人类型:1好友,2群组,3公众号,4企业微信联系人
-	Type *int `json:"type,optional"`
-}
-
-// Contact information response | Contact信息返回体
-// swagger:model ContactInfoResp
-type ContactInfoResp struct {
-	BaseDataInfo
-	// Contact information | Contact数据
-	Data ContactInfo `json:"data"`
-}
-
-// swagger:model AddNewFriendReq
-type AddNewFriendReq struct {
-	OwnerWxid string `json:"ownerWxid"`
-	Wxid      string `json:"wxid"`
-	Gid       string `json:"gid"`
-	Desc      string `json:"desc"`
-	AddType   string `json:"addType"`
-}
-
 // ContactLabelList | Contact标签列表
 type ContactLabelList struct {
 	// label
@@ -908,6 +844,120 @@ type LabelRelationshipInfoResp struct {
 	Data LabelRelationshipInfo `json:"data"`
 }
 
+type LoginQRStatus struct {
+	// 登陆二维码
+	QRCode string `json:"qRCode,optional"`
+	// 登陆二维码状态
+	Status string `json:"status,optional"`
+	// 登陆二维码状态描述
+	StatusDesc string `json:"statusDesc,optional"`
+}
+
+// 刷新登陆二维码请求参数
+// swagger:model RefreshLoginQRReq
+type RefreshLoginQRReq struct {
+	// 服务器id
+	ServerId *uint64 `json:"serverId,optional"`
+	// 端口号
+	Port *string `json:"port,optional"`
+	// 回调地址
+	Callback *string `json:"callback,optional"`
+}
+
+// 刷新登陆二维码返回参数
+// swagger:model RefreshLoginQRResp
+type RefreshLoginQRResp struct {
+	BaseDataInfo
+	// 二维码Base64
+	Data LoginQRStatus `json:"data,optional"`
+}
+
+// 发送微信文本消息请求参数
+// swagger:model SendTextMsgReq
+type SendTextMsgReq struct {
+	// 属主微信id
+	WxWxid *string `json:"senderWxId"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"receiverWxId"`
+	// 微信文本消息内容
+	Msg *string `json:"msg"`
+}
+
+// 发送微信图片消息请求参数
+// swagger:model SendPicMsgReq
+type SendPicMsgReq struct {
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+	Picpath *string `json:"picpath"`
+	// 微信图片自定义名称(此属性只有网络图片有)
+	Diyfilename *string `json:"diyfilename,optional"`
+}
+
+// 发送微信图片(本地)请求参数
+// swagger:model SendPicMsgLocalReq
+type SendPicMsgLocalReq struct {
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+	Picpath *string `json:"picpath"`
+}
+
+// The response data of contact list | Contact列表数据
+// swagger:model ContactListResp
+type ContactListResp struct {
+	BaseDataInfo
+	// Contact list data | Contact列表数据
+	Data ContactListInfo `json:"data"`
+}
+
+// Contact list data | Contact列表数据
+// swagger:model ContactListInfo
+type ContactListInfo struct {
+	BaseListInfo
+	// The API list data | Contact列表数据
+	Data []ContactInfo `json:"data"`
+}
+
+// Get contact list request params | Contact列表请求参数
+// swagger:model ContactListReq
+type ContactListReq struct {
+	PageInfo
+	// Label ID list | 标签ID列表
+	LabelIDs []uint64 `json:"labelIDs,optional"`
+	// 属主微信id
+	WxWxid *string `json:"wxWxid,optional"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid,optional"`
+	// 微信账号
+	Account *string `json:"account,optional"`
+	// 昵称
+	Nickname *string `json:"nickname,optional"`
+	// 联系人类型:1好友,2群组,3公众号,4企业微信联系人
+	Type *int `json:"type,optional"`
+}
+
+// Contact information response | Contact信息返回体
+// swagger:model ContactInfoResp
+type ContactInfoResp struct {
+	BaseDataInfo
+	// Contact information | Contact数据
+	Data ContactInfo `json:"data"`
+}
+
+// swagger:model AddNewFriendReq
+type AddNewFriendReq struct {
+	OwnerWxid string `json:"ownerWxid"`
+	Wxid      string `json:"wxid"`
+	Gid       string `json:"gid"`
+	Desc      string `json:"desc"`
+	AddType   string `json:"addType"`
+}
+
 // The response data of message information | Message信息
 // swagger:model MessageInfo
 type MessageInfo struct {
@@ -962,6 +1012,20 @@ type LabelSelectListResp struct {
 	Data []LabelSelectListInfo `json:"data"`
 }
 
+// The response data of label list | Label群发列表数据
+// swagger:model LabelBatchSelectListResp
+type LabelBatchSelectListResp struct {
+	BaseDataInfo
+	// Label list data | Label列表数据
+	Data LabelBatchSelectListData `json:"data"`
+}
+
+// The response data of label list | Label群发列表数据
+type LabelBatchSelectListData struct {
+	Contact []LabelSelectListInfo `json:"contact"`
+	Group   []LabelSelectListInfo `json:"group"`
+}
+
 // The response data of label list | Label列表数据
 // swagger:model LabelListResp
 type LabelListResp struct {
@@ -1309,6 +1373,10 @@ type MessageRecordsListReq struct {
 	BatchMsgId *uint64 `json:"batchMsgId,optional"`
 	// 机器人微信 id
 	BotWxid *string `json:"botWxid,optional"`
+	// 消息类型:源类型 1 点发 2 群发 3 SOP 阶段 4 SOP 节点
+	SourceType *int `json:"sourceType,optional"`
+	// 消息源ID:
+	SourceId *uint64 `json:"sourceId,optional"`
 	// 接收方微信 id
 	ContactWxid *string `json:"contactWxid,optional"`
 	// 发送内容
@@ -1480,8 +1548,11 @@ type BatchMsgInfo struct {
 	StartTimeStr *string `json:"startTimeStr,optional"`
 	// 结束时间
 	StopTime *int64 `json:"stopTime,optional"`
+	// 发送时间
+	SendTime *int64 `json:"sendTime,optional"`
 	// 标签列表
-	Labels []string `json:"labels,optional"`
+	Labels      []uint64 `json:"labels,optional"`
+	GroupLabels []uint64 `json:"groupLabels,optional"`
 	// 标签列表
 	Type *int32 `json:"type,optional"`
 }