Bläddra i källkod

Merge branch 'master' into feature/531-bowen-wecom

lichangdong 6 dagar sedan
förälder
incheckning
006c0fec58
56 ändrade filer med 7520 tillägg och 421 borttagningar
  1. 12 45
      cli/asynctask/asynctask.go
  2. 21 0
      cli/asynctask/etc/asynctask.yaml
  3. 6 6
      crontask/init.go
  4. 151 0
      crontask/wx_add_friend.go
  5. 11 1
      desc/openapi/chat.api
  6. 3 0
      desc/wechat/usage_total.api
  7. 3 0
      desc/wechat/wx.api
  8. 247 0
      ent/addwechatfriendlog.go
  9. 152 0
      ent/addwechatfriendlog/addwechatfriendlog.go
  10. 589 0
      ent/addwechatfriendlog/where.go
  11. 1437 0
      ent/addwechatfriendlog_create.go
  12. 88 0
      ent/addwechatfriendlog_delete.go
  13. 526 0
      ent/addwechatfriendlog_query.go
  14. 793 0
      ent/addwechatfriendlog_update.go
  15. 180 37
      ent/client.go
  16. 2 0
      ent/ent.go
  17. 12 0
      ent/hook/hook.go
  18. 30 0
      ent/intercept/intercept.go
  19. 36 1
      ent/migrate/schema.go
  20. 1262 0
      ent/mutation.go
  21. 82 0
      ent/pagination.go
  22. 3 0
      ent/predicate/predicate.go
  23. 96 3
      ent/runtime/runtime.go
  24. 92 0
      ent/schema/add_wechat_friend_log.go
  25. 3 0
      ent/schema/usage_total.go
  26. 336 0
      ent/set_not_nil.go
  27. 4 1
      ent/tx.go
  28. 13 0
      ent/usagetotal.go
  29. 10 0
      ent/usagetotal/usagetotal.go
  30. 55 0
      ent/usagetotal/where.go
  31. 102 0
      ent/usagetotal_create.go
  32. 72 0
      ent/usagetotal_update.go
  33. 109 0
      hook/contact.go
  34. 20 15
      hook/credit/credit.go
  35. 30 26
      hook/credit/models.go
  36. 44 0
      internal/handler/chat/add_friend_by_phone_handler.go
  37. 5 0
      internal/handler/routes.go
  38. 73 0
      internal/lock/wxid_lock.go
  39. 3 0
      internal/logic/Wx/get_wx_list_logic.go
  40. 72 0
      internal/logic/chat/add_friend_by_phone_logic.go
  41. 4 212
      internal/logic/chat/chat_completions_logic.go
  42. 6 2
      internal/logic/chatrecords/gpts_submit_api_chat_logic.go
  43. 12 1
      internal/logic/contact/get_contact_list_logic.go
  44. 8 7
      internal/logic/credit_balance/get_credit_balance_list_logic.go
  45. 5 1
      internal/service/MessageHandlers/contact_Label_info_notice.go
  46. 112 0
      internal/service/MessageHandlers/find_contact_task_result_notice.go
  47. 51 38
      internal/service/MessageHandlers/friend_push_notice.go
  48. 2 0
      internal/service/MessageHandlers/register_strategy.go
  49. 75 0
      internal/service/MessageHandlers/task_result_notice.go
  50. 88 0
      internal/service/addfriend/add_wechat_friend_log.go
  51. 11 9
      internal/svc/service_context.go
  52. 14 1
      internal/types/types.go
  53. 11 0
      internal/types/workphone.go
  54. 1 1
      internal/utils/compapi/form.go
  55. 318 0
      internal/utils/compapi/func.go
  56. 17 14
      internal/utils/compapi/intent.go

+ 12 - 45
cli/asynctask/asynctask.go

@@ -10,7 +10,6 @@ import (
 	"hash/fnv"
 	"os"
 	"os/signal"
-	"reflect"
 	"runtime"
 	"strconv"
 	"strings"
@@ -324,8 +323,8 @@ func (me *AsyncTask) requestAPI(taskData *ent.CompapiAsynctask) (int, error) {
 		err     error
 		apiResp *types.CompOpenApiResp
 	)
-	req := types.CompApiReq{}
-	if err = json.Unmarshal([]byte(taskData.RequestRaw), &req); err != nil {
+	req := &types.CompApiReq{}
+	if err = json.Unmarshal([]byte(taskData.RequestRaw), req); err != nil {
 		return 0, err
 	}
 	//初始化client
@@ -341,7 +340,7 @@ func (me *AsyncTask) requestAPI(taskData *ent.CompapiAsynctask) (int, error) {
 		case <-me.ctx.Done(): //接到信号退出
 			goto endloopTry
 		default:
-			apiResp, err = client.Chat(&req)
+			apiResp, err = client.Chat(req)
 			if err == nil && apiResp != nil && len(apiResp.Choices) > 0 {
 				//call succ
 				goto endloopTry
@@ -371,6 +370,13 @@ endloopTry:
 	}
 	//成功后处理环节
 
+	//追加访问大模型token统计数据
+	svcCtx := &compapi.ServiceContext{DB: me.svcCtx.DB, Rds: me.svcCtx.Rds, Config: me.svcCtx.Config}
+	err = compapi.AppendUsageDetailLog(me.ctx, svcCtx, taskData.AuthToken, req, apiResp)
+	if err != nil {
+		return 0, err
+	}
+
 	//更新任务状态 => ReqApi_Done(请求API完成)
 	err = me.updateTaskStatus(taskData.ID, ReqApi_Done)
 	if err != nil {
@@ -390,51 +396,12 @@ endloopTry:
 	return 1, nil
 }
 
-func EntStructGenScanField(structPtr any) (string, []any, error) {
-	t := reflect.TypeOf(structPtr)
-	v := reflect.ValueOf(structPtr)
-
-	if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
-		return "", nil, errors.New("input must be a pointer to a struct")
-	}
-	t = t.Elem()
-	v = v.Elem()
-
-	var fields []string
-	var scanArgs []any
-	for i := 0; i < t.NumField(); i++ {
-		field := t.Field(i)
-		value := v.Field(i)
-
-		// Skip unexported fields
-		if !field.IsExported() {
-			continue
-		}
-
-		// Get json tag
-		jsonTag := field.Tag.Get("json")
-		if jsonTag == "-" || jsonTag == "" {
-			continue
-		}
-
-		jsonParts := strings.Split(jsonTag, ",")
-		jsonName := jsonParts[0]
-		if jsonName == "" {
-			continue
-		}
-
-		fields = append(fields, jsonName)
-		scanArgs = append(scanArgs, value.Addr().Interface())
-	}
-	return strings.Join(fields, ", "), scanArgs, nil
-}
-
 /*
 CREATE INDEX idx_compapi_task_status_chat_id_id_desc
 ON compapi_asynctask (task_status, chat_id, id DESC);
 */
 func (me *AsyncTask) getAsyncReqTaskFairList() ([]Task, error) {
-	fieldListStr, _, err := EntStructGenScanField(&ent.CompapiAsynctask{})
+	fieldListStr, _, err := compapi.EntStructGenScanField(&ent.CompapiAsynctask{})
 	if err != nil {
 		return nil, err
 	}
@@ -464,7 +431,7 @@ func (me *AsyncTask) getAsyncReqTaskFairList() ([]Task, error) {
 	for rows.Next() {
 		taskrow := ent.CompapiAsynctask{}
 		var scanParams []any
-		_, scanParams, err = EntStructGenScanField(&taskrow)
+		_, scanParams, err = compapi.EntStructGenScanField(&taskrow)
 		if err != nil {
 			break
 		}

+ 21 - 0
cli/asynctask/etc/asynctask.yaml

@@ -0,0 +1,21 @@
+BatchLoadTask: 200 #每批次取任务数
+MaxWorker: 10       #最大消费者数量
+MaxChannel: 2      #最大消费通道数量
+Debug: false
+
+DatabaseConf: #数据库配置
+  Type: mysql
+  Host: 127.0.0.1
+  Port: 3306
+  DBName: wechat
+  Username: root
+  Password: simple-admin.
+  MaxOpenConn: 100
+  SSLMode: disable
+  CacheTime: 5
+
+RedisConf: #redis配置
+  Host: 127.0.0.1:6379
+
+
+

+ 6 - 6
crontask/init.go

@@ -44,16 +44,16 @@ func ScheduleRun(c *cron.Cron, serverCtx *svc.ServiceContext) {
 		computeStatistic.computeStatistic()
 	})
 
-	//syncWx := NewCronTask(context.Background(), serverCtx)
-	//c.AddFunc("*/30 * * * *", func() {
-	//	syncWx.syncWx()
-	//})
-
 	contactForm := NewCronTask(context.Background(), serverCtx)
-	c.AddFunc("0 0 * * *", func() {
+	c.AddFunc("10 0 * * *", func() {
 		contactForm.analyze()
 	})
 
+	l = NewCronTask(context.Background(), serverCtx)
+	c.AddFunc("*/30 * * * *", func() {
+		l.wxAddFriend()
+	})
+
 	//l = NewCronTask(context.Background(), serverCtx)
 	//c.AddFunc("* * * * *", func() {
 	//	MaxWorker := 10

+ 151 - 0
crontask/wx_add_friend.go

@@ -0,0 +1,151 @@
+package crontask
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+	"time"
+	_ "time/tzdata"
+
+	"wechat-api/ent"
+	"wechat-api/internal/service/addfriend"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/utils/compapi"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+const (
+	WX_FREQKEY        = "WX_DAILY_FREQKEY"
+	WX_DAILY_ADDCOUNT = 30
+)
+
+type wxAddFreqCtl struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func (me *wxAddFreqCtl) getDailyWxIDKey(wxID string) string {
+	now, _ := getLocNowTime()
+	dateStr := now.Format("20060102") // Go 的日期格式化字符串
+	return fmt.Sprintf("%s:%s:%s", WX_FREQKEY, wxID, dateStr)
+}
+
+func getLocNowTime() (time.Time, *time.Location) {
+	loc, err := time.LoadLocation("Asia/Shanghai")
+	if err != nil {
+		fmt.Println(err)
+	}
+	now := time.Now()
+	if loc != nil {
+		now = now.In(loc)
+	}
+	return now, loc
+}
+
+func (me *wxAddFreqCtl) Check(wxID string) (bool, int64, error) {
+
+	key := me.getDailyWxIDKey(wxID)
+	//me.svcCtx.Rds.Del(me.ctx, key)
+	count, err := me.svcCtx.Rds.Incr(me.ctx, key).Result()
+	if err != nil {
+		return false, 0, err
+	}
+
+	//如果是当天的第一次发送 (count == 1),设置过期时间
+	if count == 1 {
+		// 计算到明天零点的秒数
+		now, loc := getLocNowTime()
+		tomorrow := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, loc)
+		expiration := tomorrow.Sub(now)
+
+		// 设置过期时间
+		// 添加一个小的缓冲时间(例如 5 分钟),防止临界点问题
+		expireCmd := me.svcCtx.Rds.Expire(me.ctx, key, expiration+5*time.Minute)
+		if expireCmd.Err() != nil {
+			me.Logger.Errorf("redis set expire error: %v", expireCmd.Err())
+		}
+	}
+	return count <= WX_DAILY_ADDCOUNT, count, nil
+}
+
+func NewWxAddFreqCtl(ctx context.Context, svcCtx *svc.ServiceContext) *wxAddFreqCtl {
+	return &wxAddFreqCtl{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *CronTask) CliwxAddFriend() {
+	l.wxAddFriend()
+}
+
+func (l *CronTask) wxAddFriend() {
+
+	tasks, err := l.getTaskList()
+	if err != nil {
+		fmt.Println(err)
+		l.Logger.Errorf("get AddWechatFriendLog TaskList %v", err)
+		return
+	}
+	serv := addfriend.NewAddWechatFriendService(l.ctx, l.svcCtx)
+	servFreqCtl := NewWxAddFreqCtl(l.ctx, l.svcCtx)
+	canAdd := false
+	addCount := int64(0)
+	for _, task := range tasks {
+		canAdd, addCount, err = servFreqCtl.Check(task.OwnerWxID)
+		if err != nil {
+			l.Logger.Errorf("check add freq error:%v", err)
+			continue
+		}
+		if !canAdd {
+			l.Logger.Infof("WxID:'%s' AddNewFriend today count:%d over limit:%d",
+				task.OwnerWxID, addCount, WX_DAILY_ADDCOUNT)
+			continue
+		}
+		ok := serv.AddNewFriend(task.OwnerWxID, task.FindContent, task.Message)
+		l.Logger.Debugf("serv.AddNewFriend()=>%v", ok)
+	}
+
+}
+
+func (me *CronTask) getTaskList() ([]*ent.AddWechatFriendLog, error) {
+	taskrow := ent.AddWechatFriendLog{}
+	mapAnyType := reflect.TypeOf(taskrow.FindRequest)
+	fieldListStr, _, err := compapi.EntStructGenScanField(&taskrow, mapAnyType)
+	if err != nil {
+		return nil, err
+	}
+	rawQuery := fmt.Sprintf(`
+		WITH RandRanked AS (
+    		SELECT %s,ROW_NUMBER() OVER(PARTITION BY owner_wx_id ORDER BY id DESC) as rn
+    		FROM add_wechat_friend_log
+		    WHERE is_can_add = 1 AND task_count < 3)
+		SELECT %s FROM RandRanked WHERE rn = 1;`, fieldListStr, fieldListStr)
+
+	//fmt.Println(rawQuery)
+	// 执行原始查询
+	rows, err := me.svcCtx.DB.QueryContext(me.ctx, rawQuery)
+	if err != nil {
+		return nil, fmt.Errorf("fetch fair tasks query error: %w", err)
+	}
+	defer rows.Close()
+	Idx := 0
+	tasks := []*ent.AddWechatFriendLog{}
+	for rows.Next() {
+		var scanParams []any
+		mapAnyType := reflect.TypeOf(taskrow.FindRequest)
+		_, scanParams, err = compapi.EntStructGenScanField(&taskrow, mapAnyType)
+		if err != nil {
+			break
+		}
+		err = rows.Scan(scanParams...)
+		if err != nil {
+			break
+		}
+		tasks = append(tasks, &taskrow)
+		Idx++
+	}
+	return tasks, nil
+}

+ 11 - 1
desc/openapi/chat.api

@@ -2,8 +2,16 @@ import "../base.api"
 
 type (
     
-    //以下是API请求类型
+    
+	//add_friend_by_phone api接口请求值
+	AddFriendByPhoneReq {
+		Type int `json:"type"`
+		WeChatId string `json:"WeChatId"`
+		Phone string `json:"phone"`
+		Message string `json:"message"`
+	}
 
+	//以下是API请求类型
 	CompApiReq {
         CompCtlReq
 		StdCompApiReq
@@ -220,4 +228,6 @@ service Wechat {
 service Wechat {
 	@handler sendTextMsg
 	post /wx/sendTextMsg (SendTextMsgReq) returns (BaseMsgResp)
+	@handler AddFriendByPhone
+	post /wx/add_friend_by_phone (AddFriendByPhoneReq) returns (BaseMsgResp)
 }	

+ 3 - 0
desc/wechat/usage_total.api

@@ -17,6 +17,9 @@ type (
         // 使用token总数
         TotalTokens *uint64 `json:"totalTokens,optional"`
 
+		// 使用积分总数
+		Credits float64 `json:"credits,optional"`
+
         // 重制后的起始usage_detail 索引
         StartIndex *uint64 `json:"startIndex,optional"`
 

+ 3 - 0
desc/wechat/wx.api

@@ -73,6 +73,9 @@ type (
         // 使用token总数
         TotalTokens *uint64 `json:"totalTokens,optional"`
 
+		// 使用积分总数
+		Credits *float64 `json:"credits,optional"`
+
 		Ctype *uint64 `json:"ctype,optional"`
     }
 

+ 247 - 0
ent/addwechatfriendlog.go

@@ -0,0 +1,247 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+	"wechat-api/ent/addwechatfriendlog"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// 微信添加好友记录
+type AddWechatFriendLog struct {
+	config `json:"-"`
+	// ID of the ent.
+	// 主键id
+	ID int64 `json:"id,omitempty"`
+	// 属主的wxid
+	OwnerWxID string `json:"owner_wx_id,omitempty"`
+	// 属主的微信类型(1个微,2企微)
+	OwnerWxType int `json:"owner_wx_type,omitempty"`
+	// 手机号
+	FindContent string `json:"find_content,omitempty"`
+	// 添加好友时候填写的申请消息
+	Message string `json:"message,omitempty"`
+	// 发起查询数据的时候json
+	FindRequest map[string]interface{} `json:"find_request,omitempty"`
+	// 查询返回结果
+	FindResult map[string]interface{} `json:"find_result,omitempty"`
+	// 任务执行次数
+	IsCanAdd int `json:"is_can_add,omitempty"`
+	// 是否可以添加好友(与属主账号非好友且其数据查询正常时 0 不可以,1 可以 2成功添加申请)
+	TaskCount int `json:"task_count,omitempty"`
+	// 添加时候的请求体
+	TaskID int64 `json:"task_id,omitempty"`
+	// 添加时候的请求体
+	AddRequest map[string]interface{} `json:"add_request,omitempty"`
+	// 添加请求的结果
+	AddResult map[string]interface{} `json:"add_result,omitempty"`
+	// 创建时间戳
+	CreatedAt int64 `json:"created_at,omitempty"`
+	// 修改时间戳
+	UpdatedAt    int64 `json:"updated_at,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*AddWechatFriendLog) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case addwechatfriendlog.FieldFindRequest, addwechatfriendlog.FieldFindResult, addwechatfriendlog.FieldAddRequest, addwechatfriendlog.FieldAddResult:
+			values[i] = new([]byte)
+		case addwechatfriendlog.FieldID, addwechatfriendlog.FieldOwnerWxType, addwechatfriendlog.FieldIsCanAdd, addwechatfriendlog.FieldTaskCount, addwechatfriendlog.FieldTaskID, addwechatfriendlog.FieldCreatedAt, addwechatfriendlog.FieldUpdatedAt:
+			values[i] = new(sql.NullInt64)
+		case addwechatfriendlog.FieldOwnerWxID, addwechatfriendlog.FieldFindContent, addwechatfriendlog.FieldMessage:
+			values[i] = new(sql.NullString)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the AddWechatFriendLog fields.
+func (awfl *AddWechatFriendLog) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case addwechatfriendlog.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			awfl.ID = int64(value.Int64)
+		case addwechatfriendlog.FieldOwnerWxID:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field owner_wx_id", values[i])
+			} else if value.Valid {
+				awfl.OwnerWxID = value.String
+			}
+		case addwechatfriendlog.FieldOwnerWxType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field owner_wx_type", values[i])
+			} else if value.Valid {
+				awfl.OwnerWxType = int(value.Int64)
+			}
+		case addwechatfriendlog.FieldFindContent:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field find_content", values[i])
+			} else if value.Valid {
+				awfl.FindContent = value.String
+			}
+		case addwechatfriendlog.FieldMessage:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field message", values[i])
+			} else if value.Valid {
+				awfl.Message = value.String
+			}
+		case addwechatfriendlog.FieldFindRequest:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field find_request", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &awfl.FindRequest); err != nil {
+					return fmt.Errorf("unmarshal field find_request: %w", err)
+				}
+			}
+		case addwechatfriendlog.FieldFindResult:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field find_result", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &awfl.FindResult); err != nil {
+					return fmt.Errorf("unmarshal field find_result: %w", err)
+				}
+			}
+		case addwechatfriendlog.FieldIsCanAdd:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field is_can_add", values[i])
+			} else if value.Valid {
+				awfl.IsCanAdd = int(value.Int64)
+			}
+		case addwechatfriendlog.FieldTaskCount:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field task_count", values[i])
+			} else if value.Valid {
+				awfl.TaskCount = int(value.Int64)
+			}
+		case addwechatfriendlog.FieldTaskID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field task_id", values[i])
+			} else if value.Valid {
+				awfl.TaskID = value.Int64
+			}
+		case addwechatfriendlog.FieldAddRequest:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field add_request", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &awfl.AddRequest); err != nil {
+					return fmt.Errorf("unmarshal field add_request: %w", err)
+				}
+			}
+		case addwechatfriendlog.FieldAddResult:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field add_result", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &awfl.AddResult); err != nil {
+					return fmt.Errorf("unmarshal field add_result: %w", err)
+				}
+			}
+		case addwechatfriendlog.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				awfl.CreatedAt = value.Int64
+			}
+		case addwechatfriendlog.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				awfl.UpdatedAt = value.Int64
+			}
+		default:
+			awfl.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the AddWechatFriendLog.
+// This includes values selected through modifiers, order, etc.
+func (awfl *AddWechatFriendLog) Value(name string) (ent.Value, error) {
+	return awfl.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this AddWechatFriendLog.
+// Note that you need to call AddWechatFriendLog.Unwrap() before calling this method if this AddWechatFriendLog
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (awfl *AddWechatFriendLog) Update() *AddWechatFriendLogUpdateOne {
+	return NewAddWechatFriendLogClient(awfl.config).UpdateOne(awfl)
+}
+
+// Unwrap unwraps the AddWechatFriendLog entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (awfl *AddWechatFriendLog) Unwrap() *AddWechatFriendLog {
+	_tx, ok := awfl.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: AddWechatFriendLog is not a transactional entity")
+	}
+	awfl.config.driver = _tx.drv
+	return awfl
+}
+
+// String implements the fmt.Stringer.
+func (awfl *AddWechatFriendLog) String() string {
+	var builder strings.Builder
+	builder.WriteString("AddWechatFriendLog(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", awfl.ID))
+	builder.WriteString("owner_wx_id=")
+	builder.WriteString(awfl.OwnerWxID)
+	builder.WriteString(", ")
+	builder.WriteString("owner_wx_type=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.OwnerWxType))
+	builder.WriteString(", ")
+	builder.WriteString("find_content=")
+	builder.WriteString(awfl.FindContent)
+	builder.WriteString(", ")
+	builder.WriteString("message=")
+	builder.WriteString(awfl.Message)
+	builder.WriteString(", ")
+	builder.WriteString("find_request=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.FindRequest))
+	builder.WriteString(", ")
+	builder.WriteString("find_result=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.FindResult))
+	builder.WriteString(", ")
+	builder.WriteString("is_can_add=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.IsCanAdd))
+	builder.WriteString(", ")
+	builder.WriteString("task_count=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.TaskCount))
+	builder.WriteString(", ")
+	builder.WriteString("task_id=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.TaskID))
+	builder.WriteString(", ")
+	builder.WriteString("add_request=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.AddRequest))
+	builder.WriteString(", ")
+	builder.WriteString("add_result=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.AddResult))
+	builder.WriteString(", ")
+	builder.WriteString("created_at=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.CreatedAt))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(fmt.Sprintf("%v", awfl.UpdatedAt))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// AddWechatFriendLogs is a parsable slice of AddWechatFriendLog.
+type AddWechatFriendLogs []*AddWechatFriendLog

+ 152 - 0
ent/addwechatfriendlog/addwechatfriendlog.go

@@ -0,0 +1,152 @@
+// Code generated by ent, DO NOT EDIT.
+
+package addwechatfriendlog
+
+import (
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the addwechatfriendlog type in the database.
+	Label = "add_wechat_friend_log"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldOwnerWxID holds the string denoting the owner_wx_id field in the database.
+	FieldOwnerWxID = "owner_wx_id"
+	// FieldOwnerWxType holds the string denoting the owner_wx_type field in the database.
+	FieldOwnerWxType = "owner_wx_type"
+	// FieldFindContent holds the string denoting the find_content field in the database.
+	FieldFindContent = "find_content"
+	// FieldMessage holds the string denoting the message field in the database.
+	FieldMessage = "message"
+	// FieldFindRequest holds the string denoting the find_request field in the database.
+	FieldFindRequest = "find_request"
+	// FieldFindResult holds the string denoting the find_result field in the database.
+	FieldFindResult = "find_result"
+	// FieldIsCanAdd holds the string denoting the is_can_add field in the database.
+	FieldIsCanAdd = "is_can_add"
+	// FieldTaskCount holds the string denoting the task_count field in the database.
+	FieldTaskCount = "task_count"
+	// FieldTaskID holds the string denoting the task_id field in the database.
+	FieldTaskID = "task_id"
+	// FieldAddRequest holds the string denoting the add_request field in the database.
+	FieldAddRequest = "add_request"
+	// FieldAddResult holds the string denoting the add_result field in the database.
+	FieldAddResult = "add_result"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// Table holds the table name of the addwechatfriendlog in the database.
+	Table = "add_wechat_friend_log"
+)
+
+// Columns holds all SQL columns for addwechatfriendlog fields.
+var Columns = []string{
+	FieldID,
+	FieldOwnerWxID,
+	FieldOwnerWxType,
+	FieldFindContent,
+	FieldMessage,
+	FieldFindRequest,
+	FieldFindResult,
+	FieldIsCanAdd,
+	FieldTaskCount,
+	FieldTaskID,
+	FieldAddRequest,
+	FieldAddResult,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+var (
+	// DefaultOwnerWxID holds the default value on creation for the "owner_wx_id" field.
+	DefaultOwnerWxID string
+	// OwnerWxIDValidator is a validator for the "owner_wx_id" field. It is called by the builders before save.
+	OwnerWxIDValidator func(string) error
+	// DefaultOwnerWxType holds the default value on creation for the "owner_wx_type" field.
+	DefaultOwnerWxType int
+	// DefaultFindContent holds the default value on creation for the "find_content" field.
+	DefaultFindContent string
+	// FindContentValidator is a validator for the "find_content" field. It is called by the builders before save.
+	FindContentValidator func(string) error
+	// DefaultMessage holds the default value on creation for the "message" field.
+	DefaultMessage string
+	// MessageValidator is a validator for the "message" field. It is called by the builders before save.
+	MessageValidator func(string) error
+	// DefaultIsCanAdd holds the default value on creation for the "is_can_add" field.
+	DefaultIsCanAdd int
+	// DefaultTaskCount holds the default value on creation for the "task_count" field.
+	DefaultTaskCount int
+	// DefaultTaskID holds the default value on creation for the "task_id" field.
+	DefaultTaskID int64
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() int64
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() int64
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() int64
+)
+
+// OrderOption defines the ordering options for the AddWechatFriendLog queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByOwnerWxID orders the results by the owner_wx_id field.
+func ByOwnerWxID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOwnerWxID, opts...).ToFunc()
+}
+
+// ByOwnerWxType orders the results by the owner_wx_type field.
+func ByOwnerWxType(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOwnerWxType, opts...).ToFunc()
+}
+
+// ByFindContent orders the results by the find_content field.
+func ByFindContent(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldFindContent, opts...).ToFunc()
+}
+
+// ByMessage orders the results by the message field.
+func ByMessage(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldMessage, opts...).ToFunc()
+}
+
+// ByIsCanAdd orders the results by the is_can_add field.
+func ByIsCanAdd(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldIsCanAdd, opts...).ToFunc()
+}
+
+// ByTaskCount orders the results by the task_count field.
+func ByTaskCount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTaskCount, opts...).ToFunc()
+}
+
+// ByTaskID orders the results by the task_id field.
+func ByTaskID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTaskID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}

+ 589 - 0
ent/addwechatfriendlog/where.go

@@ -0,0 +1,589 @@
+// Code generated by ent, DO NOT EDIT.
+
+package addwechatfriendlog
+
+import (
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldID, id))
+}
+
+// OwnerWxID applies equality check predicate on the "owner_wx_id" field. It's identical to OwnerWxIDEQ.
+func OwnerWxID(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldOwnerWxID, v))
+}
+
+// OwnerWxType applies equality check predicate on the "owner_wx_type" field. It's identical to OwnerWxTypeEQ.
+func OwnerWxType(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldOwnerWxType, v))
+}
+
+// FindContent applies equality check predicate on the "find_content" field. It's identical to FindContentEQ.
+func FindContent(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldFindContent, v))
+}
+
+// Message applies equality check predicate on the "message" field. It's identical to MessageEQ.
+func Message(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldMessage, v))
+}
+
+// IsCanAdd applies equality check predicate on the "is_can_add" field. It's identical to IsCanAddEQ.
+func IsCanAdd(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldIsCanAdd, v))
+}
+
+// TaskCount applies equality check predicate on the "task_count" field. It's identical to TaskCountEQ.
+func TaskCount(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldTaskCount, v))
+}
+
+// TaskID applies equality check predicate on the "task_id" field. It's identical to TaskIDEQ.
+func TaskID(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldTaskID, v))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// OwnerWxIDEQ applies the EQ predicate on the "owner_wx_id" field.
+func OwnerWxIDEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDNEQ applies the NEQ predicate on the "owner_wx_id" field.
+func OwnerWxIDNEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDIn applies the In predicate on the "owner_wx_id" field.
+func OwnerWxIDIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldOwnerWxID, vs...))
+}
+
+// OwnerWxIDNotIn applies the NotIn predicate on the "owner_wx_id" field.
+func OwnerWxIDNotIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldOwnerWxID, vs...))
+}
+
+// OwnerWxIDGT applies the GT predicate on the "owner_wx_id" field.
+func OwnerWxIDGT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDGTE applies the GTE predicate on the "owner_wx_id" field.
+func OwnerWxIDGTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDLT applies the LT predicate on the "owner_wx_id" field.
+func OwnerWxIDLT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDLTE applies the LTE predicate on the "owner_wx_id" field.
+func OwnerWxIDLTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDContains applies the Contains predicate on the "owner_wx_id" field.
+func OwnerWxIDContains(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContains(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDHasPrefix applies the HasPrefix predicate on the "owner_wx_id" field.
+func OwnerWxIDHasPrefix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasPrefix(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDHasSuffix applies the HasSuffix predicate on the "owner_wx_id" field.
+func OwnerWxIDHasSuffix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasSuffix(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDEqualFold applies the EqualFold predicate on the "owner_wx_id" field.
+func OwnerWxIDEqualFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEqualFold(FieldOwnerWxID, v))
+}
+
+// OwnerWxIDContainsFold applies the ContainsFold predicate on the "owner_wx_id" field.
+func OwnerWxIDContainsFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContainsFold(FieldOwnerWxID, v))
+}
+
+// OwnerWxTypeEQ applies the EQ predicate on the "owner_wx_type" field.
+func OwnerWxTypeEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldOwnerWxType, v))
+}
+
+// OwnerWxTypeNEQ applies the NEQ predicate on the "owner_wx_type" field.
+func OwnerWxTypeNEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldOwnerWxType, v))
+}
+
+// OwnerWxTypeIn applies the In predicate on the "owner_wx_type" field.
+func OwnerWxTypeIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldOwnerWxType, vs...))
+}
+
+// OwnerWxTypeNotIn applies the NotIn predicate on the "owner_wx_type" field.
+func OwnerWxTypeNotIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldOwnerWxType, vs...))
+}
+
+// OwnerWxTypeGT applies the GT predicate on the "owner_wx_type" field.
+func OwnerWxTypeGT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldOwnerWxType, v))
+}
+
+// OwnerWxTypeGTE applies the GTE predicate on the "owner_wx_type" field.
+func OwnerWxTypeGTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldOwnerWxType, v))
+}
+
+// OwnerWxTypeLT applies the LT predicate on the "owner_wx_type" field.
+func OwnerWxTypeLT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldOwnerWxType, v))
+}
+
+// OwnerWxTypeLTE applies the LTE predicate on the "owner_wx_type" field.
+func OwnerWxTypeLTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldOwnerWxType, v))
+}
+
+// FindContentEQ applies the EQ predicate on the "find_content" field.
+func FindContentEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldFindContent, v))
+}
+
+// FindContentNEQ applies the NEQ predicate on the "find_content" field.
+func FindContentNEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldFindContent, v))
+}
+
+// FindContentIn applies the In predicate on the "find_content" field.
+func FindContentIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldFindContent, vs...))
+}
+
+// FindContentNotIn applies the NotIn predicate on the "find_content" field.
+func FindContentNotIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldFindContent, vs...))
+}
+
+// FindContentGT applies the GT predicate on the "find_content" field.
+func FindContentGT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldFindContent, v))
+}
+
+// FindContentGTE applies the GTE predicate on the "find_content" field.
+func FindContentGTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldFindContent, v))
+}
+
+// FindContentLT applies the LT predicate on the "find_content" field.
+func FindContentLT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldFindContent, v))
+}
+
+// FindContentLTE applies the LTE predicate on the "find_content" field.
+func FindContentLTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldFindContent, v))
+}
+
+// FindContentContains applies the Contains predicate on the "find_content" field.
+func FindContentContains(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContains(FieldFindContent, v))
+}
+
+// FindContentHasPrefix applies the HasPrefix predicate on the "find_content" field.
+func FindContentHasPrefix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasPrefix(FieldFindContent, v))
+}
+
+// FindContentHasSuffix applies the HasSuffix predicate on the "find_content" field.
+func FindContentHasSuffix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasSuffix(FieldFindContent, v))
+}
+
+// FindContentEqualFold applies the EqualFold predicate on the "find_content" field.
+func FindContentEqualFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEqualFold(FieldFindContent, v))
+}
+
+// FindContentContainsFold applies the ContainsFold predicate on the "find_content" field.
+func FindContentContainsFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContainsFold(FieldFindContent, v))
+}
+
+// MessageEQ applies the EQ predicate on the "message" field.
+func MessageEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldMessage, v))
+}
+
+// MessageNEQ applies the NEQ predicate on the "message" field.
+func MessageNEQ(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldMessage, v))
+}
+
+// MessageIn applies the In predicate on the "message" field.
+func MessageIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldMessage, vs...))
+}
+
+// MessageNotIn applies the NotIn predicate on the "message" field.
+func MessageNotIn(vs ...string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldMessage, vs...))
+}
+
+// MessageGT applies the GT predicate on the "message" field.
+func MessageGT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldMessage, v))
+}
+
+// MessageGTE applies the GTE predicate on the "message" field.
+func MessageGTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldMessage, v))
+}
+
+// MessageLT applies the LT predicate on the "message" field.
+func MessageLT(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldMessage, v))
+}
+
+// MessageLTE applies the LTE predicate on the "message" field.
+func MessageLTE(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldMessage, v))
+}
+
+// MessageContains applies the Contains predicate on the "message" field.
+func MessageContains(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContains(FieldMessage, v))
+}
+
+// MessageHasPrefix applies the HasPrefix predicate on the "message" field.
+func MessageHasPrefix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasPrefix(FieldMessage, v))
+}
+
+// MessageHasSuffix applies the HasSuffix predicate on the "message" field.
+func MessageHasSuffix(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldHasSuffix(FieldMessage, v))
+}
+
+// MessageEqualFold applies the EqualFold predicate on the "message" field.
+func MessageEqualFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEqualFold(FieldMessage, v))
+}
+
+// MessageContainsFold applies the ContainsFold predicate on the "message" field.
+func MessageContainsFold(v string) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldContainsFold(FieldMessage, v))
+}
+
+// FindRequestIsNil applies the IsNil predicate on the "find_request" field.
+func FindRequestIsNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIsNull(FieldFindRequest))
+}
+
+// FindRequestNotNil applies the NotNil predicate on the "find_request" field.
+func FindRequestNotNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotNull(FieldFindRequest))
+}
+
+// FindResultIsNil applies the IsNil predicate on the "find_result" field.
+func FindResultIsNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIsNull(FieldFindResult))
+}
+
+// FindResultNotNil applies the NotNil predicate on the "find_result" field.
+func FindResultNotNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotNull(FieldFindResult))
+}
+
+// IsCanAddEQ applies the EQ predicate on the "is_can_add" field.
+func IsCanAddEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldIsCanAdd, v))
+}
+
+// IsCanAddNEQ applies the NEQ predicate on the "is_can_add" field.
+func IsCanAddNEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldIsCanAdd, v))
+}
+
+// IsCanAddIn applies the In predicate on the "is_can_add" field.
+func IsCanAddIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldIsCanAdd, vs...))
+}
+
+// IsCanAddNotIn applies the NotIn predicate on the "is_can_add" field.
+func IsCanAddNotIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldIsCanAdd, vs...))
+}
+
+// IsCanAddGT applies the GT predicate on the "is_can_add" field.
+func IsCanAddGT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldIsCanAdd, v))
+}
+
+// IsCanAddGTE applies the GTE predicate on the "is_can_add" field.
+func IsCanAddGTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldIsCanAdd, v))
+}
+
+// IsCanAddLT applies the LT predicate on the "is_can_add" field.
+func IsCanAddLT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldIsCanAdd, v))
+}
+
+// IsCanAddLTE applies the LTE predicate on the "is_can_add" field.
+func IsCanAddLTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldIsCanAdd, v))
+}
+
+// TaskCountEQ applies the EQ predicate on the "task_count" field.
+func TaskCountEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldTaskCount, v))
+}
+
+// TaskCountNEQ applies the NEQ predicate on the "task_count" field.
+func TaskCountNEQ(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldTaskCount, v))
+}
+
+// TaskCountIn applies the In predicate on the "task_count" field.
+func TaskCountIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldTaskCount, vs...))
+}
+
+// TaskCountNotIn applies the NotIn predicate on the "task_count" field.
+func TaskCountNotIn(vs ...int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldTaskCount, vs...))
+}
+
+// TaskCountGT applies the GT predicate on the "task_count" field.
+func TaskCountGT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldTaskCount, v))
+}
+
+// TaskCountGTE applies the GTE predicate on the "task_count" field.
+func TaskCountGTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldTaskCount, v))
+}
+
+// TaskCountLT applies the LT predicate on the "task_count" field.
+func TaskCountLT(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldTaskCount, v))
+}
+
+// TaskCountLTE applies the LTE predicate on the "task_count" field.
+func TaskCountLTE(v int) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldTaskCount, v))
+}
+
+// TaskIDEQ applies the EQ predicate on the "task_id" field.
+func TaskIDEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldTaskID, v))
+}
+
+// TaskIDNEQ applies the NEQ predicate on the "task_id" field.
+func TaskIDNEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldTaskID, v))
+}
+
+// TaskIDIn applies the In predicate on the "task_id" field.
+func TaskIDIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldTaskID, vs...))
+}
+
+// TaskIDNotIn applies the NotIn predicate on the "task_id" field.
+func TaskIDNotIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldTaskID, vs...))
+}
+
+// TaskIDGT applies the GT predicate on the "task_id" field.
+func TaskIDGT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldTaskID, v))
+}
+
+// TaskIDGTE applies the GTE predicate on the "task_id" field.
+func TaskIDGTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldTaskID, v))
+}
+
+// TaskIDLT applies the LT predicate on the "task_id" field.
+func TaskIDLT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldTaskID, v))
+}
+
+// TaskIDLTE applies the LTE predicate on the "task_id" field.
+func TaskIDLTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldTaskID, v))
+}
+
+// AddRequestIsNil applies the IsNil predicate on the "add_request" field.
+func AddRequestIsNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIsNull(FieldAddRequest))
+}
+
+// AddRequestNotNil applies the NotNil predicate on the "add_request" field.
+func AddRequestNotNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotNull(FieldAddRequest))
+}
+
+// AddResultIsNil applies the IsNil predicate on the "add_result" field.
+func AddResultIsNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIsNull(FieldAddResult))
+}
+
+// AddResultNotNil applies the NotNil predicate on the "add_result" field.
+func AddResultNotNil() predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotNull(FieldAddResult))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v int64) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.AddWechatFriendLog) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.AddWechatFriendLog) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.AddWechatFriendLog) predicate.AddWechatFriendLog {
+	return predicate.AddWechatFriendLog(sql.NotPredicates(p))
+}

+ 1437 - 0
ent/addwechatfriendlog_create.go

@@ -0,0 +1,1437 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"wechat-api/ent/addwechatfriendlog"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AddWechatFriendLogCreate is the builder for creating a AddWechatFriendLog entity.
+type AddWechatFriendLogCreate struct {
+	config
+	mutation *AddWechatFriendLogMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (awflc *AddWechatFriendLogCreate) SetOwnerWxID(s string) *AddWechatFriendLogCreate {
+	awflc.mutation.SetOwnerWxID(s)
+	return awflc
+}
+
+// SetNillableOwnerWxID sets the "owner_wx_id" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableOwnerWxID(s *string) *AddWechatFriendLogCreate {
+	if s != nil {
+		awflc.SetOwnerWxID(*s)
+	}
+	return awflc
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (awflc *AddWechatFriendLogCreate) SetOwnerWxType(i int) *AddWechatFriendLogCreate {
+	awflc.mutation.SetOwnerWxType(i)
+	return awflc
+}
+
+// SetNillableOwnerWxType sets the "owner_wx_type" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableOwnerWxType(i *int) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetOwnerWxType(*i)
+	}
+	return awflc
+}
+
+// SetFindContent sets the "find_content" field.
+func (awflc *AddWechatFriendLogCreate) SetFindContent(s string) *AddWechatFriendLogCreate {
+	awflc.mutation.SetFindContent(s)
+	return awflc
+}
+
+// SetNillableFindContent sets the "find_content" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableFindContent(s *string) *AddWechatFriendLogCreate {
+	if s != nil {
+		awflc.SetFindContent(*s)
+	}
+	return awflc
+}
+
+// SetMessage sets the "message" field.
+func (awflc *AddWechatFriendLogCreate) SetMessage(s string) *AddWechatFriendLogCreate {
+	awflc.mutation.SetMessage(s)
+	return awflc
+}
+
+// SetNillableMessage sets the "message" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableMessage(s *string) *AddWechatFriendLogCreate {
+	if s != nil {
+		awflc.SetMessage(*s)
+	}
+	return awflc
+}
+
+// SetFindRequest sets the "find_request" field.
+func (awflc *AddWechatFriendLogCreate) SetFindRequest(m map[string]interface{}) *AddWechatFriendLogCreate {
+	awflc.mutation.SetFindRequest(m)
+	return awflc
+}
+
+// SetFindResult sets the "find_result" field.
+func (awflc *AddWechatFriendLogCreate) SetFindResult(m map[string]interface{}) *AddWechatFriendLogCreate {
+	awflc.mutation.SetFindResult(m)
+	return awflc
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (awflc *AddWechatFriendLogCreate) SetIsCanAdd(i int) *AddWechatFriendLogCreate {
+	awflc.mutation.SetIsCanAdd(i)
+	return awflc
+}
+
+// SetNillableIsCanAdd sets the "is_can_add" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableIsCanAdd(i *int) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetIsCanAdd(*i)
+	}
+	return awflc
+}
+
+// SetTaskCount sets the "task_count" field.
+func (awflc *AddWechatFriendLogCreate) SetTaskCount(i int) *AddWechatFriendLogCreate {
+	awflc.mutation.SetTaskCount(i)
+	return awflc
+}
+
+// SetNillableTaskCount sets the "task_count" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableTaskCount(i *int) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetTaskCount(*i)
+	}
+	return awflc
+}
+
+// SetTaskID sets the "task_id" field.
+func (awflc *AddWechatFriendLogCreate) SetTaskID(i int64) *AddWechatFriendLogCreate {
+	awflc.mutation.SetTaskID(i)
+	return awflc
+}
+
+// SetNillableTaskID sets the "task_id" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableTaskID(i *int64) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetTaskID(*i)
+	}
+	return awflc
+}
+
+// SetAddRequest sets the "add_request" field.
+func (awflc *AddWechatFriendLogCreate) SetAddRequest(m map[string]interface{}) *AddWechatFriendLogCreate {
+	awflc.mutation.SetAddRequest(m)
+	return awflc
+}
+
+// SetAddResult sets the "add_result" field.
+func (awflc *AddWechatFriendLogCreate) SetAddResult(m map[string]interface{}) *AddWechatFriendLogCreate {
+	awflc.mutation.SetAddResult(m)
+	return awflc
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (awflc *AddWechatFriendLogCreate) SetCreatedAt(i int64) *AddWechatFriendLogCreate {
+	awflc.mutation.SetCreatedAt(i)
+	return awflc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableCreatedAt(i *int64) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetCreatedAt(*i)
+	}
+	return awflc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (awflc *AddWechatFriendLogCreate) SetUpdatedAt(i int64) *AddWechatFriendLogCreate {
+	awflc.mutation.SetUpdatedAt(i)
+	return awflc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (awflc *AddWechatFriendLogCreate) SetNillableUpdatedAt(i *int64) *AddWechatFriendLogCreate {
+	if i != nil {
+		awflc.SetUpdatedAt(*i)
+	}
+	return awflc
+}
+
+// SetID sets the "id" field.
+func (awflc *AddWechatFriendLogCreate) SetID(i int64) *AddWechatFriendLogCreate {
+	awflc.mutation.SetID(i)
+	return awflc
+}
+
+// Mutation returns the AddWechatFriendLogMutation object of the builder.
+func (awflc *AddWechatFriendLogCreate) Mutation() *AddWechatFriendLogMutation {
+	return awflc.mutation
+}
+
+// Save creates the AddWechatFriendLog in the database.
+func (awflc *AddWechatFriendLogCreate) Save(ctx context.Context) (*AddWechatFriendLog, error) {
+	awflc.defaults()
+	return withHooks(ctx, awflc.sqlSave, awflc.mutation, awflc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (awflc *AddWechatFriendLogCreate) SaveX(ctx context.Context) *AddWechatFriendLog {
+	v, err := awflc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (awflc *AddWechatFriendLogCreate) Exec(ctx context.Context) error {
+	_, err := awflc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awflc *AddWechatFriendLogCreate) ExecX(ctx context.Context) {
+	if err := awflc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (awflc *AddWechatFriendLogCreate) defaults() {
+	if _, ok := awflc.mutation.OwnerWxID(); !ok {
+		v := addwechatfriendlog.DefaultOwnerWxID
+		awflc.mutation.SetOwnerWxID(v)
+	}
+	if _, ok := awflc.mutation.OwnerWxType(); !ok {
+		v := addwechatfriendlog.DefaultOwnerWxType
+		awflc.mutation.SetOwnerWxType(v)
+	}
+	if _, ok := awflc.mutation.FindContent(); !ok {
+		v := addwechatfriendlog.DefaultFindContent
+		awflc.mutation.SetFindContent(v)
+	}
+	if _, ok := awflc.mutation.Message(); !ok {
+		v := addwechatfriendlog.DefaultMessage
+		awflc.mutation.SetMessage(v)
+	}
+	if _, ok := awflc.mutation.IsCanAdd(); !ok {
+		v := addwechatfriendlog.DefaultIsCanAdd
+		awflc.mutation.SetIsCanAdd(v)
+	}
+	if _, ok := awflc.mutation.TaskCount(); !ok {
+		v := addwechatfriendlog.DefaultTaskCount
+		awflc.mutation.SetTaskCount(v)
+	}
+	if _, ok := awflc.mutation.TaskID(); !ok {
+		v := addwechatfriendlog.DefaultTaskID
+		awflc.mutation.SetTaskID(v)
+	}
+	if _, ok := awflc.mutation.CreatedAt(); !ok {
+		v := addwechatfriendlog.DefaultCreatedAt()
+		awflc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := awflc.mutation.UpdatedAt(); !ok {
+		v := addwechatfriendlog.DefaultUpdatedAt()
+		awflc.mutation.SetUpdatedAt(v)
+	}
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (awflc *AddWechatFriendLogCreate) check() error {
+	if _, ok := awflc.mutation.OwnerWxID(); !ok {
+		return &ValidationError{Name: "owner_wx_id", err: errors.New(`ent: missing required field "AddWechatFriendLog.owner_wx_id"`)}
+	}
+	if v, ok := awflc.mutation.OwnerWxID(); ok {
+		if err := addwechatfriendlog.OwnerWxIDValidator(v); err != nil {
+			return &ValidationError{Name: "owner_wx_id", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.owner_wx_id": %w`, err)}
+		}
+	}
+	if _, ok := awflc.mutation.OwnerWxType(); !ok {
+		return &ValidationError{Name: "owner_wx_type", err: errors.New(`ent: missing required field "AddWechatFriendLog.owner_wx_type"`)}
+	}
+	if _, ok := awflc.mutation.FindContent(); !ok {
+		return &ValidationError{Name: "find_content", err: errors.New(`ent: missing required field "AddWechatFriendLog.find_content"`)}
+	}
+	if v, ok := awflc.mutation.FindContent(); ok {
+		if err := addwechatfriendlog.FindContentValidator(v); err != nil {
+			return &ValidationError{Name: "find_content", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.find_content": %w`, err)}
+		}
+	}
+	if _, ok := awflc.mutation.Message(); !ok {
+		return &ValidationError{Name: "message", err: errors.New(`ent: missing required field "AddWechatFriendLog.message"`)}
+	}
+	if v, ok := awflc.mutation.Message(); ok {
+		if err := addwechatfriendlog.MessageValidator(v); err != nil {
+			return &ValidationError{Name: "message", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.message": %w`, err)}
+		}
+	}
+	if _, ok := awflc.mutation.IsCanAdd(); !ok {
+		return &ValidationError{Name: "is_can_add", err: errors.New(`ent: missing required field "AddWechatFriendLog.is_can_add"`)}
+	}
+	if _, ok := awflc.mutation.TaskCount(); !ok {
+		return &ValidationError{Name: "task_count", err: errors.New(`ent: missing required field "AddWechatFriendLog.task_count"`)}
+	}
+	if _, ok := awflc.mutation.TaskID(); !ok {
+		return &ValidationError{Name: "task_id", err: errors.New(`ent: missing required field "AddWechatFriendLog.task_id"`)}
+	}
+	if _, ok := awflc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "AddWechatFriendLog.created_at"`)}
+	}
+	if _, ok := awflc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "AddWechatFriendLog.updated_at"`)}
+	}
+	return nil
+}
+
+func (awflc *AddWechatFriendLogCreate) sqlSave(ctx context.Context) (*AddWechatFriendLog, error) {
+	if err := awflc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := awflc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, awflc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = int64(id)
+	}
+	awflc.mutation.id = &_node.ID
+	awflc.mutation.done = true
+	return _node, nil
+}
+
+func (awflc *AddWechatFriendLogCreate) createSpec() (*AddWechatFriendLog, *sqlgraph.CreateSpec) {
+	var (
+		_node = &AddWechatFriendLog{config: awflc.config}
+		_spec = sqlgraph.NewCreateSpec(addwechatfriendlog.Table, sqlgraph.NewFieldSpec(addwechatfriendlog.FieldID, field.TypeInt64))
+	)
+	_spec.OnConflict = awflc.conflict
+	if id, ok := awflc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := awflc.mutation.OwnerWxID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxID, field.TypeString, value)
+		_node.OwnerWxID = value
+	}
+	if value, ok := awflc.mutation.OwnerWxType(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxType, field.TypeInt, value)
+		_node.OwnerWxType = value
+	}
+	if value, ok := awflc.mutation.FindContent(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindContent, field.TypeString, value)
+		_node.FindContent = value
+	}
+	if value, ok := awflc.mutation.Message(); ok {
+		_spec.SetField(addwechatfriendlog.FieldMessage, field.TypeString, value)
+		_node.Message = value
+	}
+	if value, ok := awflc.mutation.FindRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindRequest, field.TypeJSON, value)
+		_node.FindRequest = value
+	}
+	if value, ok := awflc.mutation.FindResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindResult, field.TypeJSON, value)
+		_node.FindResult = value
+	}
+	if value, ok := awflc.mutation.IsCanAdd(); ok {
+		_spec.SetField(addwechatfriendlog.FieldIsCanAdd, field.TypeInt, value)
+		_node.IsCanAdd = value
+	}
+	if value, ok := awflc.mutation.TaskCount(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskCount, field.TypeInt, value)
+		_node.TaskCount = value
+	}
+	if value, ok := awflc.mutation.TaskID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskID, field.TypeInt64, value)
+		_node.TaskID = value
+	}
+	if value, ok := awflc.mutation.AddRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddRequest, field.TypeJSON, value)
+		_node.AddRequest = value
+	}
+	if value, ok := awflc.mutation.AddResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddResult, field.TypeJSON, value)
+		_node.AddResult = value
+	}
+	if value, ok := awflc.mutation.CreatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldCreatedAt, field.TypeInt64, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := awflc.mutation.UpdatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldUpdatedAt, field.TypeInt64, value)
+		_node.UpdatedAt = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.AddWechatFriendLog.Create().
+//		SetOwnerWxID(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.AddWechatFriendLogUpsert) {
+//			SetOwnerWxID(v+v).
+//		}).
+//		Exec(ctx)
+func (awflc *AddWechatFriendLogCreate) OnConflict(opts ...sql.ConflictOption) *AddWechatFriendLogUpsertOne {
+	awflc.conflict = opts
+	return &AddWechatFriendLogUpsertOne{
+		create: awflc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.AddWechatFriendLog.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (awflc *AddWechatFriendLogCreate) OnConflictColumns(columns ...string) *AddWechatFriendLogUpsertOne {
+	awflc.conflict = append(awflc.conflict, sql.ConflictColumns(columns...))
+	return &AddWechatFriendLogUpsertOne{
+		create: awflc,
+	}
+}
+
+type (
+	// AddWechatFriendLogUpsertOne is the builder for "upsert"-ing
+	//  one AddWechatFriendLog node.
+	AddWechatFriendLogUpsertOne struct {
+		create *AddWechatFriendLogCreate
+	}
+
+	// AddWechatFriendLogUpsert is the "OnConflict" setter.
+	AddWechatFriendLogUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (u *AddWechatFriendLogUpsert) SetOwnerWxID(v string) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldOwnerWxID, v)
+	return u
+}
+
+// UpdateOwnerWxID sets the "owner_wx_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateOwnerWxID() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldOwnerWxID)
+	return u
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsert) SetOwnerWxType(v int) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldOwnerWxType, v)
+	return u
+}
+
+// UpdateOwnerWxType sets the "owner_wx_type" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateOwnerWxType() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldOwnerWxType)
+	return u
+}
+
+// AddOwnerWxType adds v to the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsert) AddOwnerWxType(v int) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldOwnerWxType, v)
+	return u
+}
+
+// SetFindContent sets the "find_content" field.
+func (u *AddWechatFriendLogUpsert) SetFindContent(v string) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldFindContent, v)
+	return u
+}
+
+// UpdateFindContent sets the "find_content" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateFindContent() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldFindContent)
+	return u
+}
+
+// SetMessage sets the "message" field.
+func (u *AddWechatFriendLogUpsert) SetMessage(v string) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldMessage, v)
+	return u
+}
+
+// UpdateMessage sets the "message" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateMessage() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldMessage)
+	return u
+}
+
+// SetFindRequest sets the "find_request" field.
+func (u *AddWechatFriendLogUpsert) SetFindRequest(v map[string]interface{}) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldFindRequest, v)
+	return u
+}
+
+// UpdateFindRequest sets the "find_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateFindRequest() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldFindRequest)
+	return u
+}
+
+// ClearFindRequest clears the value of the "find_request" field.
+func (u *AddWechatFriendLogUpsert) ClearFindRequest() *AddWechatFriendLogUpsert {
+	u.SetNull(addwechatfriendlog.FieldFindRequest)
+	return u
+}
+
+// SetFindResult sets the "find_result" field.
+func (u *AddWechatFriendLogUpsert) SetFindResult(v map[string]interface{}) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldFindResult, v)
+	return u
+}
+
+// UpdateFindResult sets the "find_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateFindResult() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldFindResult)
+	return u
+}
+
+// ClearFindResult clears the value of the "find_result" field.
+func (u *AddWechatFriendLogUpsert) ClearFindResult() *AddWechatFriendLogUpsert {
+	u.SetNull(addwechatfriendlog.FieldFindResult)
+	return u
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (u *AddWechatFriendLogUpsert) SetIsCanAdd(v int) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldIsCanAdd, v)
+	return u
+}
+
+// UpdateIsCanAdd sets the "is_can_add" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateIsCanAdd() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldIsCanAdd)
+	return u
+}
+
+// AddIsCanAdd adds v to the "is_can_add" field.
+func (u *AddWechatFriendLogUpsert) AddIsCanAdd(v int) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldIsCanAdd, v)
+	return u
+}
+
+// SetTaskCount sets the "task_count" field.
+func (u *AddWechatFriendLogUpsert) SetTaskCount(v int) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldTaskCount, v)
+	return u
+}
+
+// UpdateTaskCount sets the "task_count" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateTaskCount() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldTaskCount)
+	return u
+}
+
+// AddTaskCount adds v to the "task_count" field.
+func (u *AddWechatFriendLogUpsert) AddTaskCount(v int) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldTaskCount, v)
+	return u
+}
+
+// SetTaskID sets the "task_id" field.
+func (u *AddWechatFriendLogUpsert) SetTaskID(v int64) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldTaskID, v)
+	return u
+}
+
+// UpdateTaskID sets the "task_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateTaskID() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldTaskID)
+	return u
+}
+
+// AddTaskID adds v to the "task_id" field.
+func (u *AddWechatFriendLogUpsert) AddTaskID(v int64) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldTaskID, v)
+	return u
+}
+
+// SetAddRequest sets the "add_request" field.
+func (u *AddWechatFriendLogUpsert) SetAddRequest(v map[string]interface{}) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldAddRequest, v)
+	return u
+}
+
+// UpdateAddRequest sets the "add_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateAddRequest() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldAddRequest)
+	return u
+}
+
+// ClearAddRequest clears the value of the "add_request" field.
+func (u *AddWechatFriendLogUpsert) ClearAddRequest() *AddWechatFriendLogUpsert {
+	u.SetNull(addwechatfriendlog.FieldAddRequest)
+	return u
+}
+
+// SetAddResult sets the "add_result" field.
+func (u *AddWechatFriendLogUpsert) SetAddResult(v map[string]interface{}) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldAddResult, v)
+	return u
+}
+
+// UpdateAddResult sets the "add_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateAddResult() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldAddResult)
+	return u
+}
+
+// ClearAddResult clears the value of the "add_result" field.
+func (u *AddWechatFriendLogUpsert) ClearAddResult() *AddWechatFriendLogUpsert {
+	u.SetNull(addwechatfriendlog.FieldAddResult)
+	return u
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (u *AddWechatFriendLogUpsert) SetCreatedAt(v int64) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldCreatedAt, v)
+	return u
+}
+
+// UpdateCreatedAt sets the "created_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateCreatedAt() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldCreatedAt)
+	return u
+}
+
+// AddCreatedAt adds v to the "created_at" field.
+func (u *AddWechatFriendLogUpsert) AddCreatedAt(v int64) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldCreatedAt, v)
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AddWechatFriendLogUpsert) SetUpdatedAt(v int64) *AddWechatFriendLogUpsert {
+	u.Set(addwechatfriendlog.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsert) UpdateUpdatedAt() *AddWechatFriendLogUpsert {
+	u.SetExcluded(addwechatfriendlog.FieldUpdatedAt)
+	return u
+}
+
+// AddUpdatedAt adds v to the "updated_at" field.
+func (u *AddWechatFriendLogUpsert) AddUpdatedAt(v int64) *AddWechatFriendLogUpsert {
+	u.Add(addwechatfriendlog.FieldUpdatedAt, v)
+	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:
+//
+//	client.AddWechatFriendLog.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(addwechatfriendlog.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *AddWechatFriendLogUpsertOne) UpdateNewValues() *AddWechatFriendLogUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(addwechatfriendlog.FieldID)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.AddWechatFriendLog.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *AddWechatFriendLogUpsertOne) Ignore() *AddWechatFriendLogUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *AddWechatFriendLogUpsertOne) DoNothing() *AddWechatFriendLogUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the AddWechatFriendLogCreate.OnConflict
+// documentation for more info.
+func (u *AddWechatFriendLogUpsertOne) Update(set func(*AddWechatFriendLogUpsert)) *AddWechatFriendLogUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&AddWechatFriendLogUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (u *AddWechatFriendLogUpsertOne) SetOwnerWxID(v string) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetOwnerWxID(v)
+	})
+}
+
+// UpdateOwnerWxID sets the "owner_wx_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateOwnerWxID() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateOwnerWxID()
+	})
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsertOne) SetOwnerWxType(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetOwnerWxType(v)
+	})
+}
+
+// AddOwnerWxType adds v to the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsertOne) AddOwnerWxType(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddOwnerWxType(v)
+	})
+}
+
+// UpdateOwnerWxType sets the "owner_wx_type" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateOwnerWxType() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateOwnerWxType()
+	})
+}
+
+// SetFindContent sets the "find_content" field.
+func (u *AddWechatFriendLogUpsertOne) SetFindContent(v string) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindContent(v)
+	})
+}
+
+// UpdateFindContent sets the "find_content" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateFindContent() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindContent()
+	})
+}
+
+// SetMessage sets the "message" field.
+func (u *AddWechatFriendLogUpsertOne) SetMessage(v string) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetMessage(v)
+	})
+}
+
+// UpdateMessage sets the "message" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateMessage() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateMessage()
+	})
+}
+
+// SetFindRequest sets the "find_request" field.
+func (u *AddWechatFriendLogUpsertOne) SetFindRequest(v map[string]interface{}) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindRequest(v)
+	})
+}
+
+// UpdateFindRequest sets the "find_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateFindRequest() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindRequest()
+	})
+}
+
+// ClearFindRequest clears the value of the "find_request" field.
+func (u *AddWechatFriendLogUpsertOne) ClearFindRequest() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearFindRequest()
+	})
+}
+
+// SetFindResult sets the "find_result" field.
+func (u *AddWechatFriendLogUpsertOne) SetFindResult(v map[string]interface{}) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindResult(v)
+	})
+}
+
+// UpdateFindResult sets the "find_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateFindResult() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindResult()
+	})
+}
+
+// ClearFindResult clears the value of the "find_result" field.
+func (u *AddWechatFriendLogUpsertOne) ClearFindResult() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearFindResult()
+	})
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (u *AddWechatFriendLogUpsertOne) SetIsCanAdd(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetIsCanAdd(v)
+	})
+}
+
+// AddIsCanAdd adds v to the "is_can_add" field.
+func (u *AddWechatFriendLogUpsertOne) AddIsCanAdd(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddIsCanAdd(v)
+	})
+}
+
+// UpdateIsCanAdd sets the "is_can_add" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateIsCanAdd() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateIsCanAdd()
+	})
+}
+
+// SetTaskCount sets the "task_count" field.
+func (u *AddWechatFriendLogUpsertOne) SetTaskCount(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetTaskCount(v)
+	})
+}
+
+// AddTaskCount adds v to the "task_count" field.
+func (u *AddWechatFriendLogUpsertOne) AddTaskCount(v int) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddTaskCount(v)
+	})
+}
+
+// UpdateTaskCount sets the "task_count" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateTaskCount() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateTaskCount()
+	})
+}
+
+// SetTaskID sets the "task_id" field.
+func (u *AddWechatFriendLogUpsertOne) SetTaskID(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetTaskID(v)
+	})
+}
+
+// AddTaskID adds v to the "task_id" field.
+func (u *AddWechatFriendLogUpsertOne) AddTaskID(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddTaskID(v)
+	})
+}
+
+// UpdateTaskID sets the "task_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateTaskID() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateTaskID()
+	})
+}
+
+// SetAddRequest sets the "add_request" field.
+func (u *AddWechatFriendLogUpsertOne) SetAddRequest(v map[string]interface{}) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetAddRequest(v)
+	})
+}
+
+// UpdateAddRequest sets the "add_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateAddRequest() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateAddRequest()
+	})
+}
+
+// ClearAddRequest clears the value of the "add_request" field.
+func (u *AddWechatFriendLogUpsertOne) ClearAddRequest() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearAddRequest()
+	})
+}
+
+// SetAddResult sets the "add_result" field.
+func (u *AddWechatFriendLogUpsertOne) SetAddResult(v map[string]interface{}) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetAddResult(v)
+	})
+}
+
+// UpdateAddResult sets the "add_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateAddResult() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateAddResult()
+	})
+}
+
+// ClearAddResult clears the value of the "add_result" field.
+func (u *AddWechatFriendLogUpsertOne) ClearAddResult() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearAddResult()
+	})
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (u *AddWechatFriendLogUpsertOne) SetCreatedAt(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetCreatedAt(v)
+	})
+}
+
+// AddCreatedAt adds v to the "created_at" field.
+func (u *AddWechatFriendLogUpsertOne) AddCreatedAt(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddCreatedAt(v)
+	})
+}
+
+// UpdateCreatedAt sets the "created_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateCreatedAt() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateCreatedAt()
+	})
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AddWechatFriendLogUpsertOne) SetUpdatedAt(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// AddUpdatedAt adds v to the "updated_at" field.
+func (u *AddWechatFriendLogUpsertOne) AddUpdatedAt(v int64) *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertOne) UpdateUpdatedAt() *AddWechatFriendLogUpsertOne {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// Exec executes the query.
+func (u *AddWechatFriendLogUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for AddWechatFriendLogCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *AddWechatFriendLogUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *AddWechatFriendLogUpsertOne) ID(ctx context.Context) (id int64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *AddWechatFriendLogUpsertOne) IDX(ctx context.Context) int64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// AddWechatFriendLogCreateBulk is the builder for creating many AddWechatFriendLog entities in bulk.
+type AddWechatFriendLogCreateBulk struct {
+	config
+	err      error
+	builders []*AddWechatFriendLogCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the AddWechatFriendLog entities in the database.
+func (awflcb *AddWechatFriendLogCreateBulk) Save(ctx context.Context) ([]*AddWechatFriendLog, error) {
+	if awflcb.err != nil {
+		return nil, awflcb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(awflcb.builders))
+	nodes := make([]*AddWechatFriendLog, len(awflcb.builders))
+	mutators := make([]Mutator, len(awflcb.builders))
+	for i := range awflcb.builders {
+		func(i int, root context.Context) {
+			builder := awflcb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*AddWechatFriendLogMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, awflcb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = awflcb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, awflcb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = int64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, awflcb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (awflcb *AddWechatFriendLogCreateBulk) SaveX(ctx context.Context) []*AddWechatFriendLog {
+	v, err := awflcb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (awflcb *AddWechatFriendLogCreateBulk) Exec(ctx context.Context) error {
+	_, err := awflcb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awflcb *AddWechatFriendLogCreateBulk) ExecX(ctx context.Context) {
+	if err := awflcb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.AddWechatFriendLog.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.AddWechatFriendLogUpsert) {
+//			SetOwnerWxID(v+v).
+//		}).
+//		Exec(ctx)
+func (awflcb *AddWechatFriendLogCreateBulk) OnConflict(opts ...sql.ConflictOption) *AddWechatFriendLogUpsertBulk {
+	awflcb.conflict = opts
+	return &AddWechatFriendLogUpsertBulk{
+		create: awflcb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.AddWechatFriendLog.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (awflcb *AddWechatFriendLogCreateBulk) OnConflictColumns(columns ...string) *AddWechatFriendLogUpsertBulk {
+	awflcb.conflict = append(awflcb.conflict, sql.ConflictColumns(columns...))
+	return &AddWechatFriendLogUpsertBulk{
+		create: awflcb,
+	}
+}
+
+// AddWechatFriendLogUpsertBulk is the builder for "upsert"-ing
+// a bulk of AddWechatFriendLog nodes.
+type AddWechatFriendLogUpsertBulk struct {
+	create *AddWechatFriendLogCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.AddWechatFriendLog.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(addwechatfriendlog.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *AddWechatFriendLogUpsertBulk) UpdateNewValues() *AddWechatFriendLogUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(addwechatfriendlog.FieldID)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.AddWechatFriendLog.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *AddWechatFriendLogUpsertBulk) Ignore() *AddWechatFriendLogUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *AddWechatFriendLogUpsertBulk) DoNothing() *AddWechatFriendLogUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the AddWechatFriendLogCreateBulk.OnConflict
+// documentation for more info.
+func (u *AddWechatFriendLogUpsertBulk) Update(set func(*AddWechatFriendLogUpsert)) *AddWechatFriendLogUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&AddWechatFriendLogUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (u *AddWechatFriendLogUpsertBulk) SetOwnerWxID(v string) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetOwnerWxID(v)
+	})
+}
+
+// UpdateOwnerWxID sets the "owner_wx_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateOwnerWxID() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateOwnerWxID()
+	})
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsertBulk) SetOwnerWxType(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetOwnerWxType(v)
+	})
+}
+
+// AddOwnerWxType adds v to the "owner_wx_type" field.
+func (u *AddWechatFriendLogUpsertBulk) AddOwnerWxType(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddOwnerWxType(v)
+	})
+}
+
+// UpdateOwnerWxType sets the "owner_wx_type" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateOwnerWxType() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateOwnerWxType()
+	})
+}
+
+// SetFindContent sets the "find_content" field.
+func (u *AddWechatFriendLogUpsertBulk) SetFindContent(v string) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindContent(v)
+	})
+}
+
+// UpdateFindContent sets the "find_content" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateFindContent() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindContent()
+	})
+}
+
+// SetMessage sets the "message" field.
+func (u *AddWechatFriendLogUpsertBulk) SetMessage(v string) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetMessage(v)
+	})
+}
+
+// UpdateMessage sets the "message" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateMessage() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateMessage()
+	})
+}
+
+// SetFindRequest sets the "find_request" field.
+func (u *AddWechatFriendLogUpsertBulk) SetFindRequest(v map[string]interface{}) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindRequest(v)
+	})
+}
+
+// UpdateFindRequest sets the "find_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateFindRequest() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindRequest()
+	})
+}
+
+// ClearFindRequest clears the value of the "find_request" field.
+func (u *AddWechatFriendLogUpsertBulk) ClearFindRequest() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearFindRequest()
+	})
+}
+
+// SetFindResult sets the "find_result" field.
+func (u *AddWechatFriendLogUpsertBulk) SetFindResult(v map[string]interface{}) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetFindResult(v)
+	})
+}
+
+// UpdateFindResult sets the "find_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateFindResult() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateFindResult()
+	})
+}
+
+// ClearFindResult clears the value of the "find_result" field.
+func (u *AddWechatFriendLogUpsertBulk) ClearFindResult() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearFindResult()
+	})
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (u *AddWechatFriendLogUpsertBulk) SetIsCanAdd(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetIsCanAdd(v)
+	})
+}
+
+// AddIsCanAdd adds v to the "is_can_add" field.
+func (u *AddWechatFriendLogUpsertBulk) AddIsCanAdd(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddIsCanAdd(v)
+	})
+}
+
+// UpdateIsCanAdd sets the "is_can_add" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateIsCanAdd() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateIsCanAdd()
+	})
+}
+
+// SetTaskCount sets the "task_count" field.
+func (u *AddWechatFriendLogUpsertBulk) SetTaskCount(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetTaskCount(v)
+	})
+}
+
+// AddTaskCount adds v to the "task_count" field.
+func (u *AddWechatFriendLogUpsertBulk) AddTaskCount(v int) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddTaskCount(v)
+	})
+}
+
+// UpdateTaskCount sets the "task_count" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateTaskCount() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateTaskCount()
+	})
+}
+
+// SetTaskID sets the "task_id" field.
+func (u *AddWechatFriendLogUpsertBulk) SetTaskID(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetTaskID(v)
+	})
+}
+
+// AddTaskID adds v to the "task_id" field.
+func (u *AddWechatFriendLogUpsertBulk) AddTaskID(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddTaskID(v)
+	})
+}
+
+// UpdateTaskID sets the "task_id" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateTaskID() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateTaskID()
+	})
+}
+
+// SetAddRequest sets the "add_request" field.
+func (u *AddWechatFriendLogUpsertBulk) SetAddRequest(v map[string]interface{}) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetAddRequest(v)
+	})
+}
+
+// UpdateAddRequest sets the "add_request" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateAddRequest() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateAddRequest()
+	})
+}
+
+// ClearAddRequest clears the value of the "add_request" field.
+func (u *AddWechatFriendLogUpsertBulk) ClearAddRequest() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearAddRequest()
+	})
+}
+
+// SetAddResult sets the "add_result" field.
+func (u *AddWechatFriendLogUpsertBulk) SetAddResult(v map[string]interface{}) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetAddResult(v)
+	})
+}
+
+// UpdateAddResult sets the "add_result" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateAddResult() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateAddResult()
+	})
+}
+
+// ClearAddResult clears the value of the "add_result" field.
+func (u *AddWechatFriendLogUpsertBulk) ClearAddResult() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.ClearAddResult()
+	})
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (u *AddWechatFriendLogUpsertBulk) SetCreatedAt(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetCreatedAt(v)
+	})
+}
+
+// AddCreatedAt adds v to the "created_at" field.
+func (u *AddWechatFriendLogUpsertBulk) AddCreatedAt(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddCreatedAt(v)
+	})
+}
+
+// UpdateCreatedAt sets the "created_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateCreatedAt() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateCreatedAt()
+	})
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *AddWechatFriendLogUpsertBulk) SetUpdatedAt(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// AddUpdatedAt adds v to the "updated_at" field.
+func (u *AddWechatFriendLogUpsertBulk) AddUpdatedAt(v int64) *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.AddUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *AddWechatFriendLogUpsertBulk) UpdateUpdatedAt() *AddWechatFriendLogUpsertBulk {
+	return u.Update(func(s *AddWechatFriendLogUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// Exec executes the query.
+func (u *AddWechatFriendLogUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the AddWechatFriendLogCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for AddWechatFriendLogCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *AddWechatFriendLogUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/addwechatfriendlog_delete.go

@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AddWechatFriendLogDelete is the builder for deleting a AddWechatFriendLog entity.
+type AddWechatFriendLogDelete struct {
+	config
+	hooks    []Hook
+	mutation *AddWechatFriendLogMutation
+}
+
+// Where appends a list predicates to the AddWechatFriendLogDelete builder.
+func (awfld *AddWechatFriendLogDelete) Where(ps ...predicate.AddWechatFriendLog) *AddWechatFriendLogDelete {
+	awfld.mutation.Where(ps...)
+	return awfld
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (awfld *AddWechatFriendLogDelete) Exec(ctx context.Context) (int, error) {
+	return withHooks(ctx, awfld.sqlExec, awfld.mutation, awfld.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awfld *AddWechatFriendLogDelete) ExecX(ctx context.Context) int {
+	n, err := awfld.Exec(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func (awfld *AddWechatFriendLogDelete) sqlExec(ctx context.Context) (int, error) {
+	_spec := sqlgraph.NewDeleteSpec(addwechatfriendlog.Table, sqlgraph.NewFieldSpec(addwechatfriendlog.FieldID, field.TypeInt64))
+	if ps := awfld.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	affected, err := sqlgraph.DeleteNodes(ctx, awfld.driver, _spec)
+	if err != nil && sqlgraph.IsConstraintError(err) {
+		err = &ConstraintError{msg: err.Error(), wrap: err}
+	}
+	awfld.mutation.done = true
+	return affected, err
+}
+
+// AddWechatFriendLogDeleteOne is the builder for deleting a single AddWechatFriendLog entity.
+type AddWechatFriendLogDeleteOne struct {
+	awfld *AddWechatFriendLogDelete
+}
+
+// Where appends a list predicates to the AddWechatFriendLogDelete builder.
+func (awfldo *AddWechatFriendLogDeleteOne) Where(ps ...predicate.AddWechatFriendLog) *AddWechatFriendLogDeleteOne {
+	awfldo.awfld.mutation.Where(ps...)
+	return awfldo
+}
+
+// Exec executes the deletion query.
+func (awfldo *AddWechatFriendLogDeleteOne) Exec(ctx context.Context) error {
+	n, err := awfldo.awfld.Exec(ctx)
+	switch {
+	case err != nil:
+		return err
+	case n == 0:
+		return &NotFoundError{addwechatfriendlog.Label}
+	default:
+		return nil
+	}
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awfldo *AddWechatFriendLogDeleteOne) ExecX(ctx context.Context) {
+	if err := awfldo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 526 - 0
ent/addwechatfriendlog_query.go

@@ -0,0 +1,526 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"fmt"
+	"math"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AddWechatFriendLogQuery is the builder for querying AddWechatFriendLog entities.
+type AddWechatFriendLogQuery struct {
+	config
+	ctx        *QueryContext
+	order      []addwechatfriendlog.OrderOption
+	inters     []Interceptor
+	predicates []predicate.AddWechatFriendLog
+	// intermediate query (i.e. traversal path).
+	sql  *sql.Selector
+	path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the AddWechatFriendLogQuery builder.
+func (awflq *AddWechatFriendLogQuery) Where(ps ...predicate.AddWechatFriendLog) *AddWechatFriendLogQuery {
+	awflq.predicates = append(awflq.predicates, ps...)
+	return awflq
+}
+
+// Limit the number of records to be returned by this query.
+func (awflq *AddWechatFriendLogQuery) Limit(limit int) *AddWechatFriendLogQuery {
+	awflq.ctx.Limit = &limit
+	return awflq
+}
+
+// Offset to start from.
+func (awflq *AddWechatFriendLogQuery) Offset(offset int) *AddWechatFriendLogQuery {
+	awflq.ctx.Offset = &offset
+	return awflq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (awflq *AddWechatFriendLogQuery) Unique(unique bool) *AddWechatFriendLogQuery {
+	awflq.ctx.Unique = &unique
+	return awflq
+}
+
+// Order specifies how the records should be ordered.
+func (awflq *AddWechatFriendLogQuery) Order(o ...addwechatfriendlog.OrderOption) *AddWechatFriendLogQuery {
+	awflq.order = append(awflq.order, o...)
+	return awflq
+}
+
+// First returns the first AddWechatFriendLog entity from the query.
+// Returns a *NotFoundError when no AddWechatFriendLog was found.
+func (awflq *AddWechatFriendLogQuery) First(ctx context.Context) (*AddWechatFriendLog, error) {
+	nodes, err := awflq.Limit(1).All(setContextOp(ctx, awflq.ctx, "First"))
+	if err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nil, &NotFoundError{addwechatfriendlog.Label}
+	}
+	return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) FirstX(ctx context.Context) *AddWechatFriendLog {
+	node, err := awflq.First(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return node
+}
+
+// FirstID returns the first AddWechatFriendLog ID from the query.
+// Returns a *NotFoundError when no AddWechatFriendLog ID was found.
+func (awflq *AddWechatFriendLogQuery) FirstID(ctx context.Context) (id int64, err error) {
+	var ids []int64
+	if ids, err = awflq.Limit(1).IDs(setContextOp(ctx, awflq.ctx, "FirstID")); err != nil {
+		return
+	}
+	if len(ids) == 0 {
+		err = &NotFoundError{addwechatfriendlog.Label}
+		return
+	}
+	return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) FirstIDX(ctx context.Context) int64 {
+	id, err := awflq.FirstID(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return id
+}
+
+// Only returns a single AddWechatFriendLog entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one AddWechatFriendLog entity is found.
+// Returns a *NotFoundError when no AddWechatFriendLog entities are found.
+func (awflq *AddWechatFriendLogQuery) Only(ctx context.Context) (*AddWechatFriendLog, error) {
+	nodes, err := awflq.Limit(2).All(setContextOp(ctx, awflq.ctx, "Only"))
+	if err != nil {
+		return nil, err
+	}
+	switch len(nodes) {
+	case 1:
+		return nodes[0], nil
+	case 0:
+		return nil, &NotFoundError{addwechatfriendlog.Label}
+	default:
+		return nil, &NotSingularError{addwechatfriendlog.Label}
+	}
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) OnlyX(ctx context.Context) *AddWechatFriendLog {
+	node, err := awflq.Only(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// OnlyID is like Only, but returns the only AddWechatFriendLog ID in the query.
+// Returns a *NotSingularError when more than one AddWechatFriendLog ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (awflq *AddWechatFriendLogQuery) OnlyID(ctx context.Context) (id int64, err error) {
+	var ids []int64
+	if ids, err = awflq.Limit(2).IDs(setContextOp(ctx, awflq.ctx, "OnlyID")); err != nil {
+		return
+	}
+	switch len(ids) {
+	case 1:
+		id = ids[0]
+	case 0:
+		err = &NotFoundError{addwechatfriendlog.Label}
+	default:
+		err = &NotSingularError{addwechatfriendlog.Label}
+	}
+	return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) OnlyIDX(ctx context.Context) int64 {
+	id, err := awflq.OnlyID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// All executes the query and returns a list of AddWechatFriendLogs.
+func (awflq *AddWechatFriendLogQuery) All(ctx context.Context) ([]*AddWechatFriendLog, error) {
+	ctx = setContextOp(ctx, awflq.ctx, "All")
+	if err := awflq.prepareQuery(ctx); err != nil {
+		return nil, err
+	}
+	qr := querierAll[[]*AddWechatFriendLog, *AddWechatFriendLogQuery]()
+	return withInterceptors[[]*AddWechatFriendLog](ctx, awflq, qr, awflq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) AllX(ctx context.Context) []*AddWechatFriendLog {
+	nodes, err := awflq.All(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return nodes
+}
+
+// IDs executes the query and returns a list of AddWechatFriendLog IDs.
+func (awflq *AddWechatFriendLogQuery) IDs(ctx context.Context) (ids []int64, err error) {
+	if awflq.ctx.Unique == nil && awflq.path != nil {
+		awflq.Unique(true)
+	}
+	ctx = setContextOp(ctx, awflq.ctx, "IDs")
+	if err = awflq.Select(addwechatfriendlog.FieldID).Scan(ctx, &ids); err != nil {
+		return nil, err
+	}
+	return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) IDsX(ctx context.Context) []int64 {
+	ids, err := awflq.IDs(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return ids
+}
+
+// Count returns the count of the given query.
+func (awflq *AddWechatFriendLogQuery) Count(ctx context.Context) (int, error) {
+	ctx = setContextOp(ctx, awflq.ctx, "Count")
+	if err := awflq.prepareQuery(ctx); err != nil {
+		return 0, err
+	}
+	return withInterceptors[int](ctx, awflq, querierCount[*AddWechatFriendLogQuery](), awflq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) CountX(ctx context.Context) int {
+	count, err := awflq.Count(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (awflq *AddWechatFriendLogQuery) Exist(ctx context.Context) (bool, error) {
+	ctx = setContextOp(ctx, awflq.ctx, "Exist")
+	switch _, err := awflq.FirstID(ctx); {
+	case IsNotFound(err):
+		return false, nil
+	case err != nil:
+		return false, fmt.Errorf("ent: check existence: %w", err)
+	default:
+		return true, nil
+	}
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (awflq *AddWechatFriendLogQuery) ExistX(ctx context.Context) bool {
+	exist, err := awflq.Exist(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return exist
+}
+
+// Clone returns a duplicate of the AddWechatFriendLogQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (awflq *AddWechatFriendLogQuery) Clone() *AddWechatFriendLogQuery {
+	if awflq == nil {
+		return nil
+	}
+	return &AddWechatFriendLogQuery{
+		config:     awflq.config,
+		ctx:        awflq.ctx.Clone(),
+		order:      append([]addwechatfriendlog.OrderOption{}, awflq.order...),
+		inters:     append([]Interceptor{}, awflq.inters...),
+		predicates: append([]predicate.AddWechatFriendLog{}, awflq.predicates...),
+		// clone intermediate query.
+		sql:  awflq.sql.Clone(),
+		path: awflq.path,
+	}
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+//	var v []struct {
+//		OwnerWxID string `json:"owner_wx_id,omitempty"`
+//		Count int `json:"count,omitempty"`
+//	}
+//
+//	client.AddWechatFriendLog.Query().
+//		GroupBy(addwechatfriendlog.FieldOwnerWxID).
+//		Aggregate(ent.Count()).
+//		Scan(ctx, &v)
+func (awflq *AddWechatFriendLogQuery) GroupBy(field string, fields ...string) *AddWechatFriendLogGroupBy {
+	awflq.ctx.Fields = append([]string{field}, fields...)
+	grbuild := &AddWechatFriendLogGroupBy{build: awflq}
+	grbuild.flds = &awflq.ctx.Fields
+	grbuild.label = addwechatfriendlog.Label
+	grbuild.scan = grbuild.Scan
+	return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+//	var v []struct {
+//		OwnerWxID string `json:"owner_wx_id,omitempty"`
+//	}
+//
+//	client.AddWechatFriendLog.Query().
+//		Select(addwechatfriendlog.FieldOwnerWxID).
+//		Scan(ctx, &v)
+func (awflq *AddWechatFriendLogQuery) Select(fields ...string) *AddWechatFriendLogSelect {
+	awflq.ctx.Fields = append(awflq.ctx.Fields, fields...)
+	sbuild := &AddWechatFriendLogSelect{AddWechatFriendLogQuery: awflq}
+	sbuild.label = addwechatfriendlog.Label
+	sbuild.flds, sbuild.scan = &awflq.ctx.Fields, sbuild.Scan
+	return sbuild
+}
+
+// Aggregate returns a AddWechatFriendLogSelect configured with the given aggregations.
+func (awflq *AddWechatFriendLogQuery) Aggregate(fns ...AggregateFunc) *AddWechatFriendLogSelect {
+	return awflq.Select().Aggregate(fns...)
+}
+
+func (awflq *AddWechatFriendLogQuery) prepareQuery(ctx context.Context) error {
+	for _, inter := range awflq.inters {
+		if inter == nil {
+			return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+		}
+		if trv, ok := inter.(Traverser); ok {
+			if err := trv.Traverse(ctx, awflq); err != nil {
+				return err
+			}
+		}
+	}
+	for _, f := range awflq.ctx.Fields {
+		if !addwechatfriendlog.ValidColumn(f) {
+			return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+		}
+	}
+	if awflq.path != nil {
+		prev, err := awflq.path(ctx)
+		if err != nil {
+			return err
+		}
+		awflq.sql = prev
+	}
+	return nil
+}
+
+func (awflq *AddWechatFriendLogQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*AddWechatFriendLog, error) {
+	var (
+		nodes = []*AddWechatFriendLog{}
+		_spec = awflq.querySpec()
+	)
+	_spec.ScanValues = func(columns []string) ([]any, error) {
+		return (*AddWechatFriendLog).scanValues(nil, columns)
+	}
+	_spec.Assign = func(columns []string, values []any) error {
+		node := &AddWechatFriendLog{config: awflq.config}
+		nodes = append(nodes, node)
+		return node.assignValues(columns, values)
+	}
+	for i := range hooks {
+		hooks[i](ctx, _spec)
+	}
+	if err := sqlgraph.QueryNodes(ctx, awflq.driver, _spec); err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nodes, nil
+	}
+	return nodes, nil
+}
+
+func (awflq *AddWechatFriendLogQuery) sqlCount(ctx context.Context) (int, error) {
+	_spec := awflq.querySpec()
+	_spec.Node.Columns = awflq.ctx.Fields
+	if len(awflq.ctx.Fields) > 0 {
+		_spec.Unique = awflq.ctx.Unique != nil && *awflq.ctx.Unique
+	}
+	return sqlgraph.CountNodes(ctx, awflq.driver, _spec)
+}
+
+func (awflq *AddWechatFriendLogQuery) querySpec() *sqlgraph.QuerySpec {
+	_spec := sqlgraph.NewQuerySpec(addwechatfriendlog.Table, addwechatfriendlog.Columns, sqlgraph.NewFieldSpec(addwechatfriendlog.FieldID, field.TypeInt64))
+	_spec.From = awflq.sql
+	if unique := awflq.ctx.Unique; unique != nil {
+		_spec.Unique = *unique
+	} else if awflq.path != nil {
+		_spec.Unique = true
+	}
+	if fields := awflq.ctx.Fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, addwechatfriendlog.FieldID)
+		for i := range fields {
+			if fields[i] != addwechatfriendlog.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+			}
+		}
+	}
+	if ps := awflq.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if limit := awflq.ctx.Limit; limit != nil {
+		_spec.Limit = *limit
+	}
+	if offset := awflq.ctx.Offset; offset != nil {
+		_spec.Offset = *offset
+	}
+	if ps := awflq.order; len(ps) > 0 {
+		_spec.Order = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	return _spec
+}
+
+func (awflq *AddWechatFriendLogQuery) sqlQuery(ctx context.Context) *sql.Selector {
+	builder := sql.Dialect(awflq.driver.Dialect())
+	t1 := builder.Table(addwechatfriendlog.Table)
+	columns := awflq.ctx.Fields
+	if len(columns) == 0 {
+		columns = addwechatfriendlog.Columns
+	}
+	selector := builder.Select(t1.Columns(columns...)...).From(t1)
+	if awflq.sql != nil {
+		selector = awflq.sql
+		selector.Select(selector.Columns(columns...)...)
+	}
+	if awflq.ctx.Unique != nil && *awflq.ctx.Unique {
+		selector.Distinct()
+	}
+	for _, p := range awflq.predicates {
+		p(selector)
+	}
+	for _, p := range awflq.order {
+		p(selector)
+	}
+	if offset := awflq.ctx.Offset; offset != nil {
+		// limit is mandatory for offset clause. We start
+		// with default value, and override it below if needed.
+		selector.Offset(*offset).Limit(math.MaxInt32)
+	}
+	if limit := awflq.ctx.Limit; limit != nil {
+		selector.Limit(*limit)
+	}
+	return selector
+}
+
+// AddWechatFriendLogGroupBy is the group-by builder for AddWechatFriendLog entities.
+type AddWechatFriendLogGroupBy struct {
+	selector
+	build *AddWechatFriendLogQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (awflgb *AddWechatFriendLogGroupBy) Aggregate(fns ...AggregateFunc) *AddWechatFriendLogGroupBy {
+	awflgb.fns = append(awflgb.fns, fns...)
+	return awflgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (awflgb *AddWechatFriendLogGroupBy) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, awflgb.build.ctx, "GroupBy")
+	if err := awflgb.build.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*AddWechatFriendLogQuery, *AddWechatFriendLogGroupBy](ctx, awflgb.build, awflgb, awflgb.build.inters, v)
+}
+
+func (awflgb *AddWechatFriendLogGroupBy) sqlScan(ctx context.Context, root *AddWechatFriendLogQuery, v any) error {
+	selector := root.sqlQuery(ctx).Select()
+	aggregation := make([]string, 0, len(awflgb.fns))
+	for _, fn := range awflgb.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	if len(selector.SelectedColumns()) == 0 {
+		columns := make([]string, 0, len(*awflgb.flds)+len(awflgb.fns))
+		for _, f := range *awflgb.flds {
+			columns = append(columns, selector.C(f))
+		}
+		columns = append(columns, aggregation...)
+		selector.Select(columns...)
+	}
+	selector.GroupBy(selector.Columns(*awflgb.flds...)...)
+	if err := selector.Err(); err != nil {
+		return err
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := awflgb.build.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}
+
+// AddWechatFriendLogSelect is the builder for selecting fields of AddWechatFriendLog entities.
+type AddWechatFriendLogSelect struct {
+	*AddWechatFriendLogQuery
+	selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (awfls *AddWechatFriendLogSelect) Aggregate(fns ...AggregateFunc) *AddWechatFriendLogSelect {
+	awfls.fns = append(awfls.fns, fns...)
+	return awfls
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (awfls *AddWechatFriendLogSelect) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, awfls.ctx, "Select")
+	if err := awfls.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*AddWechatFriendLogQuery, *AddWechatFriendLogSelect](ctx, awfls.AddWechatFriendLogQuery, awfls, awfls.inters, v)
+}
+
+func (awfls *AddWechatFriendLogSelect) sqlScan(ctx context.Context, root *AddWechatFriendLogQuery, v any) error {
+	selector := root.sqlQuery(ctx)
+	aggregation := make([]string, 0, len(awfls.fns))
+	for _, fn := range awfls.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	switch n := len(*awfls.selector.flds); {
+	case n == 0 && len(aggregation) > 0:
+		selector.Select(aggregation...)
+	case n != 0 && len(aggregation) > 0:
+		selector.AppendSelect(aggregation...)
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := awfls.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}

+ 793 - 0
ent/addwechatfriendlog_update.go

@@ -0,0 +1,793 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// AddWechatFriendLogUpdate is the builder for updating AddWechatFriendLog entities.
+type AddWechatFriendLogUpdate struct {
+	config
+	hooks    []Hook
+	mutation *AddWechatFriendLogMutation
+}
+
+// Where appends a list predicates to the AddWechatFriendLogUpdate builder.
+func (awflu *AddWechatFriendLogUpdate) Where(ps ...predicate.AddWechatFriendLog) *AddWechatFriendLogUpdate {
+	awflu.mutation.Where(ps...)
+	return awflu
+}
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (awflu *AddWechatFriendLogUpdate) SetOwnerWxID(s string) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetOwnerWxID(s)
+	return awflu
+}
+
+// SetNillableOwnerWxID sets the "owner_wx_id" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableOwnerWxID(s *string) *AddWechatFriendLogUpdate {
+	if s != nil {
+		awflu.SetOwnerWxID(*s)
+	}
+	return awflu
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (awflu *AddWechatFriendLogUpdate) SetOwnerWxType(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetOwnerWxType()
+	awflu.mutation.SetOwnerWxType(i)
+	return awflu
+}
+
+// SetNillableOwnerWxType sets the "owner_wx_type" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableOwnerWxType(i *int) *AddWechatFriendLogUpdate {
+	if i != nil {
+		awflu.SetOwnerWxType(*i)
+	}
+	return awflu
+}
+
+// AddOwnerWxType adds i to the "owner_wx_type" field.
+func (awflu *AddWechatFriendLogUpdate) AddOwnerWxType(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddOwnerWxType(i)
+	return awflu
+}
+
+// SetFindContent sets the "find_content" field.
+func (awflu *AddWechatFriendLogUpdate) SetFindContent(s string) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetFindContent(s)
+	return awflu
+}
+
+// SetNillableFindContent sets the "find_content" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableFindContent(s *string) *AddWechatFriendLogUpdate {
+	if s != nil {
+		awflu.SetFindContent(*s)
+	}
+	return awflu
+}
+
+// SetMessage sets the "message" field.
+func (awflu *AddWechatFriendLogUpdate) SetMessage(s string) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetMessage(s)
+	return awflu
+}
+
+// SetNillableMessage sets the "message" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableMessage(s *string) *AddWechatFriendLogUpdate {
+	if s != nil {
+		awflu.SetMessage(*s)
+	}
+	return awflu
+}
+
+// SetFindRequest sets the "find_request" field.
+func (awflu *AddWechatFriendLogUpdate) SetFindRequest(m map[string]interface{}) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetFindRequest(m)
+	return awflu
+}
+
+// ClearFindRequest clears the value of the "find_request" field.
+func (awflu *AddWechatFriendLogUpdate) ClearFindRequest() *AddWechatFriendLogUpdate {
+	awflu.mutation.ClearFindRequest()
+	return awflu
+}
+
+// SetFindResult sets the "find_result" field.
+func (awflu *AddWechatFriendLogUpdate) SetFindResult(m map[string]interface{}) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetFindResult(m)
+	return awflu
+}
+
+// ClearFindResult clears the value of the "find_result" field.
+func (awflu *AddWechatFriendLogUpdate) ClearFindResult() *AddWechatFriendLogUpdate {
+	awflu.mutation.ClearFindResult()
+	return awflu
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (awflu *AddWechatFriendLogUpdate) SetIsCanAdd(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetIsCanAdd()
+	awflu.mutation.SetIsCanAdd(i)
+	return awflu
+}
+
+// SetNillableIsCanAdd sets the "is_can_add" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableIsCanAdd(i *int) *AddWechatFriendLogUpdate {
+	if i != nil {
+		awflu.SetIsCanAdd(*i)
+	}
+	return awflu
+}
+
+// AddIsCanAdd adds i to the "is_can_add" field.
+func (awflu *AddWechatFriendLogUpdate) AddIsCanAdd(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddIsCanAdd(i)
+	return awflu
+}
+
+// SetTaskCount sets the "task_count" field.
+func (awflu *AddWechatFriendLogUpdate) SetTaskCount(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetTaskCount()
+	awflu.mutation.SetTaskCount(i)
+	return awflu
+}
+
+// SetNillableTaskCount sets the "task_count" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableTaskCount(i *int) *AddWechatFriendLogUpdate {
+	if i != nil {
+		awflu.SetTaskCount(*i)
+	}
+	return awflu
+}
+
+// AddTaskCount adds i to the "task_count" field.
+func (awflu *AddWechatFriendLogUpdate) AddTaskCount(i int) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddTaskCount(i)
+	return awflu
+}
+
+// SetTaskID sets the "task_id" field.
+func (awflu *AddWechatFriendLogUpdate) SetTaskID(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetTaskID()
+	awflu.mutation.SetTaskID(i)
+	return awflu
+}
+
+// SetNillableTaskID sets the "task_id" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableTaskID(i *int64) *AddWechatFriendLogUpdate {
+	if i != nil {
+		awflu.SetTaskID(*i)
+	}
+	return awflu
+}
+
+// AddTaskID adds i to the "task_id" field.
+func (awflu *AddWechatFriendLogUpdate) AddTaskID(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddTaskID(i)
+	return awflu
+}
+
+// SetAddRequest sets the "add_request" field.
+func (awflu *AddWechatFriendLogUpdate) SetAddRequest(m map[string]interface{}) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetAddRequest(m)
+	return awflu
+}
+
+// ClearAddRequest clears the value of the "add_request" field.
+func (awflu *AddWechatFriendLogUpdate) ClearAddRequest() *AddWechatFriendLogUpdate {
+	awflu.mutation.ClearAddRequest()
+	return awflu
+}
+
+// SetAddResult sets the "add_result" field.
+func (awflu *AddWechatFriendLogUpdate) SetAddResult(m map[string]interface{}) *AddWechatFriendLogUpdate {
+	awflu.mutation.SetAddResult(m)
+	return awflu
+}
+
+// ClearAddResult clears the value of the "add_result" field.
+func (awflu *AddWechatFriendLogUpdate) ClearAddResult() *AddWechatFriendLogUpdate {
+	awflu.mutation.ClearAddResult()
+	return awflu
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (awflu *AddWechatFriendLogUpdate) SetCreatedAt(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetCreatedAt()
+	awflu.mutation.SetCreatedAt(i)
+	return awflu
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (awflu *AddWechatFriendLogUpdate) SetNillableCreatedAt(i *int64) *AddWechatFriendLogUpdate {
+	if i != nil {
+		awflu.SetCreatedAt(*i)
+	}
+	return awflu
+}
+
+// AddCreatedAt adds i to the "created_at" field.
+func (awflu *AddWechatFriendLogUpdate) AddCreatedAt(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddCreatedAt(i)
+	return awflu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (awflu *AddWechatFriendLogUpdate) SetUpdatedAt(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.ResetUpdatedAt()
+	awflu.mutation.SetUpdatedAt(i)
+	return awflu
+}
+
+// AddUpdatedAt adds i to the "updated_at" field.
+func (awflu *AddWechatFriendLogUpdate) AddUpdatedAt(i int64) *AddWechatFriendLogUpdate {
+	awflu.mutation.AddUpdatedAt(i)
+	return awflu
+}
+
+// Mutation returns the AddWechatFriendLogMutation object of the builder.
+func (awflu *AddWechatFriendLogUpdate) Mutation() *AddWechatFriendLogMutation {
+	return awflu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (awflu *AddWechatFriendLogUpdate) Save(ctx context.Context) (int, error) {
+	awflu.defaults()
+	return withHooks(ctx, awflu.sqlSave, awflu.mutation, awflu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (awflu *AddWechatFriendLogUpdate) SaveX(ctx context.Context) int {
+	affected, err := awflu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (awflu *AddWechatFriendLogUpdate) Exec(ctx context.Context) error {
+	_, err := awflu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awflu *AddWechatFriendLogUpdate) ExecX(ctx context.Context) {
+	if err := awflu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (awflu *AddWechatFriendLogUpdate) defaults() {
+	if _, ok := awflu.mutation.UpdatedAt(); !ok {
+		v := addwechatfriendlog.UpdateDefaultUpdatedAt()
+		awflu.mutation.SetUpdatedAt(v)
+	}
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (awflu *AddWechatFriendLogUpdate) check() error {
+	if v, ok := awflu.mutation.OwnerWxID(); ok {
+		if err := addwechatfriendlog.OwnerWxIDValidator(v); err != nil {
+			return &ValidationError{Name: "owner_wx_id", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.owner_wx_id": %w`, err)}
+		}
+	}
+	if v, ok := awflu.mutation.FindContent(); ok {
+		if err := addwechatfriendlog.FindContentValidator(v); err != nil {
+			return &ValidationError{Name: "find_content", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.find_content": %w`, err)}
+		}
+	}
+	if v, ok := awflu.mutation.Message(); ok {
+		if err := addwechatfriendlog.MessageValidator(v); err != nil {
+			return &ValidationError{Name: "message", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.message": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (awflu *AddWechatFriendLogUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := awflu.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(addwechatfriendlog.Table, addwechatfriendlog.Columns, sqlgraph.NewFieldSpec(addwechatfriendlog.FieldID, field.TypeInt64))
+	if ps := awflu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := awflu.mutation.OwnerWxID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxID, field.TypeString, value)
+	}
+	if value, ok := awflu.mutation.OwnerWxType(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxType, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.AddedOwnerWxType(); ok {
+		_spec.AddField(addwechatfriendlog.FieldOwnerWxType, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.FindContent(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindContent, field.TypeString, value)
+	}
+	if value, ok := awflu.mutation.Message(); ok {
+		_spec.SetField(addwechatfriendlog.FieldMessage, field.TypeString, value)
+	}
+	if value, ok := awflu.mutation.FindRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindRequest, field.TypeJSON, value)
+	}
+	if awflu.mutation.FindRequestCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldFindRequest, field.TypeJSON)
+	}
+	if value, ok := awflu.mutation.FindResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindResult, field.TypeJSON, value)
+	}
+	if awflu.mutation.FindResultCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldFindResult, field.TypeJSON)
+	}
+	if value, ok := awflu.mutation.IsCanAdd(); ok {
+		_spec.SetField(addwechatfriendlog.FieldIsCanAdd, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.AddedIsCanAdd(); ok {
+		_spec.AddField(addwechatfriendlog.FieldIsCanAdd, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.TaskCount(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskCount, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.AddedTaskCount(); ok {
+		_spec.AddField(addwechatfriendlog.FieldTaskCount, field.TypeInt, value)
+	}
+	if value, ok := awflu.mutation.TaskID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskID, field.TypeInt64, value)
+	}
+	if value, ok := awflu.mutation.AddedTaskID(); ok {
+		_spec.AddField(addwechatfriendlog.FieldTaskID, field.TypeInt64, value)
+	}
+	if value, ok := awflu.mutation.AddRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddRequest, field.TypeJSON, value)
+	}
+	if awflu.mutation.AddRequestCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldAddRequest, field.TypeJSON)
+	}
+	if value, ok := awflu.mutation.AddResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddResult, field.TypeJSON, value)
+	}
+	if awflu.mutation.AddResultCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldAddResult, field.TypeJSON)
+	}
+	if value, ok := awflu.mutation.CreatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldCreatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awflu.mutation.AddedCreatedAt(); ok {
+		_spec.AddField(addwechatfriendlog.FieldCreatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awflu.mutation.UpdatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldUpdatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awflu.mutation.AddedUpdatedAt(); ok {
+		_spec.AddField(addwechatfriendlog.FieldUpdatedAt, field.TypeInt64, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, awflu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{addwechatfriendlog.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	awflu.mutation.done = true
+	return n, nil
+}
+
+// AddWechatFriendLogUpdateOne is the builder for updating a single AddWechatFriendLog entity.
+type AddWechatFriendLogUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *AddWechatFriendLogMutation
+}
+
+// SetOwnerWxID sets the "owner_wx_id" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetOwnerWxID(s string) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetOwnerWxID(s)
+	return awfluo
+}
+
+// SetNillableOwnerWxID sets the "owner_wx_id" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableOwnerWxID(s *string) *AddWechatFriendLogUpdateOne {
+	if s != nil {
+		awfluo.SetOwnerWxID(*s)
+	}
+	return awfluo
+}
+
+// SetOwnerWxType sets the "owner_wx_type" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetOwnerWxType(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetOwnerWxType()
+	awfluo.mutation.SetOwnerWxType(i)
+	return awfluo
+}
+
+// SetNillableOwnerWxType sets the "owner_wx_type" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableOwnerWxType(i *int) *AddWechatFriendLogUpdateOne {
+	if i != nil {
+		awfluo.SetOwnerWxType(*i)
+	}
+	return awfluo
+}
+
+// AddOwnerWxType adds i to the "owner_wx_type" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddOwnerWxType(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddOwnerWxType(i)
+	return awfluo
+}
+
+// SetFindContent sets the "find_content" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetFindContent(s string) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetFindContent(s)
+	return awfluo
+}
+
+// SetNillableFindContent sets the "find_content" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableFindContent(s *string) *AddWechatFriendLogUpdateOne {
+	if s != nil {
+		awfluo.SetFindContent(*s)
+	}
+	return awfluo
+}
+
+// SetMessage sets the "message" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetMessage(s string) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetMessage(s)
+	return awfluo
+}
+
+// SetNillableMessage sets the "message" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableMessage(s *string) *AddWechatFriendLogUpdateOne {
+	if s != nil {
+		awfluo.SetMessage(*s)
+	}
+	return awfluo
+}
+
+// SetFindRequest sets the "find_request" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetFindRequest(m map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetFindRequest(m)
+	return awfluo
+}
+
+// ClearFindRequest clears the value of the "find_request" field.
+func (awfluo *AddWechatFriendLogUpdateOne) ClearFindRequest() *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ClearFindRequest()
+	return awfluo
+}
+
+// SetFindResult sets the "find_result" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetFindResult(m map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetFindResult(m)
+	return awfluo
+}
+
+// ClearFindResult clears the value of the "find_result" field.
+func (awfluo *AddWechatFriendLogUpdateOne) ClearFindResult() *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ClearFindResult()
+	return awfluo
+}
+
+// SetIsCanAdd sets the "is_can_add" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetIsCanAdd(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetIsCanAdd()
+	awfluo.mutation.SetIsCanAdd(i)
+	return awfluo
+}
+
+// SetNillableIsCanAdd sets the "is_can_add" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableIsCanAdd(i *int) *AddWechatFriendLogUpdateOne {
+	if i != nil {
+		awfluo.SetIsCanAdd(*i)
+	}
+	return awfluo
+}
+
+// AddIsCanAdd adds i to the "is_can_add" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddIsCanAdd(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddIsCanAdd(i)
+	return awfluo
+}
+
+// SetTaskCount sets the "task_count" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetTaskCount(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetTaskCount()
+	awfluo.mutation.SetTaskCount(i)
+	return awfluo
+}
+
+// SetNillableTaskCount sets the "task_count" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableTaskCount(i *int) *AddWechatFriendLogUpdateOne {
+	if i != nil {
+		awfluo.SetTaskCount(*i)
+	}
+	return awfluo
+}
+
+// AddTaskCount adds i to the "task_count" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddTaskCount(i int) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddTaskCount(i)
+	return awfluo
+}
+
+// SetTaskID sets the "task_id" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetTaskID(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetTaskID()
+	awfluo.mutation.SetTaskID(i)
+	return awfluo
+}
+
+// SetNillableTaskID sets the "task_id" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableTaskID(i *int64) *AddWechatFriendLogUpdateOne {
+	if i != nil {
+		awfluo.SetTaskID(*i)
+	}
+	return awfluo
+}
+
+// AddTaskID adds i to the "task_id" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddTaskID(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddTaskID(i)
+	return awfluo
+}
+
+// SetAddRequest sets the "add_request" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetAddRequest(m map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetAddRequest(m)
+	return awfluo
+}
+
+// ClearAddRequest clears the value of the "add_request" field.
+func (awfluo *AddWechatFriendLogUpdateOne) ClearAddRequest() *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ClearAddRequest()
+	return awfluo
+}
+
+// SetAddResult sets the "add_result" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetAddResult(m map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.SetAddResult(m)
+	return awfluo
+}
+
+// ClearAddResult clears the value of the "add_result" field.
+func (awfluo *AddWechatFriendLogUpdateOne) ClearAddResult() *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ClearAddResult()
+	return awfluo
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetCreatedAt(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetCreatedAt()
+	awfluo.mutation.SetCreatedAt(i)
+	return awfluo
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (awfluo *AddWechatFriendLogUpdateOne) SetNillableCreatedAt(i *int64) *AddWechatFriendLogUpdateOne {
+	if i != nil {
+		awfluo.SetCreatedAt(*i)
+	}
+	return awfluo
+}
+
+// AddCreatedAt adds i to the "created_at" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddCreatedAt(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddCreatedAt(i)
+	return awfluo
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (awfluo *AddWechatFriendLogUpdateOne) SetUpdatedAt(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.ResetUpdatedAt()
+	awfluo.mutation.SetUpdatedAt(i)
+	return awfluo
+}
+
+// AddUpdatedAt adds i to the "updated_at" field.
+func (awfluo *AddWechatFriendLogUpdateOne) AddUpdatedAt(i int64) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.AddUpdatedAt(i)
+	return awfluo
+}
+
+// Mutation returns the AddWechatFriendLogMutation object of the builder.
+func (awfluo *AddWechatFriendLogUpdateOne) Mutation() *AddWechatFriendLogMutation {
+	return awfluo.mutation
+}
+
+// Where appends a list predicates to the AddWechatFriendLogUpdate builder.
+func (awfluo *AddWechatFriendLogUpdateOne) Where(ps ...predicate.AddWechatFriendLog) *AddWechatFriendLogUpdateOne {
+	awfluo.mutation.Where(ps...)
+	return awfluo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (awfluo *AddWechatFriendLogUpdateOne) Select(field string, fields ...string) *AddWechatFriendLogUpdateOne {
+	awfluo.fields = append([]string{field}, fields...)
+	return awfluo
+}
+
+// Save executes the query and returns the updated AddWechatFriendLog entity.
+func (awfluo *AddWechatFriendLogUpdateOne) Save(ctx context.Context) (*AddWechatFriendLog, error) {
+	awfluo.defaults()
+	return withHooks(ctx, awfluo.sqlSave, awfluo.mutation, awfluo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (awfluo *AddWechatFriendLogUpdateOne) SaveX(ctx context.Context) *AddWechatFriendLog {
+	node, err := awfluo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (awfluo *AddWechatFriendLogUpdateOne) Exec(ctx context.Context) error {
+	_, err := awfluo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (awfluo *AddWechatFriendLogUpdateOne) ExecX(ctx context.Context) {
+	if err := awfluo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (awfluo *AddWechatFriendLogUpdateOne) defaults() {
+	if _, ok := awfluo.mutation.UpdatedAt(); !ok {
+		v := addwechatfriendlog.UpdateDefaultUpdatedAt()
+		awfluo.mutation.SetUpdatedAt(v)
+	}
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (awfluo *AddWechatFriendLogUpdateOne) check() error {
+	if v, ok := awfluo.mutation.OwnerWxID(); ok {
+		if err := addwechatfriendlog.OwnerWxIDValidator(v); err != nil {
+			return &ValidationError{Name: "owner_wx_id", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.owner_wx_id": %w`, err)}
+		}
+	}
+	if v, ok := awfluo.mutation.FindContent(); ok {
+		if err := addwechatfriendlog.FindContentValidator(v); err != nil {
+			return &ValidationError{Name: "find_content", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.find_content": %w`, err)}
+		}
+	}
+	if v, ok := awfluo.mutation.Message(); ok {
+		if err := addwechatfriendlog.MessageValidator(v); err != nil {
+			return &ValidationError{Name: "message", err: fmt.Errorf(`ent: validator failed for field "AddWechatFriendLog.message": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (awfluo *AddWechatFriendLogUpdateOne) sqlSave(ctx context.Context) (_node *AddWechatFriendLog, err error) {
+	if err := awfluo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(addwechatfriendlog.Table, addwechatfriendlog.Columns, sqlgraph.NewFieldSpec(addwechatfriendlog.FieldID, field.TypeInt64))
+	id, ok := awfluo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "AddWechatFriendLog.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := awfluo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, addwechatfriendlog.FieldID)
+		for _, f := range fields {
+			if !addwechatfriendlog.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != addwechatfriendlog.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := awfluo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := awfluo.mutation.OwnerWxID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxID, field.TypeString, value)
+	}
+	if value, ok := awfluo.mutation.OwnerWxType(); ok {
+		_spec.SetField(addwechatfriendlog.FieldOwnerWxType, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.AddedOwnerWxType(); ok {
+		_spec.AddField(addwechatfriendlog.FieldOwnerWxType, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.FindContent(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindContent, field.TypeString, value)
+	}
+	if value, ok := awfluo.mutation.Message(); ok {
+		_spec.SetField(addwechatfriendlog.FieldMessage, field.TypeString, value)
+	}
+	if value, ok := awfluo.mutation.FindRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindRequest, field.TypeJSON, value)
+	}
+	if awfluo.mutation.FindRequestCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldFindRequest, field.TypeJSON)
+	}
+	if value, ok := awfluo.mutation.FindResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldFindResult, field.TypeJSON, value)
+	}
+	if awfluo.mutation.FindResultCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldFindResult, field.TypeJSON)
+	}
+	if value, ok := awfluo.mutation.IsCanAdd(); ok {
+		_spec.SetField(addwechatfriendlog.FieldIsCanAdd, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.AddedIsCanAdd(); ok {
+		_spec.AddField(addwechatfriendlog.FieldIsCanAdd, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.TaskCount(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskCount, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.AddedTaskCount(); ok {
+		_spec.AddField(addwechatfriendlog.FieldTaskCount, field.TypeInt, value)
+	}
+	if value, ok := awfluo.mutation.TaskID(); ok {
+		_spec.SetField(addwechatfriendlog.FieldTaskID, field.TypeInt64, value)
+	}
+	if value, ok := awfluo.mutation.AddedTaskID(); ok {
+		_spec.AddField(addwechatfriendlog.FieldTaskID, field.TypeInt64, value)
+	}
+	if value, ok := awfluo.mutation.AddRequest(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddRequest, field.TypeJSON, value)
+	}
+	if awfluo.mutation.AddRequestCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldAddRequest, field.TypeJSON)
+	}
+	if value, ok := awfluo.mutation.AddResult(); ok {
+		_spec.SetField(addwechatfriendlog.FieldAddResult, field.TypeJSON, value)
+	}
+	if awfluo.mutation.AddResultCleared() {
+		_spec.ClearField(addwechatfriendlog.FieldAddResult, field.TypeJSON)
+	}
+	if value, ok := awfluo.mutation.CreatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldCreatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awfluo.mutation.AddedCreatedAt(); ok {
+		_spec.AddField(addwechatfriendlog.FieldCreatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awfluo.mutation.UpdatedAt(); ok {
+		_spec.SetField(addwechatfriendlog.FieldUpdatedAt, field.TypeInt64, value)
+	}
+	if value, ok := awfluo.mutation.AddedUpdatedAt(); ok {
+		_spec.AddField(addwechatfriendlog.FieldUpdatedAt, field.TypeInt64, value)
+	}
+	_node = &AddWechatFriendLog{config: awfluo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, awfluo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{addwechatfriendlog.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	awfluo.mutation.done = true
+	return _node, nil
+}

+ 180 - 37
ent/client.go

@@ -11,6 +11,7 @@ import (
 
 	"wechat-api/ent/migrate"
 
+	"wechat-api/ent/addwechatfriendlog"
 	"wechat-api/ent/agent"
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/aliyunavatar"
@@ -72,6 +73,8 @@ type Client struct {
 	config
 	// Schema is the client for creating, migrating and dropping schema.
 	Schema *migrate.Schema
+	// AddWechatFriendLog is the client for interacting with the AddWechatFriendLog builders.
+	AddWechatFriendLog *AddWechatFriendLogClient
 	// Agent is the client for interacting with the Agent builders.
 	Agent *AgentClient
 	// AgentBase is the client for interacting with the AgentBase builders.
@@ -177,6 +180,7 @@ func NewClient(opts ...Option) *Client {
 
 func (c *Client) init() {
 	c.Schema = migrate.NewSchema(c.driver)
+	c.AddWechatFriendLog = NewAddWechatFriendLogClient(c.config)
 	c.Agent = NewAgentClient(c.config)
 	c.AgentBase = NewAgentBaseClient(c.config)
 	c.AliyunAvatar = NewAliyunAvatarClient(c.config)
@@ -316,6 +320,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 	return &Tx{
 		ctx:                  ctx,
 		config:               cfg,
+		AddWechatFriendLog:   NewAddWechatFriendLogClient(cfg),
 		Agent:                NewAgentClient(cfg),
 		AgentBase:            NewAgentBaseClient(cfg),
 		AliyunAvatar:         NewAliyunAvatarClient(cfg),
@@ -382,6 +387,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 	return &Tx{
 		ctx:                  ctx,
 		config:               cfg,
+		AddWechatFriendLog:   NewAddWechatFriendLogClient(cfg),
 		Agent:                NewAgentClient(cfg),
 		AgentBase:            NewAgentBaseClient(cfg),
 		AliyunAvatar:         NewAliyunAvatarClient(cfg),
@@ -435,7 +441,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 // Debug returns a new debug-client. It's used to get verbose logging on specific operations.
 //
 //	client.Debug().
-//		Agent.
+//		AddWechatFriendLog.
 //		Query().
 //		Count(ctx)
 func (c *Client) Debug() *Client {
@@ -458,16 +464,16 @@ func (c *Client) Close() error {
 // In order to add hooks to a specific client, call: `client.Node.Use(...)`.
 func (c *Client) Use(hooks ...Hook) {
 	for _, n := range []interface{ Use(...Hook) }{
-		c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent, c.ApiKey, c.BatchMsg,
-		c.Category, c.ChatRecords, c.ChatSession, c.CompapiAsynctask, c.Contact,
-		c.ContactField, c.ContactFieldTemplate, c.CreditBalance, c.CreditUsage,
-		c.Employee, c.EmployeeConfig, c.Label, c.LabelLog, c.LabelRelationship,
-		c.LabelTagging, c.Message, c.MessageRecords, c.Msg, c.PayRecharge, c.Server,
-		c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial, c.UsageDetail,
-		c.UsageStatisticDay, c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal,
-		c.Whatsapp, c.WhatsappChannel, c.WorkExperience, c.WpChatroom,
-		c.WpChatroomMember, c.Wx, c.WxCard, c.WxCardUser, c.WxCardVisit, c.Xunji,
-		c.XunjiService,
+		c.AddWechatFriendLog, c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent,
+		c.ApiKey, c.BatchMsg, c.Category, c.ChatRecords, c.ChatSession,
+		c.CompapiAsynctask, c.Contact, c.ContactField, c.ContactFieldTemplate,
+		c.CreditBalance, c.CreditUsage, c.Employee, c.EmployeeConfig, c.Label,
+		c.LabelLog, c.LabelRelationship, c.LabelTagging, c.Message, c.MessageRecords,
+		c.Msg, c.PayRecharge, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Token,
+		c.Tutorial, c.UsageDetail, c.UsageStatisticDay, c.UsageStatisticHour,
+		c.UsageStatisticMonth, c.UsageTotal, c.Whatsapp, c.WhatsappChannel,
+		c.WorkExperience, c.WpChatroom, c.WpChatroomMember, c.Wx, c.WxCard,
+		c.WxCardUser, c.WxCardVisit, c.Xunji, c.XunjiService,
 	} {
 		n.Use(hooks...)
 	}
@@ -477,16 +483,16 @@ func (c *Client) Use(hooks ...Hook) {
 // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
 func (c *Client) Intercept(interceptors ...Interceptor) {
 	for _, n := range []interface{ Intercept(...Interceptor) }{
-		c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent, c.ApiKey, c.BatchMsg,
-		c.Category, c.ChatRecords, c.ChatSession, c.CompapiAsynctask, c.Contact,
-		c.ContactField, c.ContactFieldTemplate, c.CreditBalance, c.CreditUsage,
-		c.Employee, c.EmployeeConfig, c.Label, c.LabelLog, c.LabelRelationship,
-		c.LabelTagging, c.Message, c.MessageRecords, c.Msg, c.PayRecharge, c.Server,
-		c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial, c.UsageDetail,
-		c.UsageStatisticDay, c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal,
-		c.Whatsapp, c.WhatsappChannel, c.WorkExperience, c.WpChatroom,
-		c.WpChatroomMember, c.Wx, c.WxCard, c.WxCardUser, c.WxCardVisit, c.Xunji,
-		c.XunjiService,
+		c.AddWechatFriendLog, c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent,
+		c.ApiKey, c.BatchMsg, c.Category, c.ChatRecords, c.ChatSession,
+		c.CompapiAsynctask, c.Contact, c.ContactField, c.ContactFieldTemplate,
+		c.CreditBalance, c.CreditUsage, c.Employee, c.EmployeeConfig, c.Label,
+		c.LabelLog, c.LabelRelationship, c.LabelTagging, c.Message, c.MessageRecords,
+		c.Msg, c.PayRecharge, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Token,
+		c.Tutorial, c.UsageDetail, c.UsageStatisticDay, c.UsageStatisticHour,
+		c.UsageStatisticMonth, c.UsageTotal, c.Whatsapp, c.WhatsappChannel,
+		c.WorkExperience, c.WpChatroom, c.WpChatroomMember, c.Wx, c.WxCard,
+		c.WxCardUser, c.WxCardVisit, c.Xunji, c.XunjiService,
 	} {
 		n.Intercept(interceptors...)
 	}
@@ -495,6 +501,8 @@ func (c *Client) Intercept(interceptors ...Interceptor) {
 // Mutate implements the ent.Mutator interface.
 func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 	switch m := m.(type) {
+	case *AddWechatFriendLogMutation:
+		return c.AddWechatFriendLog.mutate(ctx, m)
 	case *AgentMutation:
 		return c.Agent.mutate(ctx, m)
 	case *AgentBaseMutation:
@@ -594,6 +602,139 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 	}
 }
 
+// AddWechatFriendLogClient is a client for the AddWechatFriendLog schema.
+type AddWechatFriendLogClient struct {
+	config
+}
+
+// NewAddWechatFriendLogClient returns a client for the AddWechatFriendLog from the given config.
+func NewAddWechatFriendLogClient(c config) *AddWechatFriendLogClient {
+	return &AddWechatFriendLogClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `addwechatfriendlog.Hooks(f(g(h())))`.
+func (c *AddWechatFriendLogClient) Use(hooks ...Hook) {
+	c.hooks.AddWechatFriendLog = append(c.hooks.AddWechatFriendLog, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `addwechatfriendlog.Intercept(f(g(h())))`.
+func (c *AddWechatFriendLogClient) Intercept(interceptors ...Interceptor) {
+	c.inters.AddWechatFriendLog = append(c.inters.AddWechatFriendLog, interceptors...)
+}
+
+// Create returns a builder for creating a AddWechatFriendLog entity.
+func (c *AddWechatFriendLogClient) Create() *AddWechatFriendLogCreate {
+	mutation := newAddWechatFriendLogMutation(c.config, OpCreate)
+	return &AddWechatFriendLogCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of AddWechatFriendLog entities.
+func (c *AddWechatFriendLogClient) CreateBulk(builders ...*AddWechatFriendLogCreate) *AddWechatFriendLogCreateBulk {
+	return &AddWechatFriendLogCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *AddWechatFriendLogClient) MapCreateBulk(slice any, setFunc func(*AddWechatFriendLogCreate, int)) *AddWechatFriendLogCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &AddWechatFriendLogCreateBulk{err: fmt.Errorf("calling to AddWechatFriendLogClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*AddWechatFriendLogCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &AddWechatFriendLogCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for AddWechatFriendLog.
+func (c *AddWechatFriendLogClient) Update() *AddWechatFriendLogUpdate {
+	mutation := newAddWechatFriendLogMutation(c.config, OpUpdate)
+	return &AddWechatFriendLogUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *AddWechatFriendLogClient) UpdateOne(awfl *AddWechatFriendLog) *AddWechatFriendLogUpdateOne {
+	mutation := newAddWechatFriendLogMutation(c.config, OpUpdateOne, withAddWechatFriendLog(awfl))
+	return &AddWechatFriendLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *AddWechatFriendLogClient) UpdateOneID(id int64) *AddWechatFriendLogUpdateOne {
+	mutation := newAddWechatFriendLogMutation(c.config, OpUpdateOne, withAddWechatFriendLogID(id))
+	return &AddWechatFriendLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for AddWechatFriendLog.
+func (c *AddWechatFriendLogClient) Delete() *AddWechatFriendLogDelete {
+	mutation := newAddWechatFriendLogMutation(c.config, OpDelete)
+	return &AddWechatFriendLogDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *AddWechatFriendLogClient) DeleteOne(awfl *AddWechatFriendLog) *AddWechatFriendLogDeleteOne {
+	return c.DeleteOneID(awfl.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *AddWechatFriendLogClient) DeleteOneID(id int64) *AddWechatFriendLogDeleteOne {
+	builder := c.Delete().Where(addwechatfriendlog.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &AddWechatFriendLogDeleteOne{builder}
+}
+
+// Query returns a query builder for AddWechatFriendLog.
+func (c *AddWechatFriendLogClient) Query() *AddWechatFriendLogQuery {
+	return &AddWechatFriendLogQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeAddWechatFriendLog},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a AddWechatFriendLog entity by its id.
+func (c *AddWechatFriendLogClient) Get(ctx context.Context, id int64) (*AddWechatFriendLog, error) {
+	return c.Query().Where(addwechatfriendlog.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *AddWechatFriendLogClient) GetX(ctx context.Context, id int64) *AddWechatFriendLog {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *AddWechatFriendLogClient) Hooks() []Hook {
+	return c.hooks.AddWechatFriendLog
+}
+
+// Interceptors returns the client interceptors.
+func (c *AddWechatFriendLogClient) Interceptors() []Interceptor {
+	return c.inters.AddWechatFriendLog
+}
+
+func (c *AddWechatFriendLogClient) mutate(ctx context.Context, m *AddWechatFriendLogMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&AddWechatFriendLogCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&AddWechatFriendLogUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&AddWechatFriendLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&AddWechatFriendLogDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown AddWechatFriendLog mutation op: %q", m.Op())
+	}
+}
+
 // AgentClient is a client for the Agent schema.
 type AgentClient struct {
 	config
@@ -7448,24 +7589,26 @@ func (c *XunjiServiceClient) mutate(ctx context.Context, m *XunjiServiceMutation
 // hooks and interceptors per client, for fast access.
 type (
 	hooks struct {
-		Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey, BatchMsg, Category,
-		ChatRecords, ChatSession, CompapiAsynctask, Contact, ContactField,
-		ContactFieldTemplate, CreditBalance, CreditUsage, Employee, EmployeeConfig,
-		Label, LabelLog, LabelRelationship, LabelTagging, Message, MessageRecords, Msg,
-		PayRecharge, Server, SopNode, SopStage, SopTask, Token, Tutorial, UsageDetail,
-		UsageStatisticDay, UsageStatisticHour, UsageStatisticMonth, UsageTotal,
-		Whatsapp, WhatsappChannel, WorkExperience, WpChatroom, WpChatroomMember, Wx,
-		WxCard, WxCardUser, WxCardVisit, Xunji, XunjiService []ent.Hook
+		AddWechatFriendLog, Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey,
+		BatchMsg, Category, ChatRecords, ChatSession, CompapiAsynctask, Contact,
+		ContactField, ContactFieldTemplate, CreditBalance, CreditUsage, Employee,
+		EmployeeConfig, Label, LabelLog, LabelRelationship, LabelTagging, Message,
+		MessageRecords, Msg, PayRecharge, Server, SopNode, SopStage, SopTask, Token,
+		Tutorial, UsageDetail, UsageStatisticDay, UsageStatisticHour,
+		UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel, WorkExperience,
+		WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser, WxCardVisit, Xunji,
+		XunjiService []ent.Hook
 	}
 	inters struct {
-		Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey, BatchMsg, Category,
-		ChatRecords, ChatSession, CompapiAsynctask, Contact, ContactField,
-		ContactFieldTemplate, CreditBalance, CreditUsage, Employee, EmployeeConfig,
-		Label, LabelLog, LabelRelationship, LabelTagging, Message, MessageRecords, Msg,
-		PayRecharge, Server, SopNode, SopStage, SopTask, Token, Tutorial, UsageDetail,
-		UsageStatisticDay, UsageStatisticHour, UsageStatisticMonth, UsageTotal,
-		Whatsapp, WhatsappChannel, WorkExperience, WpChatroom, WpChatroomMember, Wx,
-		WxCard, WxCardUser, WxCardVisit, Xunji, XunjiService []ent.Interceptor
+		AddWechatFriendLog, Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey,
+		BatchMsg, Category, ChatRecords, ChatSession, CompapiAsynctask, Contact,
+		ContactField, ContactFieldTemplate, CreditBalance, CreditUsage, Employee,
+		EmployeeConfig, Label, LabelLog, LabelRelationship, LabelTagging, Message,
+		MessageRecords, Msg, PayRecharge, Server, SopNode, SopStage, SopTask, Token,
+		Tutorial, UsageDetail, UsageStatisticDay, UsageStatisticHour,
+		UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel, WorkExperience,
+		WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser, WxCardVisit, Xunji,
+		XunjiService []ent.Interceptor
 	}
 )
 

+ 2 - 0
ent/ent.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"reflect"
 	"sync"
+	"wechat-api/ent/addwechatfriendlog"
 	"wechat-api/ent/agent"
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/aliyunavatar"
@@ -119,6 +120,7 @@ var (
 func checkColumn(table, column string) error {
 	initCheck.Do(func() {
 		columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
+			addwechatfriendlog.Table:   addwechatfriendlog.ValidColumn,
 			agent.Table:                agent.ValidColumn,
 			agentbase.Table:            agentbase.ValidColumn,
 			aliyunavatar.Table:         aliyunavatar.ValidColumn,

+ 12 - 0
ent/hook/hook.go

@@ -8,6 +8,18 @@ import (
 	"wechat-api/ent"
 )
 
+// The AddWechatFriendLogFunc type is an adapter to allow the use of ordinary
+// function as AddWechatFriendLog mutator.
+type AddWechatFriendLogFunc func(context.Context, *ent.AddWechatFriendLogMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f AddWechatFriendLogFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.AddWechatFriendLogMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AddWechatFriendLogMutation", m)
+}
+
 // The AgentFunc type is an adapter to allow the use of ordinary
 // function as Agent mutator.
 type AgentFunc func(context.Context, *ent.AgentMutation) (ent.Value, error)

+ 30 - 0
ent/intercept/intercept.go

@@ -6,6 +6,7 @@ import (
 	"context"
 	"fmt"
 	"wechat-api/ent"
+	"wechat-api/ent/addwechatfriendlog"
 	"wechat-api/ent/agent"
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/aliyunavatar"
@@ -114,6 +115,33 @@ func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error {
 	return f(ctx, query)
 }
 
+// The AddWechatFriendLogFunc type is an adapter to allow the use of ordinary function as a Querier.
+type AddWechatFriendLogFunc func(context.Context, *ent.AddWechatFriendLogQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f AddWechatFriendLogFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.AddWechatFriendLogQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.AddWechatFriendLogQuery", q)
+}
+
+// The TraverseAddWechatFriendLog type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseAddWechatFriendLog func(context.Context, *ent.AddWechatFriendLogQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseAddWechatFriendLog) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseAddWechatFriendLog) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.AddWechatFriendLogQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.AddWechatFriendLogQuery", q)
+}
+
 // The AgentFunc type is an adapter to allow the use of ordinary function as a Querier.
 type AgentFunc func(context.Context, *ent.AgentQuery) (ent.Value, error)
 
@@ -1386,6 +1414,8 @@ func (f TraverseXunjiService) Traverse(ctx context.Context, q ent.Query) error {
 // NewQuery returns the generic Query interface for the given typed query.
 func NewQuery(q ent.Query) (Query, error) {
 	switch q := q.(type) {
+	case *ent.AddWechatFriendLogQuery:
+		return &query[*ent.AddWechatFriendLogQuery, predicate.AddWechatFriendLog, addwechatfriendlog.OrderOption]{typ: ent.TypeAddWechatFriendLog, tq: q}, nil
 	case *ent.AgentQuery:
 		return &query[*ent.AgentQuery, predicate.Agent, agent.OrderOption]{typ: ent.TypeAgent, tq: q}, nil
 	case *ent.AgentBaseQuery:

+ 36 - 1
ent/migrate/schema.go

@@ -9,6 +9,36 @@ import (
 )
 
 var (
+	// AddWechatFriendLogColumns holds the columns for the "add_wechat_friend_log" table.
+	AddWechatFriendLogColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeInt64, Increment: true},
+		{Name: "owner_wx_id", Type: field.TypeString, Size: 64, Default: ""},
+		{Name: "owner_wx_type", Type: field.TypeInt, Default: 1},
+		{Name: "find_content", Type: field.TypeString, Size: 64, Default: ""},
+		{Name: "message", Type: field.TypeString, Size: 255, Default: ""},
+		{Name: "find_request", Type: field.TypeJSON, Nullable: true},
+		{Name: "find_result", Type: field.TypeJSON, Nullable: true},
+		{Name: "is_can_add", Type: field.TypeInt, Default: 0},
+		{Name: "task_count", Type: field.TypeInt, Default: 0},
+		{Name: "task_id", Type: field.TypeInt64, Default: 0},
+		{Name: "add_request", Type: field.TypeJSON, Nullable: true},
+		{Name: "add_result", Type: field.TypeJSON, Nullable: true},
+		{Name: "created_at", Type: field.TypeInt64},
+		{Name: "updated_at", Type: field.TypeInt64},
+	}
+	// AddWechatFriendLogTable holds the schema information for the "add_wechat_friend_log" table.
+	AddWechatFriendLogTable = &schema.Table{
+		Name:       "add_wechat_friend_log",
+		Columns:    AddWechatFriendLogColumns,
+		PrimaryKey: []*schema.Column{AddWechatFriendLogColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "addwechatfriendlog_owner_wx_id_is_can_add",
+				Unique:  false,
+				Columns: []*schema.Column{AddWechatFriendLogColumns[1], AddWechatFriendLogColumns[7]},
+			},
+		},
+	}
 	// AgentColumns holds the columns for the "agent" table.
 	AgentColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -1166,6 +1196,7 @@ var (
 		{Name: "type", Type: field.TypeInt, Nullable: true, Comment: "1 微信 2 名片", Default: 1},
 		{Name: "bot_id", Type: field.TypeString, Comment: "微信或名片id", Default: ""},
 		{Name: "total_tokens", Type: field.TypeUint64, Nullable: true, Comment: "使用token总数", Default: 0},
+		{Name: "credits", Type: field.TypeFloat64, Nullable: true, Comment: "使用积分总数", Default: 0},
 		{Name: "start_index", Type: field.TypeUint64, Nullable: true, Comment: "重制后的起始usage_detail 索引", Default: 0},
 		{Name: "end_index", Type: field.TypeUint64, Nullable: true, Comment: "usage_detail 索引", Default: 0},
 		{Name: "organization_id", Type: field.TypeUint64, Nullable: true, Comment: "机构 ID", Default: 1},
@@ -1184,7 +1215,7 @@ var (
 			{
 				Name:    "usagetotal_organization_id",
 				Unique:  false,
-				Columns: []*schema.Column{UsageTotalColumns[9]},
+				Columns: []*schema.Column{UsageTotalColumns[10]},
 			},
 		},
 	}
@@ -1586,6 +1617,7 @@ var (
 	}
 	// Tables holds all the tables in the schema.
 	Tables = []*schema.Table{
+		AddWechatFriendLogTable,
 		AgentTable,
 		AgentBaseTable,
 		AliyunAvatarTable,
@@ -1637,6 +1669,9 @@ var (
 )
 
 func init() {
+	AddWechatFriendLogTable.Annotation = &entsql.Annotation{
+		Table: "add_wechat_friend_log",
+	}
 	AgentTable.Annotation = &entsql.Annotation{
 		Table: "agent",
 	}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1262 - 0
ent/mutation.go


+ 82 - 0
ent/pagination.go

@@ -5,6 +5,7 @@ package ent
 import (
 	"context"
 	"fmt"
+	"wechat-api/ent/addwechatfriendlog"
 	"wechat-api/ent/agent"
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/aliyunavatar"
@@ -100,6 +101,87 @@ func (o OrderDirection) reverse() OrderDirection {
 
 const errInvalidPagination = "INVALID_PAGINATION"
 
+type AddWechatFriendLogPager struct {
+	Order  addwechatfriendlog.OrderOption
+	Filter func(*AddWechatFriendLogQuery) (*AddWechatFriendLogQuery, error)
+}
+
+// AddWechatFriendLogPaginateOption enables pagination customization.
+type AddWechatFriendLogPaginateOption func(*AddWechatFriendLogPager)
+
+// DefaultAddWechatFriendLogOrder is the default ordering of AddWechatFriendLog.
+var DefaultAddWechatFriendLogOrder = Desc(addwechatfriendlog.FieldID)
+
+func newAddWechatFriendLogPager(opts []AddWechatFriendLogPaginateOption) (*AddWechatFriendLogPager, error) {
+	pager := &AddWechatFriendLogPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultAddWechatFriendLogOrder
+	}
+	return pager, nil
+}
+
+func (p *AddWechatFriendLogPager) ApplyFilter(query *AddWechatFriendLogQuery) (*AddWechatFriendLogQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// AddWechatFriendLogPageList is AddWechatFriendLog PageList result.
+type AddWechatFriendLogPageList struct {
+	List        []*AddWechatFriendLog `json:"list"`
+	PageDetails *PageDetails          `json:"pageDetails"`
+}
+
+func (awfl *AddWechatFriendLogQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...AddWechatFriendLogPaginateOption,
+) (*AddWechatFriendLogPageList, error) {
+
+	pager, err := newAddWechatFriendLogPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if awfl, err = pager.ApplyFilter(awfl); err != nil {
+		return nil, err
+	}
+
+	ret := &AddWechatFriendLogPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := awfl.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		awfl = awfl.Order(pager.Order)
+	} else {
+		awfl = awfl.Order(DefaultAddWechatFriendLogOrder)
+	}
+
+	awfl = awfl.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := awfl.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type AgentPager struct {
 	Order  agent.OrderOption
 	Filter func(*AgentQuery) (*AgentQuery, error)

+ 3 - 0
ent/predicate/predicate.go

@@ -6,6 +6,9 @@ import (
 	"entgo.io/ent/dialect/sql"
 )
 
+// AddWechatFriendLog is the predicate function for addwechatfriendlog builders.
+type AddWechatFriendLog func(*sql.Selector)
+
 // Agent is the predicate function for agent builders.
 type Agent func(*sql.Selector)
 

+ 96 - 3
ent/runtime/runtime.go

@@ -4,6 +4,7 @@ package runtime
 
 import (
 	"time"
+	"wechat-api/ent/addwechatfriendlog"
 	"wechat-api/ent/agent"
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/aliyunavatar"
@@ -58,6 +59,94 @@ import (
 // (default values, validators, hooks and policies) and stitches it
 // to their package variables.
 func init() {
+	addwechatfriendlogFields := schema.AddWechatFriendLog{}.Fields()
+	_ = addwechatfriendlogFields
+	// addwechatfriendlogDescOwnerWxID is the schema descriptor for owner_wx_id field.
+	addwechatfriendlogDescOwnerWxID := addwechatfriendlogFields[1].Descriptor()
+	// addwechatfriendlog.DefaultOwnerWxID holds the default value on creation for the owner_wx_id field.
+	addwechatfriendlog.DefaultOwnerWxID = addwechatfriendlogDescOwnerWxID.Default.(string)
+	// addwechatfriendlog.OwnerWxIDValidator is a validator for the "owner_wx_id" field. It is called by the builders before save.
+	addwechatfriendlog.OwnerWxIDValidator = func() func(string) error {
+		validators := addwechatfriendlogDescOwnerWxID.Validators
+		fns := [...]func(string) error{
+			validators[0].(func(string) error),
+			validators[1].(func(string) error),
+		}
+		return func(owner_wx_id string) error {
+			for _, fn := range fns {
+				if err := fn(owner_wx_id); err != nil {
+					return err
+				}
+			}
+			return nil
+		}
+	}()
+	// addwechatfriendlogDescOwnerWxType is the schema descriptor for owner_wx_type field.
+	addwechatfriendlogDescOwnerWxType := addwechatfriendlogFields[2].Descriptor()
+	// addwechatfriendlog.DefaultOwnerWxType holds the default value on creation for the owner_wx_type field.
+	addwechatfriendlog.DefaultOwnerWxType = addwechatfriendlogDescOwnerWxType.Default.(int)
+	// addwechatfriendlogDescFindContent is the schema descriptor for find_content field.
+	addwechatfriendlogDescFindContent := addwechatfriendlogFields[3].Descriptor()
+	// addwechatfriendlog.DefaultFindContent holds the default value on creation for the find_content field.
+	addwechatfriendlog.DefaultFindContent = addwechatfriendlogDescFindContent.Default.(string)
+	// addwechatfriendlog.FindContentValidator is a validator for the "find_content" field. It is called by the builders before save.
+	addwechatfriendlog.FindContentValidator = func() func(string) error {
+		validators := addwechatfriendlogDescFindContent.Validators
+		fns := [...]func(string) error{
+			validators[0].(func(string) error),
+			validators[1].(func(string) error),
+		}
+		return func(find_content string) error {
+			for _, fn := range fns {
+				if err := fn(find_content); err != nil {
+					return err
+				}
+			}
+			return nil
+		}
+	}()
+	// addwechatfriendlogDescMessage is the schema descriptor for message field.
+	addwechatfriendlogDescMessage := addwechatfriendlogFields[4].Descriptor()
+	// addwechatfriendlog.DefaultMessage holds the default value on creation for the message field.
+	addwechatfriendlog.DefaultMessage = addwechatfriendlogDescMessage.Default.(string)
+	// addwechatfriendlog.MessageValidator is a validator for the "message" field. It is called by the builders before save.
+	addwechatfriendlog.MessageValidator = func() func(string) error {
+		validators := addwechatfriendlogDescMessage.Validators
+		fns := [...]func(string) error{
+			validators[0].(func(string) error),
+			validators[1].(func(string) error),
+		}
+		return func(message string) error {
+			for _, fn := range fns {
+				if err := fn(message); err != nil {
+					return err
+				}
+			}
+			return nil
+		}
+	}()
+	// addwechatfriendlogDescIsCanAdd is the schema descriptor for is_can_add field.
+	addwechatfriendlogDescIsCanAdd := addwechatfriendlogFields[7].Descriptor()
+	// addwechatfriendlog.DefaultIsCanAdd holds the default value on creation for the is_can_add field.
+	addwechatfriendlog.DefaultIsCanAdd = addwechatfriendlogDescIsCanAdd.Default.(int)
+	// addwechatfriendlogDescTaskCount is the schema descriptor for task_count field.
+	addwechatfriendlogDescTaskCount := addwechatfriendlogFields[8].Descriptor()
+	// addwechatfriendlog.DefaultTaskCount holds the default value on creation for the task_count field.
+	addwechatfriendlog.DefaultTaskCount = addwechatfriendlogDescTaskCount.Default.(int)
+	// addwechatfriendlogDescTaskID is the schema descriptor for task_id field.
+	addwechatfriendlogDescTaskID := addwechatfriendlogFields[9].Descriptor()
+	// addwechatfriendlog.DefaultTaskID holds the default value on creation for the task_id field.
+	addwechatfriendlog.DefaultTaskID = addwechatfriendlogDescTaskID.Default.(int64)
+	// addwechatfriendlogDescCreatedAt is the schema descriptor for created_at field.
+	addwechatfriendlogDescCreatedAt := addwechatfriendlogFields[12].Descriptor()
+	// addwechatfriendlog.DefaultCreatedAt holds the default value on creation for the created_at field.
+	addwechatfriendlog.DefaultCreatedAt = addwechatfriendlogDescCreatedAt.Default.(func() int64)
+	// addwechatfriendlogDescUpdatedAt is the schema descriptor for updated_at field.
+	addwechatfriendlogDescUpdatedAt := addwechatfriendlogFields[13].Descriptor()
+	// addwechatfriendlog.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	addwechatfriendlog.DefaultUpdatedAt = addwechatfriendlogDescUpdatedAt.Default.(func() int64)
+	// addwechatfriendlog.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	addwechatfriendlog.UpdateDefaultUpdatedAt = addwechatfriendlogDescUpdatedAt.UpdateDefault.(func() int64)
 	agentMixin := schema.Agent{}.Mixin()
 	agentMixinHooks1 := agentMixin[1].Hooks()
 	agent.Hooks[0] = agentMixinHooks1[0]
@@ -1560,16 +1649,20 @@ func init() {
 	usagetotalDescTotalTokens := usagetotalFields[2].Descriptor()
 	// usagetotal.DefaultTotalTokens holds the default value on creation for the total_tokens field.
 	usagetotal.DefaultTotalTokens = usagetotalDescTotalTokens.Default.(uint64)
+	// usagetotalDescCredits is the schema descriptor for credits field.
+	usagetotalDescCredits := usagetotalFields[3].Descriptor()
+	// usagetotal.DefaultCredits holds the default value on creation for the credits field.
+	usagetotal.DefaultCredits = usagetotalDescCredits.Default.(float64)
 	// usagetotalDescStartIndex is the schema descriptor for start_index field.
-	usagetotalDescStartIndex := usagetotalFields[3].Descriptor()
+	usagetotalDescStartIndex := usagetotalFields[4].Descriptor()
 	// usagetotal.DefaultStartIndex holds the default value on creation for the start_index field.
 	usagetotal.DefaultStartIndex = usagetotalDescStartIndex.Default.(uint64)
 	// usagetotalDescEndIndex is the schema descriptor for end_index field.
-	usagetotalDescEndIndex := usagetotalFields[4].Descriptor()
+	usagetotalDescEndIndex := usagetotalFields[5].Descriptor()
 	// usagetotal.DefaultEndIndex holds the default value on creation for the end_index field.
 	usagetotal.DefaultEndIndex = usagetotalDescEndIndex.Default.(uint64)
 	// usagetotalDescOrganizationID is the schema descriptor for organization_id field.
-	usagetotalDescOrganizationID := usagetotalFields[5].Descriptor()
+	usagetotalDescOrganizationID := usagetotalFields[6].Descriptor()
 	// usagetotal.DefaultOrganizationID holds the default value on creation for the organization_id field.
 	usagetotal.DefaultOrganizationID = usagetotalDescOrganizationID.Default.(uint64)
 	whatsappMixin := schema.Whatsapp{}.Mixin()

+ 92 - 0
ent/schema/add_wechat_friend_log.go

@@ -0,0 +1,92 @@
+package schema
+
+import (
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"time"
+)
+
+// AddWechatFriendLog holds the schema definition for the AddWechatFriendLog entity.
+type AddWechatFriendLog struct {
+	ent.Schema
+}
+
+// Fields of the AddWechatFriendLog.
+func (AddWechatFriendLog) Fields() []ent.Field {
+	return []ent.Field{
+		field.Int64("id").
+			Comment("主键id").
+			Unique().
+			Immutable(),
+
+		field.String("owner_wx_id").
+			Default("").
+			NotEmpty().
+			MaxLen(64).
+			Comment("属主的wxid"),
+
+		field.Int("owner_wx_type").
+			Default(1).
+			Comment("属主的微信类型(1个微,2企微)"),
+
+		field.String("find_content").
+			Default("").
+			NotEmpty().
+			MaxLen(64).
+			Comment("手机号"),
+		field.String("message").
+			Default("").
+			NotEmpty().
+			MaxLen(255).
+			Comment("添加好友时候填写的申请消息"),
+		field.JSON("find_request", map[string]interface{}{}).
+			Optional().
+			Comment("发起查询数据的时候json"),
+
+		field.JSON("find_result", map[string]interface{}{}).
+			Optional().
+			Comment("查询返回结果"),
+
+		field.Int("is_can_add").
+			Default(0).
+			Comment("任务执行次数"),
+		field.Int("task_count").
+			Default(0).
+			Comment("是否可以添加好友(与属主账号非好友且其数据查询正常时 0 不可以,1 可以 2成功添加申请)"),
+		field.Int64("task_id").Default(0).Comment("添加时候的请求体"),
+		field.JSON("add_request", map[string]interface{}{}).
+			Optional().Comment("添加时候的请求体"),
+		field.JSON("add_result", map[string]interface{}{}).
+			Optional().Comment("添加请求的结果"),
+
+		field.Int64("created_at").
+			DefaultFunc(func() int64 {
+				return time.Now().Unix()
+			}).Comment("创建时间戳"),
+
+		field.Int64("updated_at").
+			DefaultFunc(func() int64 {
+				return time.Now().Unix()
+			}).
+			UpdateDefault(func() int64 {
+				return time.Now().Unix()
+			}).Comment("修改时间戳"),
+	}
+}
+
+// Indexes of the AddWechatFriendLog.
+func (AddWechatFriendLog) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("owner_wx_id", "is_can_add"),
+	}
+}
+
+func (AddWechatFriendLog) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		schema.Comment("微信添加好友记录"),
+		entsql.Annotation{Table: "add_wechat_friend_log"},
+	}
+}

+ 3 - 0
ent/schema/usage_total.go

@@ -24,6 +24,9 @@ func (UsageTotal) Fields() []ent.Field {
 		field.Uint64("total_tokens").Optional().Default(0).
 			Annotations(entsql.WithComments(true)).
 			Comment("使用token总数"),
+		field.Float("credits").Optional().Default(0).
+			Annotations(entsql.WithComments(true)).
+			Comment("使用积分总数"),
 		field.Uint64("start_index").Optional().Default(0).
 			Annotations(entsql.WithComments(true)).
 			Comment("重制后的起始usage_detail 索引"),

+ 336 - 0
ent/set_not_nil.go

@@ -8,6 +8,318 @@ import (
 )
 
 // set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilOwnerWxID(value *string) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetOwnerWxID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilOwnerWxID(value *string) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetOwnerWxID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilOwnerWxID(value *string) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetOwnerWxID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilOwnerWxType(value *int) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetOwnerWxType(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilOwnerWxType(value *int) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetOwnerWxType(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilOwnerWxType(value *int) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetOwnerWxType(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilFindContent(value *string) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetFindContent(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilFindContent(value *string) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetFindContent(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilFindContent(value *string) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetFindContent(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilMessage(value *string) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetMessage(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilMessage(value *string) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetMessage(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilMessage(value *string) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetMessage(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilFindRequest(value *map[string]interface{}) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetFindRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilFindRequest(value *map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetFindRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilFindRequest(value *map[string]interface{}) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetFindRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilFindResult(value *map[string]interface{}) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetFindResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilFindResult(value *map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetFindResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilFindResult(value *map[string]interface{}) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetFindResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilIsCanAdd(value *int) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetIsCanAdd(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilIsCanAdd(value *int) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetIsCanAdd(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilIsCanAdd(value *int) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetIsCanAdd(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilTaskCount(value *int) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetTaskCount(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilTaskCount(value *int) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetTaskCount(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilTaskCount(value *int) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetTaskCount(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilTaskID(value *int64) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetTaskID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilTaskID(value *int64) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetTaskID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilTaskID(value *int64) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetTaskID(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilAddRequest(value *map[string]interface{}) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetAddRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilAddRequest(value *map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetAddRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilAddRequest(value *map[string]interface{}) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetAddRequest(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilAddResult(value *map[string]interface{}) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetAddResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilAddResult(value *map[string]interface{}) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetAddResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilAddResult(value *map[string]interface{}) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetAddResult(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilCreatedAt(value *int64) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetCreatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilCreatedAt(value *int64) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetCreatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilCreatedAt(value *int64) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetCreatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdate) SetNotNilUpdatedAt(value *int64) *AddWechatFriendLogUpdate {
+	if value != nil {
+		return awfl.SetUpdatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogUpdateOne) SetNotNilUpdatedAt(value *int64) *AddWechatFriendLogUpdateOne {
+	if value != nil {
+		return awfl.SetUpdatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
+func (awfl *AddWechatFriendLogCreate) SetNotNilUpdatedAt(value *int64) *AddWechatFriendLogCreate {
+	if value != nil {
+		return awfl.SetUpdatedAt(*value)
+	}
+	return awfl
+}
+
+// set field if value's pointer is not nil.
 func (a *AgentUpdate) SetNotNilUpdatedAt(value *time.Time) *AgentUpdate {
 	if value != nil {
 		return a.SetUpdatedAt(*value)
@@ -9440,6 +9752,30 @@ func (ut *UsageTotalCreate) SetNotNilTotalTokens(value *uint64) *UsageTotalCreat
 }
 
 // set field if value's pointer is not nil.
+func (ut *UsageTotalUpdate) SetNotNilCredits(value *float64) *UsageTotalUpdate {
+	if value != nil {
+		return ut.SetCredits(*value)
+	}
+	return ut
+}
+
+// set field if value's pointer is not nil.
+func (ut *UsageTotalUpdateOne) SetNotNilCredits(value *float64) *UsageTotalUpdateOne {
+	if value != nil {
+		return ut.SetCredits(*value)
+	}
+	return ut
+}
+
+// set field if value's pointer is not nil.
+func (ut *UsageTotalCreate) SetNotNilCredits(value *float64) *UsageTotalCreate {
+	if value != nil {
+		return ut.SetCredits(*value)
+	}
+	return ut
+}
+
+// set field if value's pointer is not nil.
 func (ut *UsageTotalUpdate) SetNotNilStartIndex(value *uint64) *UsageTotalUpdate {
 	if value != nil {
 		return ut.SetStartIndex(*value)

+ 4 - 1
ent/tx.go

@@ -14,6 +14,8 @@ import (
 // Tx is a transactional client that is created by calling Client.Tx().
 type Tx struct {
 	config
+	// AddWechatFriendLog is the client for interacting with the AddWechatFriendLog builders.
+	AddWechatFriendLog *AddWechatFriendLogClient
 	// Agent is the client for interacting with the Agent builders.
 	Agent *AgentClient
 	// AgentBase is the client for interacting with the AgentBase builders.
@@ -239,6 +241,7 @@ func (tx *Tx) Client() *Client {
 }
 
 func (tx *Tx) init() {
+	tx.AddWechatFriendLog = NewAddWechatFriendLogClient(tx.config)
 	tx.Agent = NewAgentClient(tx.config)
 	tx.AgentBase = NewAgentBaseClient(tx.config)
 	tx.AliyunAvatar = NewAliyunAvatarClient(tx.config)
@@ -295,7 +298,7 @@ func (tx *Tx) init() {
 // of them in order to commit or rollback the transaction.
 //
 // If a closed transaction is embedded in one of the generated entities, and the entity
-// applies a query, for example: Agent.QueryXXX(), the query will be executed
+// applies a query, for example: AddWechatFriendLog.QueryXXX(), the query will be executed
 // through the driver which created this transaction.
 //
 // Note that txDriver is not goroutine safe.

+ 13 - 0
ent/usagetotal.go

@@ -29,6 +29,8 @@ type UsageTotal struct {
 	BotID string `json:"bot_id,omitempty"`
 	// 使用token总数
 	TotalTokens uint64 `json:"total_tokens,omitempty"`
+	// 使用积分总数
+	Credits float64 `json:"credits,omitempty"`
 	// 重制后的起始usage_detail 索引
 	StartIndex uint64 `json:"start_index,omitempty"`
 	// usage_detail 索引
@@ -43,6 +45,8 @@ func (*UsageTotal) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
 	for i := range columns {
 		switch columns[i] {
+		case usagetotal.FieldCredits:
+			values[i] = new(sql.NullFloat64)
 		case usagetotal.FieldID, usagetotal.FieldStatus, usagetotal.FieldType, usagetotal.FieldTotalTokens, usagetotal.FieldStartIndex, usagetotal.FieldEndIndex, usagetotal.FieldOrganizationID:
 			values[i] = new(sql.NullInt64)
 		case usagetotal.FieldBotID:
@@ -106,6 +110,12 @@ func (ut *UsageTotal) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				ut.TotalTokens = uint64(value.Int64)
 			}
+		case usagetotal.FieldCredits:
+			if value, ok := values[i].(*sql.NullFloat64); !ok {
+				return fmt.Errorf("unexpected type %T for field credits", values[i])
+			} else if value.Valid {
+				ut.Credits = value.Float64
+			}
 		case usagetotal.FieldStartIndex:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field start_index", values[i])
@@ -178,6 +188,9 @@ func (ut *UsageTotal) String() string {
 	builder.WriteString("total_tokens=")
 	builder.WriteString(fmt.Sprintf("%v", ut.TotalTokens))
 	builder.WriteString(", ")
+	builder.WriteString("credits=")
+	builder.WriteString(fmt.Sprintf("%v", ut.Credits))
+	builder.WriteString(", ")
 	builder.WriteString("start_index=")
 	builder.WriteString(fmt.Sprintf("%v", ut.StartIndex))
 	builder.WriteString(", ")

+ 10 - 0
ent/usagetotal/usagetotal.go

@@ -25,6 +25,8 @@ const (
 	FieldBotID = "bot_id"
 	// FieldTotalTokens holds the string denoting the total_tokens field in the database.
 	FieldTotalTokens = "total_tokens"
+	// FieldCredits holds the string denoting the credits field in the database.
+	FieldCredits = "credits"
 	// FieldStartIndex holds the string denoting the start_index field in the database.
 	FieldStartIndex = "start_index"
 	// FieldEndIndex holds the string denoting the end_index field in the database.
@@ -44,6 +46,7 @@ var Columns = []string{
 	FieldType,
 	FieldBotID,
 	FieldTotalTokens,
+	FieldCredits,
 	FieldStartIndex,
 	FieldEndIndex,
 	FieldOrganizationID,
@@ -74,6 +77,8 @@ var (
 	DefaultBotID string
 	// DefaultTotalTokens holds the default value on creation for the "total_tokens" field.
 	DefaultTotalTokens uint64
+	// DefaultCredits holds the default value on creation for the "credits" field.
+	DefaultCredits float64
 	// DefaultStartIndex holds the default value on creation for the "start_index" field.
 	DefaultStartIndex uint64
 	// DefaultEndIndex holds the default value on creation for the "end_index" field.
@@ -120,6 +125,11 @@ func ByTotalTokens(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldTotalTokens, opts...).ToFunc()
 }
 
+// ByCredits orders the results by the credits field.
+func ByCredits(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCredits, opts...).ToFunc()
+}
+
 // ByStartIndex orders the results by the start_index field.
 func ByStartIndex(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldStartIndex, opts...).ToFunc()

+ 55 - 0
ent/usagetotal/where.go

@@ -84,6 +84,11 @@ func TotalTokens(v uint64) predicate.UsageTotal {
 	return predicate.UsageTotal(sql.FieldEQ(FieldTotalTokens, v))
 }
 
+// Credits applies equality check predicate on the "credits" field. It's identical to CreditsEQ.
+func Credits(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldEQ(FieldCredits, v))
+}
+
 // StartIndex applies equality check predicate on the "start_index" field. It's identical to StartIndexEQ.
 func StartIndex(v uint64) predicate.UsageTotal {
 	return predicate.UsageTotal(sql.FieldEQ(FieldStartIndex, v))
@@ -394,6 +399,56 @@ func TotalTokensNotNil() predicate.UsageTotal {
 	return predicate.UsageTotal(sql.FieldNotNull(FieldTotalTokens))
 }
 
+// CreditsEQ applies the EQ predicate on the "credits" field.
+func CreditsEQ(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldEQ(FieldCredits, v))
+}
+
+// CreditsNEQ applies the NEQ predicate on the "credits" field.
+func CreditsNEQ(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldNEQ(FieldCredits, v))
+}
+
+// CreditsIn applies the In predicate on the "credits" field.
+func CreditsIn(vs ...float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldIn(FieldCredits, vs...))
+}
+
+// CreditsNotIn applies the NotIn predicate on the "credits" field.
+func CreditsNotIn(vs ...float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldNotIn(FieldCredits, vs...))
+}
+
+// CreditsGT applies the GT predicate on the "credits" field.
+func CreditsGT(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldGT(FieldCredits, v))
+}
+
+// CreditsGTE applies the GTE predicate on the "credits" field.
+func CreditsGTE(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldGTE(FieldCredits, v))
+}
+
+// CreditsLT applies the LT predicate on the "credits" field.
+func CreditsLT(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldLT(FieldCredits, v))
+}
+
+// CreditsLTE applies the LTE predicate on the "credits" field.
+func CreditsLTE(v float64) predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldLTE(FieldCredits, v))
+}
+
+// CreditsIsNil applies the IsNil predicate on the "credits" field.
+func CreditsIsNil() predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldIsNull(FieldCredits))
+}
+
+// CreditsNotNil applies the NotNil predicate on the "credits" field.
+func CreditsNotNil() predicate.UsageTotal {
+	return predicate.UsageTotal(sql.FieldNotNull(FieldCredits))
+}
+
 // StartIndexEQ applies the EQ predicate on the "start_index" field.
 func StartIndexEQ(v uint64) predicate.UsageTotal {
 	return predicate.UsageTotal(sql.FieldEQ(FieldStartIndex, v))

+ 102 - 0
ent/usagetotal_create.go

@@ -106,6 +106,20 @@ func (utc *UsageTotalCreate) SetNillableTotalTokens(u *uint64) *UsageTotalCreate
 	return utc
 }
 
+// SetCredits sets the "credits" field.
+func (utc *UsageTotalCreate) SetCredits(f float64) *UsageTotalCreate {
+	utc.mutation.SetCredits(f)
+	return utc
+}
+
+// SetNillableCredits sets the "credits" field if the given value is not nil.
+func (utc *UsageTotalCreate) SetNillableCredits(f *float64) *UsageTotalCreate {
+	if f != nil {
+		utc.SetCredits(*f)
+	}
+	return utc
+}
+
 // SetStartIndex sets the "start_index" field.
 func (utc *UsageTotalCreate) SetStartIndex(u uint64) *UsageTotalCreate {
 	utc.mutation.SetStartIndex(u)
@@ -213,6 +227,10 @@ func (utc *UsageTotalCreate) defaults() {
 		v := usagetotal.DefaultTotalTokens
 		utc.mutation.SetTotalTokens(v)
 	}
+	if _, ok := utc.mutation.Credits(); !ok {
+		v := usagetotal.DefaultCredits
+		utc.mutation.SetCredits(v)
+	}
 	if _, ok := utc.mutation.StartIndex(); !ok {
 		v := usagetotal.DefaultStartIndex
 		utc.mutation.SetStartIndex(v)
@@ -295,6 +313,10 @@ func (utc *UsageTotalCreate) createSpec() (*UsageTotal, *sqlgraph.CreateSpec) {
 		_spec.SetField(usagetotal.FieldTotalTokens, field.TypeUint64, value)
 		_node.TotalTokens = value
 	}
+	if value, ok := utc.mutation.Credits(); ok {
+		_spec.SetField(usagetotal.FieldCredits, field.TypeFloat64, value)
+		_node.Credits = value
+	}
 	if value, ok := utc.mutation.StartIndex(); ok {
 		_spec.SetField(usagetotal.FieldStartIndex, field.TypeUint64, value)
 		_node.StartIndex = value
@@ -455,6 +477,30 @@ func (u *UsageTotalUpsert) ClearTotalTokens() *UsageTotalUpsert {
 	return u
 }
 
+// SetCredits sets the "credits" field.
+func (u *UsageTotalUpsert) SetCredits(v float64) *UsageTotalUpsert {
+	u.Set(usagetotal.FieldCredits, v)
+	return u
+}
+
+// UpdateCredits sets the "credits" field to the value that was provided on create.
+func (u *UsageTotalUpsert) UpdateCredits() *UsageTotalUpsert {
+	u.SetExcluded(usagetotal.FieldCredits)
+	return u
+}
+
+// AddCredits adds v to the "credits" field.
+func (u *UsageTotalUpsert) AddCredits(v float64) *UsageTotalUpsert {
+	u.Add(usagetotal.FieldCredits, v)
+	return u
+}
+
+// ClearCredits clears the value of the "credits" field.
+func (u *UsageTotalUpsert) ClearCredits() *UsageTotalUpsert {
+	u.SetNull(usagetotal.FieldCredits)
+	return u
+}
+
 // SetStartIndex sets the "start_index" field.
 func (u *UsageTotalUpsert) SetStartIndex(v uint64) *UsageTotalUpsert {
 	u.Set(usagetotal.FieldStartIndex, v)
@@ -690,6 +736,34 @@ func (u *UsageTotalUpsertOne) ClearTotalTokens() *UsageTotalUpsertOne {
 	})
 }
 
+// SetCredits sets the "credits" field.
+func (u *UsageTotalUpsertOne) SetCredits(v float64) *UsageTotalUpsertOne {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.SetCredits(v)
+	})
+}
+
+// AddCredits adds v to the "credits" field.
+func (u *UsageTotalUpsertOne) AddCredits(v float64) *UsageTotalUpsertOne {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.AddCredits(v)
+	})
+}
+
+// UpdateCredits sets the "credits" field to the value that was provided on create.
+func (u *UsageTotalUpsertOne) UpdateCredits() *UsageTotalUpsertOne {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.UpdateCredits()
+	})
+}
+
+// ClearCredits clears the value of the "credits" field.
+func (u *UsageTotalUpsertOne) ClearCredits() *UsageTotalUpsertOne {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.ClearCredits()
+	})
+}
+
 // SetStartIndex sets the "start_index" field.
 func (u *UsageTotalUpsertOne) SetStartIndex(v uint64) *UsageTotalUpsertOne {
 	return u.Update(func(s *UsageTotalUpsert) {
@@ -1103,6 +1177,34 @@ func (u *UsageTotalUpsertBulk) ClearTotalTokens() *UsageTotalUpsertBulk {
 	})
 }
 
+// SetCredits sets the "credits" field.
+func (u *UsageTotalUpsertBulk) SetCredits(v float64) *UsageTotalUpsertBulk {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.SetCredits(v)
+	})
+}
+
+// AddCredits adds v to the "credits" field.
+func (u *UsageTotalUpsertBulk) AddCredits(v float64) *UsageTotalUpsertBulk {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.AddCredits(v)
+	})
+}
+
+// UpdateCredits sets the "credits" field to the value that was provided on create.
+func (u *UsageTotalUpsertBulk) UpdateCredits() *UsageTotalUpsertBulk {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.UpdateCredits()
+	})
+}
+
+// ClearCredits clears the value of the "credits" field.
+func (u *UsageTotalUpsertBulk) ClearCredits() *UsageTotalUpsertBulk {
+	return u.Update(func(s *UsageTotalUpsert) {
+		s.ClearCredits()
+	})
+}
+
 // SetStartIndex sets the "start_index" field.
 func (u *UsageTotalUpsertBulk) SetStartIndex(v uint64) *UsageTotalUpsertBulk {
 	return u.Update(func(s *UsageTotalUpsert) {

+ 72 - 0
ent/usagetotal_update.go

@@ -129,6 +129,33 @@ func (utu *UsageTotalUpdate) ClearTotalTokens() *UsageTotalUpdate {
 	return utu
 }
 
+// SetCredits sets the "credits" field.
+func (utu *UsageTotalUpdate) SetCredits(f float64) *UsageTotalUpdate {
+	utu.mutation.ResetCredits()
+	utu.mutation.SetCredits(f)
+	return utu
+}
+
+// SetNillableCredits sets the "credits" field if the given value is not nil.
+func (utu *UsageTotalUpdate) SetNillableCredits(f *float64) *UsageTotalUpdate {
+	if f != nil {
+		utu.SetCredits(*f)
+	}
+	return utu
+}
+
+// AddCredits adds f to the "credits" field.
+func (utu *UsageTotalUpdate) AddCredits(f float64) *UsageTotalUpdate {
+	utu.mutation.AddCredits(f)
+	return utu
+}
+
+// ClearCredits clears the value of the "credits" field.
+func (utu *UsageTotalUpdate) ClearCredits() *UsageTotalUpdate {
+	utu.mutation.ClearCredits()
+	return utu
+}
+
 // SetStartIndex sets the "start_index" field.
 func (utu *UsageTotalUpdate) SetStartIndex(u uint64) *UsageTotalUpdate {
 	utu.mutation.ResetStartIndex()
@@ -293,6 +320,15 @@ func (utu *UsageTotalUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if utu.mutation.TotalTokensCleared() {
 		_spec.ClearField(usagetotal.FieldTotalTokens, field.TypeUint64)
 	}
+	if value, ok := utu.mutation.Credits(); ok {
+		_spec.SetField(usagetotal.FieldCredits, field.TypeFloat64, value)
+	}
+	if value, ok := utu.mutation.AddedCredits(); ok {
+		_spec.AddField(usagetotal.FieldCredits, field.TypeFloat64, value)
+	}
+	if utu.mutation.CreditsCleared() {
+		_spec.ClearField(usagetotal.FieldCredits, field.TypeFloat64)
+	}
 	if value, ok := utu.mutation.StartIndex(); ok {
 		_spec.SetField(usagetotal.FieldStartIndex, field.TypeUint64, value)
 	}
@@ -441,6 +477,33 @@ func (utuo *UsageTotalUpdateOne) ClearTotalTokens() *UsageTotalUpdateOne {
 	return utuo
 }
 
+// SetCredits sets the "credits" field.
+func (utuo *UsageTotalUpdateOne) SetCredits(f float64) *UsageTotalUpdateOne {
+	utuo.mutation.ResetCredits()
+	utuo.mutation.SetCredits(f)
+	return utuo
+}
+
+// SetNillableCredits sets the "credits" field if the given value is not nil.
+func (utuo *UsageTotalUpdateOne) SetNillableCredits(f *float64) *UsageTotalUpdateOne {
+	if f != nil {
+		utuo.SetCredits(*f)
+	}
+	return utuo
+}
+
+// AddCredits adds f to the "credits" field.
+func (utuo *UsageTotalUpdateOne) AddCredits(f float64) *UsageTotalUpdateOne {
+	utuo.mutation.AddCredits(f)
+	return utuo
+}
+
+// ClearCredits clears the value of the "credits" field.
+func (utuo *UsageTotalUpdateOne) ClearCredits() *UsageTotalUpdateOne {
+	utuo.mutation.ClearCredits()
+	return utuo
+}
+
 // SetStartIndex sets the "start_index" field.
 func (utuo *UsageTotalUpdateOne) SetStartIndex(u uint64) *UsageTotalUpdateOne {
 	utuo.mutation.ResetStartIndex()
@@ -635,6 +698,15 @@ func (utuo *UsageTotalUpdateOne) sqlSave(ctx context.Context) (_node *UsageTotal
 	if utuo.mutation.TotalTokensCleared() {
 		_spec.ClearField(usagetotal.FieldTotalTokens, field.TypeUint64)
 	}
+	if value, ok := utuo.mutation.Credits(); ok {
+		_spec.SetField(usagetotal.FieldCredits, field.TypeFloat64, value)
+	}
+	if value, ok := utuo.mutation.AddedCredits(); ok {
+		_spec.AddField(usagetotal.FieldCredits, field.TypeFloat64, value)
+	}
+	if utuo.mutation.CreditsCleared() {
+		_spec.ClearField(usagetotal.FieldCredits, field.TypeFloat64)
+	}
 	if value, ok := utuo.mutation.StartIndex(); ok {
 		_spec.SetField(usagetotal.FieldStartIndex, field.TypeUint64, value)
 	}

+ 109 - 0
hook/contact.go

@@ -4,7 +4,9 @@ import (
 	"encoding/json"
 	"fmt"
 	"github.com/gorilla/websocket"
+	"github.com/zeromicro/go-zero/core/logx"
 	"strings"
+	"wechat-api/workphone"
 )
 
 // 获取标签信息
@@ -239,3 +241,110 @@ func (h *Hook) AddFriendInChatRoom(ChatRoomId, wxWxid, friendId, desc string) er
 
 	return nil
 }
+
+// AddFriendsTask AddFriendTask 用于添加好友任务的消息结构
+type AddFriendsTask struct {
+	WeChatId string   `json:"WeChatId"`
+	Phones   []string `json:"Phones"`
+	Message  string   `json:"message"`
+	Remark   string   `json:"Remark"`
+	TaskId   int64    `json:"TaskId"`
+}
+
+// FindContactTask 用于查找联系人任务的消息结构
+type FindContactTask struct {
+	WeChatId string `json:"WeChatId"`
+	Content  string `json:"Content"`
+}
+
+// MessagePayload 用于封装消息的负载结构
+type MessagePayload[T any] struct {
+	Id      workphone.EnumMsgType `json:"Id"`
+	MsgType string                `json:"MsgType"`
+	Content T                     `json:"Content"`
+}
+
+// SendMessage 函数用于发送消息
+func SendMessage[T any](hook *Hook, msgType workphone.EnumMsgType, msgTypeStr string, content T) (map[string]interface{}, error) {
+	conn, err := hook.connWorkPhone()
+	if err != nil {
+		logx.Errorf("WebSocket 连接失败: %v", err)
+		return MessagePayload[T]{}.ToMap(), err
+	}
+	defer func() {
+		if cerr := conn.Close(); cerr != nil {
+			logx.Errorf("WebSocket 关闭失败: %v", cerr)
+		}
+	}()
+
+	message := MessagePayload[T]{
+		Id:      msgType,
+		MsgType: msgTypeStr,
+		Content: content,
+	}
+
+	data, err := json.Marshal(message)
+	if err != nil {
+		return message.ToMap(), fmt.Errorf("JSON 序列化失败: %w", err)
+	}
+
+	if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
+		return message.ToMap(), fmt.Errorf("发送消息失败: %w", err)
+	}
+	return message.ToMap(), nil
+}
+
+// AddFriendTask 函数用于创建并发送一个添加好友的任务
+// 参数:
+//
+//	ownerWxId: 发起添加好友请求的微信ID
+//	phone: 目标手机号
+//	msg: 添加好友时附带的消息
+//	taskId: 任务ID
+//
+// 返回值:
+//
+//	成功时返回包含添加好友任务信息的消息负载和nil错误
+//	失败时返回空的消息负载和相应的错误
+func (h *Hook) AddFriendTask(ownerWxId, phone, msg string, taskId int64) (map[string]interface{}, error) {
+	if ownerWxId == "" || phone == "" || msg == "" {
+		return MessagePayload[AddFriendsTask]{}.ToMap(), fmt.Errorf("invalid input parameters")
+	}
+	content := AddFriendsTask{
+		WeChatId: ownerWxId,
+		Phones:   []string{phone},
+		Message:  msg,
+		Remark:   "",
+		TaskId:   taskId,
+	}
+	return SendMessage(h, workphone.EnumMsgType_AddFriendsTask, "AddFriendsTask", content)
+}
+
+// FindContactByContent 函数用于创建并发送一个查找联系人的任务
+// 参数:
+//
+//	ownerWxId: 发起查找联系人请求的微信ID
+//	contentMessage: 查找联系人的查询内容
+//
+// 返回值:
+//
+//	成功时返回包含查找联系人任务信息的消息负载和nil错误
+//	失败时返回空的消息负载和相应的错误
+func (h *Hook) FindContactByContent(ownerWxId, contentMessage string) (map[string]interface{}, error) {
+	if ownerWxId == "" || contentMessage == "" {
+		return MessagePayload[FindContactTask]{}.ToMap(), fmt.Errorf("invalid input parameters")
+	}
+	content := FindContactTask{
+		WeChatId: ownerWxId,
+		Content:  contentMessage,
+	}
+	return SendMessage(h, workphone.EnumMsgType_FindContactTask, "FindContactTask", content)
+}
+
+func (m MessagePayload[T]) ToMap() map[string]interface{} {
+	return map[string]interface{}{
+		"Id":      m.Id,
+		"MsgType": m.MsgType,
+		"Content": m.Content,
+	}
+}

+ 20 - 15
hook/credit/credit.go

@@ -7,30 +7,35 @@ import (
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/custom_types"
 	"wechat-api/ent/usagetotal"
-	"wechat-api/hook/dify"
 )
 
+type Usage struct {
+	PromptTokens     uint64 `json:"prompt_tokens"`
+	CompletionTokens uint64 `json:"completion_tokens"`
+	TotalTokens      uint64 `json:"total_tokens"`
+}
+
 func AddCreditUsage(tx *ent.Tx, ctx context.Context,
 	agentId string, userId string, departmentId uint64,
 	question *string, answer *string,
-	originalData *custom_types.OriginalData, chatData *dify.ChatResp) error {
+	originalData *custom_types.OriginalData, chatData *Usage, model string) error {
 	// 积分明细表记录使用量
-	modelName, price := GetModelPrice()
-	number := ComputePrice(price, chatData.Metadata.Usage.TotalTokens)
-
+	modelName, price := GetModelPrice(model)
+	number := ComputePrice(price, chatData.TotalTokens)
+	
 	// 记录Token使用信息
 	usageDetailItem, err := tx.UsageDetail.Create().
-		SetType(3).            //1-微信 2-名片 3-智能体
-		SetBotID(agentId).     //智能体ID
+		SetType(3). //1-微信 2-名片 3-智能体
+		SetBotID(agentId). //智能体ID
 		SetReceiverID(userId). //接收者userID
-		SetApp(8).             //8-智能体
+		SetApp(8). //8-智能体
 		SetSessionID(0).
 		SetRequest(*question).
 		SetResponse(*answer).
 		SetOriginalData(*originalData).
-		SetTotalTokens(chatData.Metadata.Usage.TotalTokens).
-		SetPromptTokens(chatData.Metadata.Usage.PromptTokens).
-		SetCompletionTokens(chatData.Metadata.Usage.CompletionTokens).
+		SetTotalTokens(chatData.TotalTokens).
+		SetPromptTokens(chatData.PromptTokens).
+		SetCompletionTokens(chatData.CompletionTokens).
 		SetModel(modelName).
 		SetCredits(number).
 		Save(ctx)
@@ -46,7 +51,7 @@ func AddCreditUsage(tx *ent.Tx, ctx context.Context,
 		if ent.IsNotFound(err) {
 			usageTotal, err = tx.UsageTotal.Create().
 				SetBotID(agentId).
-				SetTotalTokens(chatData.Metadata.Usage.TotalTokens).
+				SetTotalTokens(chatData.TotalTokens).
 				SetEndIndex(usageDetailItem.ID).
 				SetOrganizationID(departmentId).
 				Save(ctx)
@@ -58,7 +63,7 @@ func AddCreditUsage(tx *ent.Tx, ctx context.Context,
 		// 更新Token使用总量
 		_, err = tx.UsageTotal.Update().
 			Where(usagetotal.OrganizationID(departmentId)).
-			SetTotalTokens(usageTotal.TotalTokens + chatData.Metadata.Usage.TotalTokens).
+			SetTotalTokens(usageTotal.TotalTokens + chatData.TotalTokens).
 			SetEndIndex(usageDetailItem.ID).
 			Save(ctx)
 		if err != nil {
@@ -90,8 +95,8 @@ func AddCreditUsage(tx *ent.Tx, ctx context.Context,
 	_, err = tx.CreditUsage.Create().
 		SetUserID(userId).
 		SetNumber(number).
-		SetBeforeNumber(beforeNumber).
-		SetAfterNumber(afterNumber).
+		SetBeforeNumber(0).
+		SetAfterNumber(0).
 		SetNtype(1).
 		SetNid(usageDetailItem.ID).
 		SetTable("usage_detail").

+ 30 - 26
hook/credit/models.go

@@ -1,6 +1,9 @@
 package credit
 
-import "math"
+import (
+	"math"
+	"strings"
+)
 
 var modelArray = []string{
 	"o1",
@@ -27,35 +30,36 @@ var modelArray = []string{
 }
 
 var priceArray = []float64{
+	0.01,
+	0.001667,
+	0.001333,
+	0.000733,
+	0.000548,
+	0.000365,
+	0.000274,
+	0.000267,
+	0.00025,
+	0.000219,
+	0.000205,
+	0.000183,
+	0.000137,
 	0.0001,
-	0.00001667,
-	0.00001333,
-	0.00000733,
-	0.00000548,
-	0.00000365,
-	0.00000274,
-	0.00000267,
-	0.0000025,
-	0.00000219,
-	0.00000205,
-	0.00000183,
-	0.00000137,
-	0.000001,
-	0.00000068,
-	0.00000067,
-	0.00000046,
-	0.00000046,
-	0.00000023,
-	0.00000014,
-	0.00000014,
+	0.000068,
+	0.000067,
+	0.000046,
+	0.000046,
+	0.000023,
+	0.000014,
+	0.000014,
 }
 
-func getModelName() string {
-	return "gpt-4o"
+func getModelName(modelName string) string {
+	// 将字符串转换为小写
+	return strings.ToLower(modelName)
 }
 
-func GetModelPrice() (model string, price float64) {
-	difyModelName := getModelName()
+func GetModelPrice(modelName string) (model string, price float64) {
+	difyModelName := getModelName(modelName)
 	for i, v := range modelArray {
 		if v == difyModelName {
 			return v, priceArray[i]
@@ -70,7 +74,7 @@ func ComputePrice(price float64, tokens uint64) float64 {
 	return math.Round(price*float64(tokens)*scale) / scale
 }
 
-// Subtraction() 保留小数点后6位的精确减法
+// Subtraction 保留小数点后6位的精确减法
 func Subtraction(number1, number2 float64) float64 {
 	d1 := number1 * 1000000
 	d2 := number2 * 1000000

+ 44 - 0
internal/handler/chat/add_friend_by_phone_handler.go

@@ -0,0 +1,44 @@
+package chat
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/chat"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wx/add_friend_by_phone chat AddFriendByPhone
+//
+
+//
+
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: AddFriendByPhoneReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func AddFriendByPhoneHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.AddFriendByPhoneReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := chat.NewAddFriendByPhoneLogic(r.Context(), svcCtx)
+		resp, err := l.AddFriendByPhone(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 5 - 0
internal/handler/routes.go

@@ -928,6 +928,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/wx/sendTextMsg",
 					Handler: chat.SendTextMsgHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx/add_friend_by_phone",
+					Handler: chat.AddFriendByPhoneHandler(serverCtx),
+				},
 			}...,
 		),
 	)

+ 73 - 0
internal/lock/wxid_lock.go

@@ -0,0 +1,73 @@
+package lock
+
+import (
+	"sync"
+)
+
+// WxIdLockManager 管理微信号级别的锁
+type WxIdLockManager struct {
+	lockMap map[string]*sync.Mutex
+	mapMu   sync.Mutex
+}
+
+var (
+	wxIdLockManager *WxIdLockManager
+	once            sync.Once
+)
+
+// GetWxIdLockManager 获取单例锁管理器
+func GetWxIdLockManager() *WxIdLockManager {
+	once.Do(func() {
+		wxIdLockManager = &WxIdLockManager{
+			lockMap: make(map[string]*sync.Mutex),
+		}
+	})
+	return wxIdLockManager
+}
+
+// getLock 获取指定微信号的锁
+func (m *WxIdLockManager) getLock(wxid string) *sync.Mutex {
+	m.mapMu.Lock()
+	defer m.mapMu.Unlock()
+
+	if _, ok := m.lockMap[wxid]; !ok {
+		m.lockMap[wxid] = &sync.Mutex{}
+	}
+	return m.lockMap[wxid]
+}
+
+// RunWithLock 只对某个微信号加锁并执行指定函数
+func (m *WxIdLockManager) RunWithLock(wxid string, fn func()) {
+	lock := m.getLock(wxid)
+	lock.Lock()
+	defer lock.Unlock()
+	fn()
+}
+
+var (
+	lockMap = make(map[string]*sync.Mutex)
+	mapLock = sync.Mutex{}
+)
+
+func LockWxId(wxid string) {
+	mapLock.Lock()
+	mu, ok := lockMap[wxid]
+	if !ok {
+		mu = &sync.Mutex{}
+		lockMap[wxid] = mu
+	}
+	mapLock.Unlock()
+
+	mu.Lock()
+}
+
+// UnlockWxId 解锁指定微信号
+func UnlockWxId(wxid string) {
+	mapLock.Lock()
+	mu, ok := lockMap[wxid]
+	mapLock.Unlock()
+
+	if ok {
+		mu.Unlock()
+	}
+}

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

@@ -264,6 +264,7 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 			}
 
 			totalTokens := uint64(0)
+			totalCredits := float64(0)
 			usageTotalInfo, _ := l.svcCtx.DB.UsageTotal.Query().
 				Where(
 					usagetotal.BotID(wxid),
@@ -271,6 +272,7 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 				Only(l.ctx)
 			if usageTotalInfo != nil {
 				totalTokens = usageTotalInfo.TotalTokens
+				totalCredits = usageTotalInfo.Credits
 			}
 
 			var agent types.AgentInfo
@@ -315,6 +317,7 @@ func (l *GetWxListLogic) GetWxList(req *types.WxListReq) (*types.WxListResp, err
 					ApiKey:           &v.APIKey,
 					TotalTokens:      &totalTokens,
 					Ctype:            &v.Ctype,
+					Credits:          &totalCredits,
 				})
 		}
 	}

+ 72 - 0
internal/logic/chat/add_friend_by_phone_logic.go

@@ -0,0 +1,72 @@
+package chat
+
+import (
+	"context"
+	"errors"
+
+	"wechat-api/ent"
+	"wechat-api/internal/service/addfriend"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/contextkey"
+
+	"github.com/suyuan32/simple-admin-common/enum/errorcode"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type AddFriendByPhoneLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewAddFriendByPhoneLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddFriendByPhoneLogic {
+	return &AddFriendByPhoneLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *AddFriendByPhoneLogic) AddFriendByPhone(req *types.AddFriendByPhoneReq) (resp *types.BaseMsgResp, err error) {
+	// todo: add your logic here and delete this line
+
+	var (
+		apiKeyObj *ent.ApiKey
+		ok        bool
+	)
+
+	//从上下文中获取鉴权中间件埋下的apiAuthInfo
+	apiKeyObj, ok = contextkey.AuthTokenInfoKey.GetValue(l.ctx)
+	if !ok {
+		return nil, errors.New("content get auth info err")
+	}
+	err = l.AppendWechaFriendAddReq(apiKeyObj, req)
+	if err != nil {
+		return nil, err
+	}
+	//addfriend.NewAddWechatFriendService(l.ctx, l.svcCtx).AddNewFriend(req.WeChatId, req.Phone, req.Message)
+	addfriend.NewAddWechatFriendService(l.ctx, l.svcCtx).FindFriendByContent(req.WeChatId, req.Phone)
+
+	resp = &types.BaseMsgResp{
+		Msg:  errormsg.Success,
+		Code: errorcode.OK,
+	}
+
+	return resp, nil
+}
+
+func (l *AddFriendByPhoneLogic) AppendWechaFriendAddReq(apiKeyObj *ent.ApiKey, req *types.AddFriendByPhoneReq) error {
+
+	res, err := l.svcCtx.DB.AddWechatFriendLog.Create().
+		SetNotNilOwnerWxID(&req.WeChatId).
+		SetNotNilOwnerWxType(&req.Type).
+		SetNotNilFindContent(&req.Phone).
+		SetNotNilMessage(&req.Message).
+		Save(l.ctx)
+
+	if err == nil {
+		logx.Infof("AppendWechaFriendAddReq succ,get id:%d", res.ID)
+	}
+	return err
+}

+ 4 - 212
internal/logic/chat/chat_completions_logic.go

@@ -5,12 +5,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"net"
-	"net/url"
-	"regexp"
-	"strconv"
-	"strings"
-
 	"wechat-api/ent"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -18,11 +12,6 @@ import (
 	"wechat-api/internal/utils/contextkey"
 	"wechat-api/internal/utils/typekit"
 
-	"wechat-api/ent/custom_types"
-	"wechat-api/ent/predicate"
-	"wechat-api/ent/usagedetail"
-	"wechat-api/ent/usagetotal"
-
 	"github.com/zeromicro/go-zero/core/logx"
 )
 
@@ -137,7 +126,7 @@ func (l *ChatCompletionsLogic) AdjustRequest(req *types.CompApiReq, apiKeyObj *e
 	if req.IsBatch {
 		//流模式暂时不支持异步模式
 		//Callback格式非法则取消批量模式
-		if req.Stream || !IsValidURL(&req.Callback, true) {
+		if req.Stream || !compapi.IsValidURL(&req.Callback, true) {
 			req.IsBatch = false
 		}
 	}
@@ -184,107 +173,9 @@ func (l *ChatCompletionsLogic) AppendAsyncRequest(apiKeyObj *ent.ApiKey, req *ty
 }
 
 func (l *ChatCompletionsLogic) AppendUsageDetailLog(authToken string, req *types.CompApiReq, resp *types.CompOpenApiResp) error {
-
-	logType := 5
-	rawReqResp := custom_types.OriginalData{Request: req, Response: resp}
-	tmpId := 0
-	tmpId, _ = strconv.Atoi(resp.ID)
-	sessionId := uint64(tmpId)
-	orgId := uint64(0)
-	apiKeyObj, ok := contextkey.AuthTokenInfoKey.GetValue(l.ctx)
-	if ok {
-		orgId = apiKeyObj.OrganizationID
-	}
-	promptTokens := uint64(resp.Usage.PromptTokens)
-	completionToken := uint64(resp.Usage.CompletionTokens)
-	totalTokens := promptTokens + completionToken
-
-	msgContent := getMessageContentStr(req.Messages[0].Content)
-
-	_, _, _ = logType, sessionId, totalTokens
-	res, err := l.svcCtx.DB.UsageDetail.Create().
-		SetNotNilType(&logType).
-		SetNotNilBotID(&authToken).
-		SetNotNilReceiverID(&req.EventType).
-		SetNotNilSessionID(&sessionId).
-		SetNillableRequest(&msgContent).
-		SetNillableResponse(&resp.Choices[0].Message.Content).
-		SetNillableOrganizationID(&orgId).
-		SetOriginalData(rawReqResp).
-		SetNillablePromptTokens(&promptTokens).
-		SetNillableCompletionTokens(&completionToken).
-		SetNillableTotalTokens(&totalTokens).
-		Save(l.ctx)
-
-	if err == nil { //插入UsageDetai之后再统计UsageTotal
-		l.updateUsageTotal(authToken, res.ID, orgId)
-	}
-	return err
-}
-
-func (l *ChatCompletionsLogic) getUsagetotalIdByToken(authToken string) (uint64, error) {
-
-	var predicates []predicate.UsageTotal
-	predicates = append(predicates, usagetotal.BotIDEQ(authToken))
-	return l.svcCtx.DB.UsageTotal.Query().Where(predicates...).FirstID(l.ctx)
-
-}
-
-func (l *ChatCompletionsLogic) replaceUsagetotalTokens(authToken string, sumTotalTokens uint64, newUsageDetailId uint64, orgId uint64) error {
-
-	Id, err := l.getUsagetotalIdByToken(authToken)
-	if err != nil && !ent.IsNotFound(err) {
-		return err
-	}
-	if Id > 0 { //UsageTotal have record by  newUsageDetailId
-		_, err = l.svcCtx.DB.UsageTotal.UpdateOneID(Id).
-			SetTotalTokens(sumTotalTokens).
-			SetEndIndex(newUsageDetailId).
-			Save(l.ctx)
-	} else { //create new record by  newUsageDetailId
-		logType := 5
-		_, err = l.svcCtx.DB.UsageTotal.Create().
-			SetNotNilBotID(&authToken).
-			SetNotNilEndIndex(&newUsageDetailId).
-			SetNotNilTotalTokens(&sumTotalTokens).
-			SetNillableType(&logType).
-			SetNotNilOrganizationID(&orgId).
-			Save(l.ctx)
-	}
-
-	return err
-}
-
-func (l *ChatCompletionsLogic) updateUsageTotal(authToken string, newUsageDetailId uint64, orgId uint64) error {
-
-	sumTotalTokens, err := l.sumTotalTokensByAuthToken(authToken) //首先sum UsageDetail的TotalTokens
-	if err == nil {
-		err = l.replaceUsagetotalTokens(authToken, sumTotalTokens, newUsageDetailId, orgId) //再更新(包含新建)Usagetotal的otalTokens
-	}
-	return err
-}
-
-// sum total_tokens from usagedetail by AuthToken
-func (l *ChatCompletionsLogic) sumTotalTokensByAuthToken(authToken string) (uint64, error) {
-
-	var predicates []predicate.UsageDetail
-	predicates = append(predicates, usagedetail.BotIDEQ(authToken))
-
-	var res []struct {
-		Sum, Min, Max, Count uint64
-	}
-	totalTokens := uint64(0)
-	var err error = nil
-	err = l.svcCtx.DB.UsageDetail.Query().Where(predicates...).Aggregate(ent.Sum("total_tokens"),
-		ent.Min("total_tokens"), ent.Max("total_tokens"), ent.Count()).Scan(l.ctx, &res)
-	if err == nil {
-		if len(res) > 0 {
-			totalTokens = res[0].Sum
-		} else {
-			totalTokens = 0
-		}
-	}
-	return totalTokens, err
+	svcCtx := &compapi.ServiceContext{Config: l.svcCtx.Config, DB: l.svcCtx.DB,
+		Rds: l.svcCtx.Rds}
+	return compapi.AppendUsageDetailLog(l.ctx, svcCtx, authToken, req, resp)
 }
 
 func (l *FastgptChatLogic) AdjustRequest(req *types.CompApiReq, apiKeyObj *ent.ApiKey) {
@@ -387,105 +278,6 @@ func humanSeeValidResult(ctx context.Context, req *types.CompApiReq, resp *types
 	fmt.Println(typekit.PrettyPrint(nres))
 }
 
-func apiKeyObjAdjust(eventType string, workId string, obj *ent.ApiKey) {
-	if eventType != "fastgpt" {
-		return
-	}
-	obj.OpenaiKey, _ = compapi.GetWorkInfoByID(eventType, workId)
-}
-
-// 合法域名正则(支持通配符、中文域名等场景按需调整)
-var domainRegex = regexp.MustCompile(
-	// 多级域名(如 example.com)
-	`^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$` +
-		`|` +
-		// 单级域名(如 localhost 或 mytest-svc)
-		`^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$`,
-)
-
-func IsValidURL(input *string, adjust bool) bool {
-	// 空值直接返回
-	if *input == "" {
-		return false
-	}
-	inputStr := *input
-
-	// --- 预处理输入:自动补全协议 ---
-	// 若输入不包含协议头,默认添加 http://
-	if !strings.Contains(*input, "://") {
-		inputStr = "http://" + *input
-	}
-
-	// --- 解析 URL ---
-	u, err := url.Parse(inputStr)
-	if err != nil {
-		return false
-	}
-
-	// --- 校验协议 ---
-	// 只允许常见协议(按需扩展)
-	switch u.Scheme {
-	case "http", "https", "ftp", "ftps":
-	default:
-		return false
-	}
-
-	// --- 拆分 Host 和 Port ---
-	host, port, err := net.SplitHostPort(u.Host)
-	if err != nil {
-		// 无端口时,整个 Host 作为主机名
-		host = u.Host
-		port = ""
-	}
-
-	// --- 校验主机名 ---
-	// 场景1:IPv4 或 IPv6
-	if ip := net.ParseIP(host); ip != nil {
-		// 允许私有或保留 IP(按需调整)
-		// 示例中允许所有合法 IP
-	} else {
-		// 场景2:域名(包括 localhost)
-		if !domainRegex.MatchString(host) {
-			return false
-		}
-	}
-
-	// --- 校验端口 ---
-	if port != "" {
-		p, err := net.LookupPort("tcp", port) // 动态获取端口(如 "http" 对应 80)
-		if err != nil {
-			// 直接尝试解析为数字端口
-			numPort, err := strconv.Atoi(port)
-			if err != nil || numPort < 1 || numPort > 65535 {
-				return false
-			}
-		} else if p == 0 { // 动态端口为 0 时无效
-			return false
-		}
-	}
-	if adjust {
-		*input = inputStr
-	}
-	return true
-}
-
-func getMessageContentStr(input any) string {
-	str := ""
-	switch val := input.(type) {
-	case string:
-		str = val
-	case []interface{}:
-		if len(val) > 0 {
-			if valc, ok := val[0].(map[string]interface{}); ok {
-				if valcc, ok := valc["text"]; ok {
-					str, _ = valcc.(string)
-				}
-			}
-		}
-	}
-	return str
-}
-
 func isAsyncReqest(req *types.CompApiReq) bool {
 	return req.IsBatch
 }

+ 6 - 2
internal/logic/chatrecords/gpts_submit_api_chat_logic.go

@@ -204,14 +204,18 @@ func (l *GptsSubmitApiChatLogic) GptsSubmitApiChat(tokenStr string, req *types.G
 					originalData := custom_types.OriginalData{}
 					originalData.Request = chatReq
 					originalData.Response = chatData
-
+					usage := credit.Usage{
+						CompletionTokens: chatData.Metadata.Usage.CompletionTokens,
+						PromptTokens:     chatData.Metadata.Usage.PromptTokens,
+						TotalTokens:      chatData.Metadata.Usage.TotalTokens,
+					}
 					if err != nil {
 						l.Logger.Errorf("start transaction error:%v\n", err)
 					} else {
 						err = credit.AddCreditUsage(tx, l.ctx,
 							agentId, userId, *userInfo.DepartmentId,
 							req.Content, &answer,
-							&originalData, &chatData,
+							&originalData, &usage, "gpt-4o-mini",
 						)
 						if err != nil {
 							_ = tx.Rollback()

+ 12 - 1
internal/logic/contact/get_contact_list_logic.go

@@ -211,12 +211,23 @@ func (l *GetContactListLogic) GetContactList(req *types.ContactListReq) (*types.
 			}
 		}
 
+		// 这里要判断联系人与自定义字段的修改时间,使用最大的那个
+		var updateTime, cfUpdateTime, cUpdateTime int64 = 0, 0, v.UpdatedAt.UnixMilli()
+		if len(v.Edges.ContactFields) > 0 {
+			cfUpdateTime = v.Edges.ContactFields[0].UpdatedAt.UnixMilli()
+		}
+		if cfUpdateTime > cUpdateTime {
+			updateTime = cfUpdateTime
+		} else {
+			updateTime = cUpdateTime
+		}
+
 		resp.Data.Data = append(resp.Data.Data,
 			types.ContactInfo{
 				BaseIDInfo: types.BaseIDInfo{
 					Id:        &v.ID,
 					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
-					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(updateTime),
 				},
 				Status:             &v.Status,
 				WxWxid:             &v.WxWxid,

+ 8 - 7
internal/logic/credit_balance/get_credit_balance_list_logic.go

@@ -27,14 +27,15 @@ func NewGetCreditBalanceListLogic(ctx context.Context, svcCtx *svc.ServiceContex
 }
 
 func (l *GetCreditBalanceListLogic) GetCreditBalanceList(req *types.CreditBalanceListReq) (*types.CreditBalanceListResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
 	isAdmin := l.ctx.Value("isAdmin").(bool)
-	if !isAdmin {
-		return nil, errorx.NewInvalidArgumentError("权限不足")
-	}
-
 	query := l.svcCtx.WechatDB.Find(&model.CreditBalance{})
-	if req.OrganizationId != nil && *req.OrganizationId > 0 {
-		query = query.Where("organization_id = ?", *req.OrganizationId)
+	if isAdmin {
+		if req.OrganizationId != nil && *req.OrganizationId > 0 {
+			query = query.Where("organization_id = ?", *req.OrganizationId)
+		}
+	} else {
+		query = query.Where("organization_id = ?", organizationId)
 	}
 	creditBalanceList := make([]model.CreditBalance, 0)
 	err := query.Order("created_at DESC").Find(&creditBalanceList).Error
@@ -58,7 +59,7 @@ func (l *GetCreditBalanceListLogic) GetCreditBalanceList(req *types.CreditBalanc
 	for _, v := range creditBalanceList {
 		departmentInfo, err := l.svcCtx.CoreRpc.GetDepartmentById(l.ctx, &core.IDReq{Id: uint64(v.OrganizationID)})
 		if err != nil {
-			return nil, err
+			continue
 		}
 
 		status := int(v.Status)

+ 5 - 1
internal/service/MessageHandlers/contact_Label_info_notice.go

@@ -12,6 +12,7 @@ import (
 	"wechat-api/ent/label"
 	"wechat-api/ent/labellog"
 	"wechat-api/ent/wx"
+	"wechat-api/internal/lock"
 	"wechat-api/internal/pkg/wechat_ws"
 	"wechat-api/internal/svc"
 	"wechat-api/workphone"
@@ -90,7 +91,8 @@ func (f *ContactLabelInfoNotice) Handle(ctx context.Context, msg *wechat_ws.MsgJ
 		tsInt, err := strconv.ParseInt(labelWx.CreateTime, 10, 64)
 		if err != nil {
 			logx.Errorf("时间戳转换失败: %v (Label ID: %d)", err, labelWx.LabelId)
-			continue
+			//continue
+			tsInt = time.Now().UnixMilli()
 		}
 
 		// 插入 LabelLog
@@ -122,6 +124,8 @@ func (f *ContactLabelInfoNotice) Handle(ctx context.Context, msg *wechat_ws.MsgJ
 		}
 	}
 
+	lock.LockWxId(message.WeChatId)
+	defer lock.UnlockWxId(message.WeChatId)
 	// 批量插入 LabelLog
 	if len(bulkLabelLogs) > 0 {
 		err := svcCtx.DB.LabelLog.CreateBulk(bulkLabelLogs...).

+ 112 - 0
internal/service/MessageHandlers/find_contact_task_result_notice.go

@@ -0,0 +1,112 @@
+package MessageHandlers
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"github.com/zeromicro/go-zero/core/logx"
+	"time"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/internal/pkg/wechat_ws"
+	"wechat-api/internal/svc"
+)
+
+type FindContactTaskResultNoticeHandler struct {
+	svcCtx *svc.ServiceContext
+}
+
+func NewFindContactTaskResultNoticeHandler(svcCtx *svc.ServiceContext) *FindContactTaskResultNoticeHandler {
+	return &FindContactTaskResultNoticeHandler{
+		svcCtx: svcCtx,
+	}
+}
+
+type EnumGender int
+
+const (
+	UnknownGender EnumGender = 0
+	Male          EnumGender = 1
+	Female        EnumGender = 2
+)
+
+// 自定义 JSON 解析,支持字符串 -> 枚举
+func (e *EnumGender) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err == nil {
+		switch s {
+		case "Male":
+			*e = Male
+		case "Female":
+			*e = Female
+		default:
+			*e = UnknownGender
+		}
+		return nil
+	}
+
+	var i int
+	if err := json.Unmarshal(b, &i); err == nil {
+		*e = EnumGender(i)
+		return nil
+	}
+	return errors.New("invalid gender value")
+}
+
+// 用于反序列化的消息结构体(扩展 Gender 类型)
+type FindContactTaskResultNoticeMessage struct {
+	WeChatId   string      `json:"WeChatId"`
+	SearchText string      `json:"SearchText"`
+	Success    bool        `json:"Success"`
+	IsFriend   bool        `json:"IsFriend"`
+	UserName   *string     `json:"UserName"`
+	Alias      *string     `json:"Alias"`
+	NickName   *string     `json:"NickName"`
+	Gender     *EnumGender `json:"Gender"` // 也是指针
+	Country    *string     `json:"Country"`
+	Province   *string     `json:"Province"`
+	City       *string     `json:"City"`
+	Avatar     *string     `json:"Avatar"`
+	ErrMsg     *string     `json:"ErrMsg"`
+}
+
+func (f *FindContactTaskResultNoticeHandler) Handle(ctx context.Context, msg *wechat_ws.MsgJsonObject, svcCtx *svc.ServiceContext) error {
+	var message FindContactTaskResultNoticeMessage
+
+	logx.Infof("msg.Message 的内容是:%s", msg.Message)
+	if err := json.Unmarshal([]byte(msg.Message), &message); err != nil {
+		return err
+	}
+	//logx.Infof("msg.Message 的内容是:%s", message)
+	//var isCanAdd int
+	m, err := ParseJSONStringToMap(msg.Message)
+	if err != nil {
+		logx.Errorf("解析 JSON 失败: %v", err)
+		return err
+	}
+	update := svcCtx.DB.AddWechatFriendLog.Update().
+		Where(addwechatfriendlog.OwnerWxIDEQ(message.WeChatId)).
+		Where(addwechatfriendlog.FindContentEQ(message.SearchText)).
+		SetFindResult(m).
+		SetUpdatedAt(time.Now().Unix())
+	if message.Success {
+		if message.IsFriend {
+			update = update.SetIsCanAdd(0)
+		} else {
+			update = update.SetIsCanAdd(1)
+		}
+	}
+	if _, err := update.Save(ctx); err != nil {
+		logx.Errorf("更新 AddWechatFriendLog 失败: %v", err)
+		return err
+	}
+	return nil
+}
+
+func ParseJSONStringToMap(jsonStr string) (map[string]interface{}, error) {
+	if !json.Valid([]byte(jsonStr)) {
+		return nil, errors.New("非法 JSON 字符串")
+	}
+	var result map[string]interface{}
+	err := json.Unmarshal([]byte(jsonStr), &result)
+	return result, err
+}

+ 51 - 38
internal/service/MessageHandlers/friend_push_notice.go

@@ -7,12 +7,14 @@ import (
 	"github.com/zeromicro/go-zero/core/logx"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 	"wechat-api/ent"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labellog"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/wx"
+	"wechat-api/internal/lock"
 	"wechat-api/internal/pkg/wechat_ws"
 	"wechat-api/internal/svc"
 	"wechat-api/workphone"
@@ -76,7 +78,8 @@ func (f *FriendPushNoticeHandler) Handler(msg *wechat_ws.MsgJsonObject) error {
 }
 
 type FriendPushNoticeTypeHandler struct {
-	svcCtx *svc.ServiceContext
+	svcCtx  *svc.ServiceContext
+	lockMap sync.Map // 微信号 -> *sync.Mutex
 }
 
 func NewFriendPushNoticeTypeHandler(svcCtx *svc.ServiceContext) *FriendPushNoticeTypeHandler {
@@ -106,6 +109,12 @@ func (f *FriendPushNoticeTypeHandler) Handle(ctx context.Context, msg *wechat_ws
 	for _, friend := range message.Friends {
 		var friendId uint64
 		friendType := 1
+		if strings.Contains(friend.FriendId, "openim") {
+			friendType = 4
+		} else {
+			friendType = 1
+		}
+		//修改拉黑后的状态被重置
 		friendId, err = svcCtx.DB.Contact.Create().
 			SetWxWxid(message.WeChatId).
 			SetType(friendType).
@@ -116,9 +125,14 @@ func (f *FriendPushNoticeTypeHandler) Handle(ctx context.Context, msg *wechat_ws
 			SetHeadimg(friend.Avatar).
 			SetOrganizationID(wxInfo.OrganizationID).
 			OnConflict().
-			UpdateNewValues().
-			SetType(friendType).
-			SetOrganizationID(wxInfo.OrganizationID).
+			UpdateWxWxid().
+			UpdateWxid().
+			UpdateType().
+			UpdateAccount().
+			UpdateNickname().
+			UpdateMarkname().
+			UpdateHeadimg().
+			UpdateOrganizationID().
 			ID(ctx)
 		if err != nil {
 			logx.Errorf("Contact.Create 失败, OrgID=%d, err=%v", wxInfo.OrganizationID, err)
@@ -165,44 +179,38 @@ func (f *FriendPushNoticeTypeHandler) Handle(ctx context.Context, msg *wechat_ws
 				continue
 			}
 
-			//svcCtx.DB.LabelRelationship.Create().
-			//	SetOrganizationID(wxInfo.OrganizationID).
-			//	SetContactID(friendId).
-			//	SetLabelID(labelInfo.ID).
-			//	SetAccount(friend.FriendNo).
-			//	SetNickname(friend.FriendNick).
-			//	SetMarkname(friend.Memo).
-			//	SetHeadimg(friend.Avatar).
-			//	SetOrganizationID(wxInfo.OrganizationID).
-			//	OnConflict().
-			//	UpdateNewValues().
-			//	SetType(friendType).
-			//	SetOrganizationID(wxInfo.OrganizationID).
-			//	ID(ctx)
-
-			//生成批量的关系数据 待插入
-			labelRelationshipCreates = append(labelRelationshipCreates,
-				svcCtx.DB.LabelRelationship.Create().
-					//SetID(int(label.LabelId)).
-					SetOrganizationID(wxInfo.OrganizationID).
-					SetContactID(friendId).
-					SetStatus(1).
-					SetLabelID(labelInfo.ID).
-					SetCreatedAt(time.Now()).
-					SetUpdatedAt(time.Now()),
-			)
+			_, err = svcCtx.DB.LabelRelationship.Query().Where(
+				labelrelationship.LabelIDEQ(labelInfo.ID),
+				//label.StatusEQ(remoteLabel.LabelName),
+				labelrelationship.ContactIDEQ(friendId),
+			).Only(ctx)
+
+			if err != nil || ent.IsNotFound(err) {
+				labelRelationshipCreates = append(labelRelationshipCreates,
+					svcCtx.DB.LabelRelationship.Create().
+						//SetID(int(label.LabelId)).
+						SetOrganizationID(wxInfo.OrganizationID).
+						SetContactID(friendId).
+						SetStatus(1).
+						SetLabelID(labelInfo.ID).
+						SetCreatedAt(time.Now()).
+						SetUpdatedAt(time.Now()),
+				)
+			}
+
 			//
 		}
 	}
 	if len(labelRelationshipCreates) > 0 {
-		errShip := svcCtx.DB.LabelRelationship.CreateBulk(labelRelationshipCreates...).
-			OnConflict(
-				sql.ConflictColumns(labelrelationship.FieldLabelID, labelrelationship.FieldContactID),
-			).DoNothing().Exec(ctx)
-		if errShip != nil {
-			logx.Error("label_relationship.create.fail: ", wxInfo.OrganizationID, labelRelationshipCreates)
-			return err
-		}
+		lock.GetWxIdLockManager().RunWithLock(message.WeChatId, func() {
+			errShip := svcCtx.DB.LabelRelationship.CreateBulk(labelRelationshipCreates...).
+				OnConflict(
+					sql.ConflictColumns(labelrelationship.FieldLabelID, labelrelationship.FieldContactID),
+				).DoNothing().Exec(ctx)
+			if errShip != nil {
+				logx.Error("label_relationship.create.fail: ", wxInfo.OrganizationID, labelRelationshipCreates)
+			}
+		})
 	}
 	return nil
 }
@@ -227,3 +235,8 @@ func ParseCSVToIntSlice(csv string) ([]int, error) {
 	}
 	return result, nil
 }
+
+func (f *FriendPushNoticeTypeHandler) getWxLock(wxid string) *sync.Mutex {
+	actual, _ := f.lockMap.LoadOrStore(wxid, &sync.Mutex{})
+	return actual.(*sync.Mutex)
+}

+ 2 - 0
internal/service/MessageHandlers/register_strategy.go

@@ -43,6 +43,8 @@ func (h *MessageHandler) RegisterStrategies() {
 		"FriendPushNotice": toStrategy(NewFriendPushNoticeTypeHandler),
 		//"ChatroomPushNotice":     toStrategy(NewChatroomPushNoticeTypeHandler),
 		"ContactLabelInfoNotice": toStrategy(NewContactLabelInfoNotice),
+		"FindContactTaskResult":  toStrategy(NewFindContactTaskResultNoticeHandler),
+		"TaskResultNotice":       toStrategy(NewTaskResultNoticeHandler),
 	}
 	for msgType, strategyFunc := range strategyMap {
 		h.RegisterStrategy(msgType, strategyFunc(h.svcCtx))

+ 75 - 0
internal/service/MessageHandlers/task_result_notice.go

@@ -0,0 +1,75 @@
+package MessageHandlers
+
+import (
+	"context"
+	"encoding/json"
+	"github.com/zeromicro/go-zero/core/logx"
+	"strconv"
+	"time"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/internal/pkg/wechat_ws"
+	"wechat-api/internal/svc"
+)
+
+type TaskResultNoticeHandler struct {
+	svcCtx *svc.ServiceContext
+}
+
+func NewTaskResultNoticeHandler(svcCtx *svc.ServiceContext) *TaskResultNoticeHandler {
+	return &TaskResultNoticeHandler{
+		svcCtx: svcCtx,
+	}
+}
+
+// Handle 实现 MessageHandlerStrategy 接口
+func (f *TaskResultNoticeHandler) Handle(ctx context.Context, msg *wechat_ws.MsgJsonObject, svcCtx *svc.ServiceContext) error {
+
+	var messageTask TaskResultNoticeMessage
+	if err := json.Unmarshal([]byte(msg.Message), &messageTask); err != nil {
+		logx.Errorf("预处理 JSON 失败: %v", err)
+		return err
+	}
+	// 如果 TaskId 是字符串,就转换成数字
+	var taskIdInt int64
+	if messageTask.TaskId != nil {
+		var err error
+		taskIdInt, err = strconv.ParseInt(*messageTask.TaskId, 10, 64)
+		if err != nil {
+			logx.Errorf("Unmarshal.fail")
+			return err
+		}
+	}
+
+	if messageTask.TaskType != "AddFriendsTask" {
+		logx.Infof("不是添加好友任务的回执")
+		return nil
+	}
+	m, err := ParseJSONStringToMap(msg.Message)
+	if err != nil {
+		logx.Errorf("解析 JSON 失败: %v", err)
+		return err
+	}
+	update := svcCtx.DB.AddWechatFriendLog.Update().
+		Where(addwechatfriendlog.OwnerWxIDEQ(*messageTask.WeChatId)).
+		Where(addwechatfriendlog.TaskIDEQ(taskIdInt)).
+		//SetFindResult(m).
+		SetAddResult(m).
+		SetUpdatedAt(time.Now().Unix())
+	if *messageTask.Success {
+		update.SetIsCanAdd(2)
+	}
+	if _, err := update.Save(ctx); err != nil {
+		logx.Errorf("更新AddWechatFriendLog-field-add-result失败: %v", err)
+		return err
+	}
+	return nil
+}
+
+type TaskResultNoticeMessage struct {
+	Success  *bool   `json:"Success,omitempty"`  // 指针,便于判断字段是否存在
+	Code     *int32  `json:"Code,omitempty"`     // 错误码
+	ErrMsg   *string `json:"ErrMsg,omitempty"`   // 错误描述
+	TaskId   *string `json:"TaskId,omitempty"`   // 任务ID(因前面问题,保持 string 类型)
+	TaskType string  `json:"TaskType,omitempty"` // 枚举类型
+	WeChatId *string `json:"WeChatId,omitempty"` // 微信号
+}

+ 88 - 0
internal/service/addfriend/add_wechat_friend_log.go

@@ -0,0 +1,88 @@
+package addfriend
+
+import (
+	"context"
+	"github.com/bwmarrin/snowflake"
+	"github.com/zeromicro/go-zero/core/logx"
+	"log"
+	"time"
+	"wechat-api/ent/addwechatfriendlog"
+	"wechat-api/hook"
+	"wechat-api/internal/svc"
+)
+
+type AddWechatFriendService struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewAddWechatFriendService(ctx context.Context, svcCtx *svc.ServiceContext) *AddWechatFriendService {
+	return &AddWechatFriendService{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+// FindFriendByContent 查找好友的服务
+// 参数  wechatId   微信ID
+// content  手机号 或者其他
+
+func (l *AddWechatFriendService) FindFriendByContent(wechatId, content string) bool {
+	//先记录数据 --- 避免 发送出请求,立马返回 导致 数据 还没入库
+	hookClient := hook.NewHook("", "", "")
+	result, err := hookClient.FindContactByContent(wechatId, content)
+
+	if err != nil {
+		result["sendResult"] = "success"
+	} else {
+		result["sendResult"] = err
+	}
+	//发送第三方查找
+	update := l.svcCtx.DB.AddWechatFriendLog.Update().
+		Where(addwechatfriendlog.OwnerWxIDEQ(wechatId)).
+		Where(addwechatfriendlog.FindContentEQ(content)).
+		SetFindRequest(result).
+		SetUpdatedAt(time.Now().Unix())
+	_, err = update.Save(l.ctx)
+	if err != nil || result["sendResult"] != "success" {
+		logx.Errorf("更新 AddWechatFriendLog 失败 或者: %v", err)
+		return false
+	}
+	return true
+}
+
+// AddNewFriend 添加好友的服务
+// 参数  wechatId   微信ID
+// content  手机号 或者其他
+// message  备注
+
+func (l *AddWechatFriendService) AddNewFriend(wechatId, content, message string) bool {
+	//先记录请求
+	hookClient := hook.NewHook("", "", "")
+	node, err := snowflake.NewNode(1) // 1 是节点 ID,根据需要设置
+	if err != nil {
+		log.Fatal(err)
+	}
+	taskId := node.Generate()
+	result, err := hookClient.AddFriendTask(wechatId, content, message, taskId.Int64())
+
+	if err != nil {
+		result["sendResult"] = "success"
+	} else {
+		result["sendResult"] = err
+	}
+	update := l.svcCtx.DB.AddWechatFriendLog.Update().
+		Where(addwechatfriendlog.OwnerWxIDEQ(wechatId)).
+		Where(addwechatfriendlog.FindContentEQ(content)).
+		SetAddRequest(result).
+		SetTaskID(taskId.Int64()).
+		AddTaskCount(1).
+		SetUpdatedAt(time.Now().Unix())
+	_, err = update.Save(l.ctx)
+	if err != nil || result["sendResult"] != "success" {
+		logx.Errorf("更新 AddWechatFriendLog 失败 或者: %v", err)
+		return false
+	}
+	return true //获取好友列表
+}

+ 11 - 9
internal/svc/service_context.go

@@ -1,6 +1,14 @@
 package svc
 
 import (
+	"time"
+	"wechat-api/database"
+	"wechat-api/database/dao/wechat/query"
+	"wechat-api/internal/config"
+	"wechat-api/internal/middleware"
+	"wechat-api/internal/pkg/wechat_ws"
+	"wechat-api/mongo_model"
+
 	"github.com/bwmarrin/snowflake"
 	"github.com/mojocn/base64Captcha"
 	"github.com/redis/go-redis/v9"
@@ -10,20 +18,14 @@ import (
 	"github.com/zeromicro/go-zero/core/collection"
 	"github.com/zeromicro/go-zero/core/logx"
 	"gorm.io/gorm"
-	"time"
-	"wechat-api/database"
-	"wechat-api/database/dao/wechat/query"
-	"wechat-api/internal/config"
-	"wechat-api/internal/middleware"
-	"wechat-api/internal/pkg/wechat_ws"
-	"wechat-api/mongo_model"
 
 	"github.com/casbin/casbin/v2"
 
-	"github.com/zeromicro/go-zero/rest"
-	"github.com/zeromicro/go-zero/zrpc"
 	"wechat-api/ent"
 	_ "wechat-api/ent/runtime"
+
+	"github.com/zeromicro/go-zero/rest"
+	"github.com/zeromicro/go-zero/zrpc"
 )
 
 type ServiceContext struct {

+ 14 - 1
internal/types/types.go

@@ -340,7 +340,9 @@ type WxInfo struct {
 	GroupBlockList []ContactInfo `json:"groupBlockList,optional"`
 	// 使用token总数
 	TotalTokens *uint64 `json:"totalTokens,optional"`
-	Ctype       *uint64 `json:"ctype,optional"`
+	// 使用积分总数
+	Credits *float64 `json:"credits,optional"`
+	Ctype   *uint64  `json:"ctype,optional"`
 }
 
 // swagger:model UpdateBlockAndAllowListReq
@@ -1981,6 +1983,15 @@ type WxidReq struct {
 	Wxid string `json:"wxid"`
 }
 
+// add_friend_by_phone api接口请求值
+// swagger:model AddFriendByPhoneReq
+type AddFriendByPhoneReq struct {
+	Type     int    `json:"type"`
+	WeChatId string `json:"WeChatId"`
+	Phone    string `json:"phone"`
+	Message  string `json:"message"`
+}
+
 // 以下是API请求类型
 // swagger:model CompApiReq
 type CompApiReq struct {
@@ -3455,6 +3466,8 @@ type UsageTotalInfo struct {
 	BotId *string `json:"botId,optional"`
 	// 使用token总数
 	TotalTokens *uint64 `json:"totalTokens,optional"`
+	// 使用积分总数
+	Credits float64 `json:"credits,optional"`
 	// 重制后的起始usage_detail 索引
 	StartIndex *uint64 `json:"startIndex,optional"`
 	// usage_detail 索引

+ 11 - 0
internal/types/workphone.go

@@ -29,3 +29,14 @@ type WorkPhoneGetWeChatsResp struct {
 	Data []WorkPhoneWeChat `json:"data"`
 	Msg  string            `json:"msg"`
 }
+type FindContactTaskResultNoticeMessageWrapper struct {
+	WeChatId   string `json:"WeChatId"`
+	SearchText string `json:"SearchText"`
+	Success    bool   `json:"Success"`
+	UserName   string `json:"UserName"`
+	NickName   string `json:"NickName"`
+	Gender     string `json:"Gender"`
+	Province   string `json:"Province"`
+	City       string `json:"City"`
+	Avatar     string `json:"Avatar"`
+}

+ 1 - 1
internal/utils/compapi/form.go

@@ -15,7 +15,7 @@ func (me *FormClient) ResponseFormatSetting(req *types.CompApiReq) ResponseForma
 	//Message重构的配置
 	me.ResformatConfig.SysmesArgs = []any{nowTime, weekday}
 	me.ResformatConfig.SysmesTmpl = `# 任务
-请帮助user从聊天记录中提取表单值,并返回一个JSON格式的表单值
+请根据提供的 表单模板,从聊天记录中提取出 用户 的相关信息,并将结果以 json 形式返回
 
 # 背景信息
 当前时间是:%s

+ 318 - 0
internal/utils/compapi/func.go

@@ -5,18 +5,274 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"net"
 	"net/http"
+	"net/url"
+	"reflect"
+	"regexp"
+	"strconv"
 	"strings"
 
+	"wechat-api/ent"
+	"wechat-api/ent/custom_types"
+	"wechat-api/hook/credit"
+	"wechat-api/internal/config"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/contextkey"
 
 	openai "github.com/openai/openai-go"
 	"github.com/openai/openai-go/option"
 	"github.com/openai/openai-go/packages/ssestream"
+	"github.com/redis/go-redis/v9"
 	"github.com/zeromicro/go-zero/rest/httpx"
 )
 
+type ServiceContext struct {
+	Config config.Config
+	DB     *ent.Client
+	Rds    redis.UniversalClient
+}
+
+func AppendUsageDetailLog(ctx context.Context, svcCtx *ServiceContext,
+	authToken string, req *types.CompApiReq, resp *types.CompOpenApiResp) error {
+
+	rawReqResp := custom_types.OriginalData{Request: req, Response: resp}
+	orgId := uint64(0)
+	apiKeyObj, ok := contextkey.AuthTokenInfoKey.GetValue(ctx)
+	if ok {
+		orgId = apiKeyObj.OrganizationID
+	}
+	msgContent := getMessageContentStr(req.Messages[0].Content)
+	tx, err := svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		err = fmt.Errorf("start transaction error:%v", err)
+	} else {
+		usage := credit.Usage{
+			CompletionTokens: uint64(resp.Usage.CompletionTokens),
+			PromptTokens:     uint64(resp.Usage.PromptTokens),
+			TotalTokens:      uint64(resp.Usage.TotalTokens),
+		}
+		err = credit.AddCreditUsage(tx, ctx,
+			authToken, req.EventType, orgId,
+			&msgContent, &resp.Choices[0].Message.Content,
+			&rawReqResp, &usage, req.Model,
+		)
+		if err != nil {
+			_ = tx.Rollback()
+			err = fmt.Errorf("save credits info failed:%v", err)
+		} else {
+			_ = tx.Commit()
+		}
+	}
+	return err
+}
+
+func IsValidURL(input *string, adjust bool) bool {
+
+	// 合法域名正则(支持通配符、中文域名等场景按需调整)
+	var domainRegex = regexp.MustCompile(
+		// 多级域名(如 example.com)
+		`^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$` +
+			`|` +
+			// 单级域名(如 localhost 或 mytest-svc)
+			`^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$`,
+	)
+
+	// 空值直接返回
+	if *input == "" {
+		return false
+	}
+	inputStr := *input
+
+	// --- 预处理输入:自动补全协议 ---
+	// 若输入不包含协议头,默认添加 http://
+	if !strings.Contains(*input, "://") {
+		inputStr = "http://" + *input
+	}
+
+	// --- 解析 URL ---
+	u, err := url.Parse(inputStr)
+	if err != nil {
+		return false
+	}
+
+	// --- 校验协议 ---
+	// 只允许常见协议(按需扩展)
+	switch u.Scheme {
+	case "http", "https", "ftp", "ftps":
+	default:
+		return false
+	}
+
+	// --- 拆分 Host 和 Port ---
+	host, port, err := net.SplitHostPort(u.Host)
+	if err != nil {
+		// 无端口时,整个 Host 作为主机名
+		host = u.Host
+		port = ""
+	}
+
+	// --- 校验主机名 ---
+	// 场景1:IPv4 或 IPv6
+	if ip := net.ParseIP(host); ip != nil {
+		// 允许私有或保留 IP(按需调整)
+		// 示例中允许所有合法 IP
+	} else {
+		// 场景2:域名(包括 localhost)
+		if !domainRegex.MatchString(host) {
+			return false
+		}
+	}
+
+	// --- 校验端口 ---
+	if port != "" {
+		p, err := net.LookupPort("tcp", port) // 动态获取端口(如 "http" 对应 80)
+		if err != nil {
+			// 直接尝试解析为数字端口
+			numPort, err := strconv.Atoi(port)
+			if err != nil || numPort < 1 || numPort > 65535 {
+				return false
+			}
+		} else if p == 0 { // 动态端口为 0 时无效
+			return false
+		}
+	}
+	if adjust {
+		*input = inputStr
+	}
+	return true
+}
+
+func getMessageContentStr(input any) string {
+	str := ""
+	switch val := input.(type) {
+	case string:
+		str = val
+	case []any:
+		if len(val) > 0 {
+			if valc, ok := val[0].(map[string]any); ok {
+				if valcc, ok := valc["text"]; ok {
+					str, _ = valcc.(string)
+				}
+			}
+		}
+	}
+	return str
+}
+
+/*
+func AppendUsageDetailLog(ctx context.Context, svcCtx *ServiceContext,
+
+	authToken string, req *types.CompApiReq, resp *types.CompOpenApiResp) error {
+
+	logType := 5
+	rawReqResp := custom_types.OriginalData{Request: req, Response: resp}
+	tmpId := 0
+	tmpId, _ = strconv.Atoi(resp.ID)
+	sessionId := uint64(tmpId)
+	orgId := uint64(0)
+	apiKeyObj, ok := contextkey.AuthTokenInfoKey.GetValue(ctx)
+	if ok {
+		orgId = apiKeyObj.OrganizationID
+	}
+	promptTokens := uint64(resp.Usage.PromptTokens)
+	completionToken := uint64(resp.Usage.CompletionTokens)
+	totalTokens := promptTokens + completionToken
+
+	msgContent := getMessageContentStr(req.Messages[0].Content)
+
+	_, _, _ = logType, sessionId, totalTokens
+	res, err := svcCtx.DB.UsageDetail.Create().
+		SetNotNilType(&logType).
+		SetNotNilBotID(&authToken).
+		SetNotNilReceiverID(&req.EventType).
+		SetNotNilSessionID(&sessionId).
+		SetNillableRequest(&msgContent).
+		SetNillableResponse(&resp.Choices[0].Message.Content).
+		SetNillableOrganizationID(&orgId).
+		SetOriginalData(rawReqResp).
+		SetNillablePromptTokens(&promptTokens).
+		SetNillableCompletionTokens(&completionToken).
+		SetNillableTotalTokens(&totalTokens).
+		Save(ctx)
+
+	if err == nil { //插入UsageDetai之后再统计UsageTotal
+		updateUsageTotal(ctx, svcCtx, authToken, res.ID, orgId)
+	}
+	return err
+}
+
+func getUsagetotalIdByToken(ctx context.Context, svcCtx *ServiceContext,
+	authToken string) (uint64, error) {
+
+	var predicates []predicate.UsageTotal
+	predicates = append(predicates, usagetotal.BotIDEQ(authToken))
+	return svcCtx.DB.UsageTotal.Query().Where(predicates...).FirstID(ctx)
+
+}
+
+func replaceUsagetotalTokens(ctx context.Context, svcCtx *ServiceContext,
+
+	authToken string, sumTotalTokens uint64, newUsageDetailId uint64, orgId uint64) error {
+
+	Id, err := getUsagetotalIdByToken(ctx, svcCtx, authToken)
+	if err != nil && !ent.IsNotFound(err) {
+		return err
+	}
+	if Id > 0 { //UsageTotal have record by  newUsageDetailId
+		_, err = svcCtx.DB.UsageTotal.UpdateOneID(Id).
+			SetTotalTokens(sumTotalTokens).
+			SetEndIndex(newUsageDetailId).
+			Save(ctx)
+	} else { //create new record by  newUsageDetailId
+		logType := 5
+		_, err = svcCtx.DB.UsageTotal.Create().
+			SetNotNilBotID(&authToken).
+			SetNotNilEndIndex(&newUsageDetailId).
+			SetNotNilTotalTokens(&sumTotalTokens).
+			SetNillableType(&logType).
+			SetNotNilOrganizationID(&orgId).
+			Save(ctx)
+	}
+
+	return err
+}
+
+func updateUsageTotal(ctx context.Context, svcCtx *ServiceContext,
+	authToken string, newUsageDetailId uint64, orgId uint64) error {
+
+	sumTotalTokens, err := sumTotalTokensByAuthToken(ctx, svcCtx, authToken) //首先sum UsageDetail的TotalTokens
+	if err == nil {
+		err = replaceUsagetotalTokens(ctx, svcCtx, authToken, sumTotalTokens, newUsageDetailId, orgId) //再更新(包含新建)Usagetotal的otalTokens
+	}
+	return err
+}
+
+// sum total_tokens from usagedetail by AuthToken
+func sumTotalTokensByAuthToken(ctx context.Context, svcCtx *ServiceContext,
+	authToken string) (uint64, error) {
+
+	var predicates []predicate.UsageDetail
+	predicates = append(predicates, usagedetail.BotIDEQ(authToken))
+
+	var res []struct {
+		Sum, Min, Max, Count uint64
+	}
+	totalTokens := uint64(0)
+	var err error = nil
+	err = svcCtx.DB.UsageDetail.Query().Where(predicates...).Aggregate(ent.Sum("total_tokens"),
+		ent.Min("total_tokens"), ent.Max("total_tokens"), ent.Count()).Scan(ctx, &res)
+	if err == nil {
+		if len(res) > 0 {
+			totalTokens = res[0].Sum
+		} else {
+			totalTokens = 0
+		}
+	}
+	return totalTokens, err
+}
+*/
+
 func IsOpenaiModel(model string) bool {
 
 	prefixes := []string{"gpt-4", "gpt-3", "o1", "o3"}
@@ -30,6 +286,68 @@ func IsOpenaiModel(model string) bool {
 	return false
 }
 
+func EntStructGenScanField(structPtr any, ignoredTypes ...reflect.Type) (string, []any, error) {
+	t := reflect.TypeOf(structPtr)
+	v := reflect.ValueOf(structPtr)
+
+	if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
+		return "", nil, errors.New("input must be a pointer to a struct")
+	}
+	t = t.Elem()
+	v = v.Elem()
+
+	var fields []string
+	var scanArgs []any
+
+	ignoredMap := make(map[reflect.Type]struct{})
+	// 检查调用者是否传入了任何要忽略的类型
+	if len(ignoredTypes) > 0 {
+		for _, ignoredType := range ignoredTypes {
+			if ignoredType != nil { // 防止 nil 类型加入 map
+				ignoredMap[ignoredType] = struct{}{}
+			}
+		}
+	}
+
+	for i := 0; i < t.NumField(); i++ {
+		field := t.Field(i)
+		value := v.Field(i)
+
+		// Skip unexported fields
+		if !field.IsExported() {
+			continue
+		}
+
+		// Get json tag
+		jsonTag := field.Tag.Get("json")
+		if jsonTag == "-" || jsonTag == "" {
+			continue
+		}
+
+		jsonParts := strings.Split(jsonTag, ",")
+		jsonName := jsonParts[0]
+		if jsonName == "" {
+			continue
+		}
+
+		//传入了要忽略的类型时进行处理
+		if len(ignoredMap) > 0 {
+			fieldType := field.Type //获取字段的实际 Go 类型
+			//如果字段是指针,我们通常关心的是指针指向的元素的类型
+			if fieldType.Kind() == reflect.Ptr {
+				fieldType = fieldType.Elem() // 获取元素类型
+			}
+			if _, shouldIgnore := ignoredMap[fieldType]; shouldIgnore {
+				continue // 成员类型存在于忽略列表中则忽略
+			}
+		}
+
+		fields = append(fields, jsonName)
+		scanArgs = append(scanArgs, value.Addr().Interface())
+	}
+	return strings.Join(fields, ", "), scanArgs, nil
+}
+
 type StdChatClient struct {
 	*openai.Client
 }

+ 17 - 14
internal/utils/compapi/intent.go

@@ -11,7 +11,7 @@ type IntentClient struct {
 func (me *IntentClient) ResponseFormatSetting(req *types.CompApiReq) ResponseFormatConfig {
 
 	//Message重构的配置
-	me.ResformatConfig.SysmesArgs = []any{}
+	me.ResformatConfig.SysmesArgs = []any{} //以下SysmesTmpl内无替换占位符,所以这里为空
 	me.ResformatConfig.SysmesTmpl = `# 任务
 1. 首先,判断用户的第一句话是否说了:“你好,(任意内容)通话”,如果说了,则不用理会评级规则,直接强制分配为"语音助手"
 2. 如果不属于“语音助手”,请根据评级规则,对聊天记录给出评级、置信度、评分依据(逐项分析不要遗漏)
@@ -19,21 +19,22 @@ func (me *IntentClient) ResponseFormatSetting(req *types.CompApiReq) ResponseFor
 # 细节说明
 置信度从0到1,0为置信度最低,1为置信度最高。`
 
+	//来自请求的变量用来替换UsermesTmpl中的占位符
 	me.ResformatConfig.UsermesArgs = []any{req.Variables["chat_history"]}
 	me.ResformatConfig.UsermesTmpl = `# 评级规则:
         [
         {
             'rule': "用户表现出对产品有积极回应,询问有关产品的问题,或愿意进行后续操作,如确认微信号、询问发货地址或表达接受产品(例:'行'、'好'、'可以'、'是的')。",
-            'score': '有意向'},
+            'intent': '有意向'},
         {
             'rule': "用户虽然未积极回应或表示不需要,但却有相关需求、或着符合某项购买条件、又或着询问了机器人问题,即便后期疲软或持否定态度,可移交销售顾问进行进一步的需求分析,以便改善产品或定制符合客户要求的产品",
-            'score': '待进一步分析'},
+            'intent': '无法判定'},
         {
             'rule': "用户表示自己在忙、在开会等,现在不太方便沟通。又或者对电话的真实性存疑,怀疑是诈骗电话,可后续让专业客服继续跟进",
-            'score': '暂时无法沟通'},
+            'intent': '在忙'},
         {
-            'rule': "除上述规则外的其他用户,包括:用户未回复直接挂机、用户拒绝后直接挂机的情况。请注意客户资源珍贵,请尽量归类为'有意向'或'待进一步分析',后续再由销售专家定性。",
-            'score': '其他'}
+            'rule': "除上述规则外的其他用户,包括:用户未回复直接挂机、用户拒绝后直接挂机的情况。请注意客户资源珍贵,请尽量归类为'有意向'或'无法判定',后续再由销售专家定性。",
+            'intent': '无意向'}
     ]
 
         # 聊天记录
@@ -41,18 +42,20 @@ func (me *IntentClient) ResponseFormatSetting(req *types.CompApiReq) ResponseFor
         `
 
 	//ResponseFormat设置的配置
-	me.ResformatConfig.ResformatDesc = "为通话记录进行评级"
+	me.ResformatConfig.ResformatDesc = "为通话记录进行评级" //Resformat描述
+	//非openai兼容大模型所使用的Resformat文本
 	me.ResformatConfig.ResformatTxt = `{
-    "score": str, #评分结果:有意向、待进一步分析、暂时无法沟通、其他
-    "confidence_score": int, #置信度分数,范围从0.0到1.0
-    "scoring_criteria": str, #请逐步介绍为何评为这个结果
+    "intent": str, #评分结果:有意向、无法判定、在忙、无意向
+    "confidence": int, #置信度分数,范围从0.0到1.0
+    "reason": str, #请逐步介绍为何评为这个结果
 }`
+	//openai兼容大模型所使用的Resformat结构或其他类型
 	me.ResformatConfig.ResformatStruct = struct {
-		Score           string  `json:"score" jsonschema_description:"评分结果:有意向、待进一步分析、暂时无法沟通、其他"`
-		ConfidenceScore float32 `json:"confidence_score" jsonschema_description:"置信度分数,范围从0.0到1.0"`
-		ScoringCriteria string  `json:"scoring_criteria" jsonschema_description:"请逐步介绍为何评为这个结果"`
+		Intent     string  `json:"intent" jsonschema_description:"评分结果:有意向、无法判定、在忙、无意向"`
+		Confidence float32 `json:"confidence" jsonschema_description:"置信度分数,范围从0.0到1.0"`
+		Reason     string  `json:"reason" jsonschema_description:"请逐步介绍为何评为这个结果"`
 	}{}
-	me.ResformatConfig.HaveSet = true
+	me.ResformatConfig.HaveSet = true //很关键,避免父类的参数再设置一遍
 
 	return me.ResformatConfig
 }

Vissa filer visades inte eftersom för många filer har ändrats