Browse Source

1. 增加 sop 任务发布接口。2. 更新联系人标签时,触发 sop 任务

boweniac 11 tháng trước cách đây
mục cha
commit
16931d8e99
42 tập tin đã thay đổi với 3233 bổ sung540 xóa
  1. 3 3
      desc/wechat/label_relationship.api
  2. 3 3
      desc/wechat/message_records.api
  3. 2 2
      desc/wechat/sop_stage.api
  4. 4 0
      desc/wechat/sop_task.api
  5. 96 0
      ent/client.go
  6. 17 1
      ent/contact.go
  7. 30 0
      ent/contact/contact.go
  8. 23 0
      ent/contact/where.go
  9. 32 0
      ent/contact_create.go
  10. 75 1
      ent/contact_query.go
  11. 163 0
      ent/contact_update.go
  12. 73 6
      ent/messagerecords.go
  13. 72 2
      ent/messagerecords/messagerecords.go
  14. 105 65
      ent/messagerecords/where.go
  15. 184 86
      ent/messagerecords_create.go
  16. 240 11
      ent/messagerecords_query.go
  17. 373 88
      ent/messagerecords_update.go
  18. 27 4
      ent/migrate/schema.go
  19. 463 157
      ent/mutation.go
  20. 2 2
      ent/runtime/runtime.go
  21. 1 0
      ent/schema/contact.go
  22. 18 4
      ent/schema/message_records.go
  23. 2 1
      ent/schema/sop_node.go
  24. 2 1
      ent/schema/sop_stage.go
  25. 15 15
      ent/set_not_nil.go
  26. 18 2
      ent/sopnode.go
  27. 30 0
      ent/sopnode/sopnode.go
  28. 23 0
      ent/sopnode/where.go
  29. 37 5
      ent/sopnode_create.go
  30. 87 12
      ent/sopnode_query.go
  31. 173 10
      ent/sopnode_update.go
  32. 18 2
      ent/sopstage.go
  33. 30 0
      ent/sopstage/sopstage.go
  34. 23 0
      ent/sopstage/where.go
  35. 37 5
      ent/sopstage_create.go
  36. 88 14
      ent/sopstage_query.go
  37. 173 10
      ent/sopstage_update.go
  38. 5 0
      internal/handler/routes.go
  39. 44 0
      internal/handler/sop_task/publish_sop_task_handler.go
  40. 164 21
      internal/logic/label_relationship/update_label_relationships_logic.go
  41. 251 0
      internal/logic/sop_task/publish_sop_task_logic.go
  42. 7 7
      internal/types/types.go

+ 3 - 3
desc/wechat/label_relationship.api

@@ -113,8 +113,8 @@ type (
     LabelRelationshipsInfo {
         BaseIDInfo
 
-        // Status 1: normal 2: ban | 状态 1 正常 2 禁用
-        Status  *uint8 `json:"status,optional"`
+        // 更新类型:为空或“all”时表示全量更新,为 “add” 时表示仅追加
+        UpdateType *string `json:"updateType,optional"`
 
         // 标签 ID
         LabelIds  []uint64 `json:"labelIds,optional"`
@@ -168,7 +168,7 @@ service Wechat {
     @handler updateLabelRelationship
     post /label_relationship/update (LabelRelationshipInfo) returns (BaseMsgResp)
 
-    // Update label relationships information | 批量更新LabelRelationship
+    // Update label relationships information | 更新联系人所有 LabelRelationship
     @handler updateLabelRelationships
     post /label_relationship/update_contact_labels (LabelRelationshipsInfo) returns (BaseMsgResp)
 

+ 3 - 3
desc/wechat/message_records.api

@@ -12,7 +12,7 @@ type (
         BotWxid  *string `json:"botWxid,optional"`
 
         // 联系人 id 
-        ContactId  *int `json:"contactId,optional"`
+        ContactId  *uint64 `json:"contactId,optional"`
 
         // 类型:1好友,2群组,3企业微信联系人 
         ContactType  *int `json:"contactType,optional"`
@@ -36,10 +36,10 @@ type (
         SourceType  *int `json:"sourceType,optional"`
 
         // 源 ID 
-        SourceId  *int `json:"sourceId,optional"`
+        SourceId  *uint64 `json:"sourceId,optional"`
 
         // 次源 ID 
-        SubSourceId  *int `json:"subSourceId,optional"`
+        SubSourceId  *uint64 `json:"subSourceId,optional"`
     }
 
     // The response data of message records list | MessageRecords列表数据

+ 2 - 2
desc/wechat/sop_stage.api

@@ -27,7 +27,7 @@ type (
         ActionMessage  []Action `json:"actionMessage,optional"`
 
         // 命中后需要打的标签 
-        ActionLabel  []int `json:"actionLabel,optional"`
+        ActionLabel  []uint64 `json:"actionLabel,optional"`
 
         // 阶段顺序 
         IndexSort  *int `json:"indexSort,optional"`
@@ -94,7 +94,7 @@ type (
         ActionMessage  []Action `json:"actionMessage,optional"`
 
         // 命中后需要打的标签
-        ActionLabel  []int `json:"actionLabel,optional"`
+        ActionLabel  []uint64 `json:"actionLabel,optional"`
 
         // 阶段信息
         StageInfo  *SopStageInfo `json:"stageInfo,optional"`

+ 4 - 0
desc/wechat/sop_task.api

@@ -68,4 +68,8 @@ service Wechat {
     // Get sop task by ID | 通过ID获取SopTask详情
     @handler getSopTaskDetail
     post /sop_task/detail (IDReq) returns (SopTaskInfoResp)
+
+    // Publish sop task | 发布 SopTask
+    @handler publishSopTask
+    post /sop_task/publish (IDReq) returns (BaseMsgResp)
 }

+ 96 - 0
ent/client.go

@@ -406,6 +406,22 @@ func (c *ContactClient) QueryContactRelationships(co *Contact) *LabelRelationshi
 	return query
 }
 
+// QueryContactMessages queries the contact_messages edge of a Contact.
+func (c *ContactClient) QueryContactMessages(co *Contact) *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := co.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(contact.Table, contact.FieldID, id),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, contact.ContactMessagesTable, contact.ContactMessagesColumn),
+		)
+		fromV = sqlgraph.Neighbors(co.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
 // Hooks returns the client hooks.
 func (c *ContactClient) Hooks() []Hook {
 	hooks := c.hooks.Contact
@@ -992,6 +1008,54 @@ func (c *MessageRecordsClient) GetX(ctx context.Context, id uint64) *MessageReco
 	return obj
 }
 
+// QuerySopStage queries the sop_stage edge of a MessageRecords.
+func (c *MessageRecordsClient) QuerySopStage(mr *MessageRecords) *SopStageQuery {
+	query := (&SopStageClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := mr.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, id),
+			sqlgraph.To(sopstage.Table, sopstage.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.SopStageTable, messagerecords.SopStageColumn),
+		)
+		fromV = sqlgraph.Neighbors(mr.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// QuerySopNode queries the sop_node edge of a MessageRecords.
+func (c *MessageRecordsClient) QuerySopNode(mr *MessageRecords) *SopNodeQuery {
+	query := (&SopNodeClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := mr.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, id),
+			sqlgraph.To(sopnode.Table, sopnode.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.SopNodeTable, messagerecords.SopNodeColumn),
+		)
+		fromV = sqlgraph.Neighbors(mr.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// QueryMessageContact queries the message_contact edge of a MessageRecords.
+func (c *MessageRecordsClient) QueryMessageContact(mr *MessageRecords) *ContactQuery {
+	query := (&ContactClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := mr.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, id),
+			sqlgraph.To(contact.Table, contact.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.MessageContactTable, messagerecords.MessageContactColumn),
+		)
+		fromV = sqlgraph.Neighbors(mr.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
 // Hooks returns the client hooks.
 func (c *MessageRecordsClient) Hooks() []Hook {
 	hooks := c.hooks.MessageRecords
@@ -1294,6 +1358,22 @@ func (c *SopNodeClient) QuerySopStage(sn *SopNode) *SopStageQuery {
 	return query
 }
 
+// QueryNodeMessages queries the node_messages edge of a SopNode.
+func (c *SopNodeClient) QueryNodeMessages(sn *SopNode) *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := sn.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(sopnode.Table, sopnode.FieldID, id),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, sopnode.NodeMessagesTable, sopnode.NodeMessagesColumn),
+		)
+		fromV = sqlgraph.Neighbors(sn.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
 // Hooks returns the client hooks.
 func (c *SopNodeClient) Hooks() []Hook {
 	hooks := c.hooks.SopNode
@@ -1461,6 +1541,22 @@ func (c *SopStageClient) QueryStageNodes(ss *SopStage) *SopNodeQuery {
 	return query
 }
 
+// QueryStageMessages queries the stage_messages edge of a SopStage.
+func (c *SopStageClient) QueryStageMessages(ss *SopStage) *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := ss.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(sopstage.Table, sopstage.FieldID, id),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, sopstage.StageMessagesTable, sopstage.StageMessagesColumn),
+		)
+		fromV = sqlgraph.Neighbors(ss.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
 // Hooks returns the client hooks.
 func (c *SopStageClient) Hooks() []Hook {
 	hooks := c.hooks.SopStage

+ 17 - 1
ent/contact.go

@@ -65,9 +65,11 @@ type Contact struct {
 type ContactEdges struct {
 	// ContactRelationships holds the value of the contact_relationships edge.
 	ContactRelationships []*LabelRelationship `json:"contact_relationships,omitempty"`
+	// ContactMessages holds the value of the contact_messages edge.
+	ContactMessages []*MessageRecords `json:"contact_messages,omitempty"`
 	// loadedTypes holds the information for reporting if a
 	// type was loaded (or requested) in eager-loading or not.
-	loadedTypes [1]bool
+	loadedTypes [2]bool
 }
 
 // ContactRelationshipsOrErr returns the ContactRelationships value or an error if the edge
@@ -79,6 +81,15 @@ func (e ContactEdges) ContactRelationshipsOrErr() ([]*LabelRelationship, error)
 	return nil, &NotLoadedError{edge: "contact_relationships"}
 }
 
+// ContactMessagesOrErr returns the ContactMessages value or an error if the edge
+// was not loaded in eager-loading.
+func (e ContactEdges) ContactMessagesOrErr() ([]*MessageRecords, error) {
+	if e.loadedTypes[1] {
+		return e.ContactMessages, nil
+	}
+	return nil, &NotLoadedError{edge: "contact_messages"}
+}
+
 // scanValues returns the types for scanning values from sql.Rows.
 func (*Contact) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
@@ -243,6 +254,11 @@ func (c *Contact) QueryContactRelationships() *LabelRelationshipQuery {
 	return NewContactClient(c.config).QueryContactRelationships(c)
 }
 
+// QueryContactMessages queries the "contact_messages" edge of the Contact entity.
+func (c *Contact) QueryContactMessages() *MessageRecordsQuery {
+	return NewContactClient(c.config).QueryContactMessages(c)
+}
+
 // Update returns a builder for updating this Contact.
 // Note that you need to call Contact.Unwrap() before calling this method if this Contact
 // was returned from a transaction, and the transaction was committed or rolled back.

+ 30 - 0
ent/contact/contact.go

@@ -55,6 +55,8 @@ const (
 	FieldV3 = "v3"
 	// EdgeContactRelationships holds the string denoting the contact_relationships edge name in mutations.
 	EdgeContactRelationships = "contact_relationships"
+	// EdgeContactMessages holds the string denoting the contact_messages edge name in mutations.
+	EdgeContactMessages = "contact_messages"
 	// Table holds the table name of the contact in the database.
 	Table = "contact"
 	// ContactRelationshipsTable is the table that holds the contact_relationships relation/edge.
@@ -64,6 +66,13 @@ const (
 	ContactRelationshipsInverseTable = "label_relationship"
 	// ContactRelationshipsColumn is the table column denoting the contact_relationships relation/edge.
 	ContactRelationshipsColumn = "contact_id"
+	// ContactMessagesTable is the table that holds the contact_messages relation/edge.
+	ContactMessagesTable = "message_records"
+	// ContactMessagesInverseTable is the table name for the MessageRecords entity.
+	// It exists in this package in order to avoid circular dependency with the "messagerecords" package.
+	ContactMessagesInverseTable = "message_records"
+	// ContactMessagesColumn is the table column denoting the contact_messages relation/edge.
+	ContactMessagesColumn = "contact_id"
 )
 
 // Columns holds all SQL columns for contact fields.
@@ -264,6 +273,20 @@ func ByContactRelationships(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOpt
 		sqlgraph.OrderByNeighborTerms(s, newContactRelationshipsStep(), append([]sql.OrderTerm{term}, terms...)...)
 	}
 }
+
+// ByContactMessagesCount orders the results by contact_messages count.
+func ByContactMessagesCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newContactMessagesStep(), opts...)
+	}
+}
+
+// ByContactMessages orders the results by contact_messages terms.
+func ByContactMessages(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newContactMessagesStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
 func newContactRelationshipsStep() *sqlgraph.Step {
 	return sqlgraph.NewStep(
 		sqlgraph.From(Table, FieldID),
@@ -271,3 +294,10 @@ func newContactRelationshipsStep() *sqlgraph.Step {
 		sqlgraph.Edge(sqlgraph.O2M, false, ContactRelationshipsTable, ContactRelationshipsColumn),
 	)
 }
+func newContactMessagesStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(ContactMessagesInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, ContactMessagesTable, ContactMessagesColumn),
+	)
+}

+ 23 - 0
ent/contact/where.go

@@ -1248,6 +1248,29 @@ func HasContactRelationshipsWith(preds ...predicate.LabelRelationship) predicate
 	})
 }
 
+// HasContactMessages applies the HasEdge predicate on the "contact_messages" edge.
+func HasContactMessages() predicate.Contact {
+	return predicate.Contact(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, ContactMessagesTable, ContactMessagesColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasContactMessagesWith applies the HasEdge predicate on the "contact_messages" edge with a given conditions (other predicates).
+func HasContactMessagesWith(preds ...predicate.MessageRecords) predicate.Contact {
+	return predicate.Contact(func(s *sql.Selector) {
+		step := newContactMessagesStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
 // And groups predicates with the AND operator between them.
 func And(predicates ...predicate.Contact) predicate.Contact {
 	return predicate.Contact(sql.AndPredicates(predicates...))

+ 32 - 0
ent/contact_create.go

@@ -9,6 +9,7 @@ import (
 	"time"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
 
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
@@ -310,6 +311,21 @@ func (cc *ContactCreate) AddContactRelationships(l ...*LabelRelationship) *Conta
 	return cc.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
+func (cc *ContactCreate) AddContactMessageIDs(ids ...uint64) *ContactCreate {
+	cc.mutation.AddContactMessageIDs(ids...)
+	return cc
+}
+
+// AddContactMessages adds the "contact_messages" edges to the MessageRecords entity.
+func (cc *ContactCreate) AddContactMessages(m ...*MessageRecords) *ContactCreate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return cc.AddContactMessageIDs(ids...)
+}
+
 // Mutation returns the ContactMutation object of the builder.
 func (cc *ContactCreate) Mutation() *ContactMutation {
 	return cc.mutation
@@ -600,6 +616,22 @@ func (cc *ContactCreate) createSpec() (*Contact, *sqlgraph.CreateSpec) {
 		}
 		_spec.Edges = append(_spec.Edges, edge)
 	}
+	if nodes := cc.mutation.ContactMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
 	return _node, _spec
 }
 

+ 75 - 1
ent/contact_query.go

@@ -9,6 +9,7 @@ import (
 	"math"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 
 	"entgo.io/ent/dialect/sql"
@@ -24,6 +25,7 @@ type ContactQuery struct {
 	inters                   []Interceptor
 	predicates               []predicate.Contact
 	withContactRelationships *LabelRelationshipQuery
+	withContactMessages      *MessageRecordsQuery
 	// intermediate query (i.e. traversal path).
 	sql  *sql.Selector
 	path func(context.Context) (*sql.Selector, error)
@@ -82,6 +84,28 @@ func (cq *ContactQuery) QueryContactRelationships() *LabelRelationshipQuery {
 	return query
 }
 
+// QueryContactMessages chains the current query on the "contact_messages" edge.
+func (cq *ContactQuery) QueryContactMessages() *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: cq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := cq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := cq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(contact.Table, contact.FieldID, selector),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, contact.ContactMessagesTable, contact.ContactMessagesColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(cq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
 // First returns the first Contact entity from the query.
 // Returns a *NotFoundError when no Contact was found.
 func (cq *ContactQuery) First(ctx context.Context) (*Contact, error) {
@@ -275,6 +299,7 @@ func (cq *ContactQuery) Clone() *ContactQuery {
 		inters:                   append([]Interceptor{}, cq.inters...),
 		predicates:               append([]predicate.Contact{}, cq.predicates...),
 		withContactRelationships: cq.withContactRelationships.Clone(),
+		withContactMessages:      cq.withContactMessages.Clone(),
 		// clone intermediate query.
 		sql:  cq.sql.Clone(),
 		path: cq.path,
@@ -292,6 +317,17 @@ func (cq *ContactQuery) WithContactRelationships(opts ...func(*LabelRelationship
 	return cq
 }
 
+// WithContactMessages tells the query-builder to eager-load the nodes that are connected to
+// the "contact_messages" edge. The optional arguments are used to configure the query builder of the edge.
+func (cq *ContactQuery) WithContactMessages(opts ...func(*MessageRecordsQuery)) *ContactQuery {
+	query := (&MessageRecordsClient{config: cq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	cq.withContactMessages = query
+	return cq
+}
+
 // 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.
 //
@@ -370,8 +406,9 @@ func (cq *ContactQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Cont
 	var (
 		nodes       = []*Contact{}
 		_spec       = cq.querySpec()
-		loadedTypes = [1]bool{
+		loadedTypes = [2]bool{
 			cq.withContactRelationships != nil,
+			cq.withContactMessages != nil,
 		}
 	)
 	_spec.ScanValues = func(columns []string) ([]any, error) {
@@ -401,6 +438,13 @@ func (cq *ContactQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Cont
 			return nil, err
 		}
 	}
+	if query := cq.withContactMessages; query != nil {
+		if err := cq.loadContactMessages(ctx, query, nodes,
+			func(n *Contact) { n.Edges.ContactMessages = []*MessageRecords{} },
+			func(n *Contact, e *MessageRecords) { n.Edges.ContactMessages = append(n.Edges.ContactMessages, e) }); err != nil {
+			return nil, err
+		}
+	}
 	return nodes, nil
 }
 
@@ -434,6 +478,36 @@ func (cq *ContactQuery) loadContactRelationships(ctx context.Context, query *Lab
 	}
 	return nil
 }
+func (cq *ContactQuery) loadContactMessages(ctx context.Context, query *MessageRecordsQuery, nodes []*Contact, init func(*Contact), assign func(*Contact, *MessageRecords)) error {
+	fks := make([]driver.Value, 0, len(nodes))
+	nodeids := make(map[uint64]*Contact)
+	for i := range nodes {
+		fks = append(fks, nodes[i].ID)
+		nodeids[nodes[i].ID] = nodes[i]
+		if init != nil {
+			init(nodes[i])
+		}
+	}
+	if len(query.ctx.Fields) > 0 {
+		query.ctx.AppendFieldOnce(messagerecords.FieldContactID)
+	}
+	query.Where(predicate.MessageRecords(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(contact.ContactMessagesColumn), fks...))
+	}))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		fk := n.ContactID
+		node, ok := nodeids[fk]
+		if !ok {
+			return fmt.Errorf(`unexpected referenced foreign-key "contact_id" returned %v for node %v`, fk, n.ID)
+		}
+		assign(node, n)
+	}
+	return nil
+}
 
 func (cq *ContactQuery) sqlCount(ctx context.Context) (int, error) {
 	_spec := cq.querySpec()

+ 163 - 0
ent/contact_update.go

@@ -9,6 +9,7 @@ import (
 	"time"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 
 	"entgo.io/ent/dialect/sql"
@@ -347,6 +348,21 @@ func (cu *ContactUpdate) AddContactRelationships(l ...*LabelRelationship) *Conta
 	return cu.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
+func (cu *ContactUpdate) AddContactMessageIDs(ids ...uint64) *ContactUpdate {
+	cu.mutation.AddContactMessageIDs(ids...)
+	return cu
+}
+
+// AddContactMessages adds the "contact_messages" edges to the MessageRecords entity.
+func (cu *ContactUpdate) AddContactMessages(m ...*MessageRecords) *ContactUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return cu.AddContactMessageIDs(ids...)
+}
+
 // Mutation returns the ContactMutation object of the builder.
 func (cu *ContactUpdate) Mutation() *ContactMutation {
 	return cu.mutation
@@ -373,6 +389,27 @@ func (cu *ContactUpdate) RemoveContactRelationships(l ...*LabelRelationship) *Co
 	return cu.RemoveContactRelationshipIDs(ids...)
 }
 
+// ClearContactMessages clears all "contact_messages" edges to the MessageRecords entity.
+func (cu *ContactUpdate) ClearContactMessages() *ContactUpdate {
+	cu.mutation.ClearContactMessages()
+	return cu
+}
+
+// RemoveContactMessageIDs removes the "contact_messages" edge to MessageRecords entities by IDs.
+func (cu *ContactUpdate) RemoveContactMessageIDs(ids ...uint64) *ContactUpdate {
+	cu.mutation.RemoveContactMessageIDs(ids...)
+	return cu
+}
+
+// RemoveContactMessages removes "contact_messages" edges to MessageRecords entities.
+func (cu *ContactUpdate) RemoveContactMessages(m ...*MessageRecords) *ContactUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return cu.RemoveContactMessageIDs(ids...)
+}
+
 // Save executes the query and returns the number of nodes affected by the update operation.
 func (cu *ContactUpdate) Save(ctx context.Context) (int, error) {
 	if err := cu.defaults(); err != nil {
@@ -550,6 +587,51 @@ func (cu *ContactUpdate) sqlSave(ctx context.Context) (n int, err error) {
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if cu.mutation.ContactMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cu.mutation.RemovedContactMessagesIDs(); len(nodes) > 0 && !cu.mutation.ContactMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cu.mutation.ContactMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, _spec); err != nil {
 		if _, ok := err.(*sqlgraph.NotFoundError); ok {
 			err = &NotFoundError{contact.Label}
@@ -888,6 +970,21 @@ func (cuo *ContactUpdateOne) AddContactRelationships(l ...*LabelRelationship) *C
 	return cuo.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
+func (cuo *ContactUpdateOne) AddContactMessageIDs(ids ...uint64) *ContactUpdateOne {
+	cuo.mutation.AddContactMessageIDs(ids...)
+	return cuo
+}
+
+// AddContactMessages adds the "contact_messages" edges to the MessageRecords entity.
+func (cuo *ContactUpdateOne) AddContactMessages(m ...*MessageRecords) *ContactUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return cuo.AddContactMessageIDs(ids...)
+}
+
 // Mutation returns the ContactMutation object of the builder.
 func (cuo *ContactUpdateOne) Mutation() *ContactMutation {
 	return cuo.mutation
@@ -914,6 +1011,27 @@ func (cuo *ContactUpdateOne) RemoveContactRelationships(l ...*LabelRelationship)
 	return cuo.RemoveContactRelationshipIDs(ids...)
 }
 
+// ClearContactMessages clears all "contact_messages" edges to the MessageRecords entity.
+func (cuo *ContactUpdateOne) ClearContactMessages() *ContactUpdateOne {
+	cuo.mutation.ClearContactMessages()
+	return cuo
+}
+
+// RemoveContactMessageIDs removes the "contact_messages" edge to MessageRecords entities by IDs.
+func (cuo *ContactUpdateOne) RemoveContactMessageIDs(ids ...uint64) *ContactUpdateOne {
+	cuo.mutation.RemoveContactMessageIDs(ids...)
+	return cuo
+}
+
+// RemoveContactMessages removes "contact_messages" edges to MessageRecords entities.
+func (cuo *ContactUpdateOne) RemoveContactMessages(m ...*MessageRecords) *ContactUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return cuo.RemoveContactMessageIDs(ids...)
+}
+
 // Where appends a list predicates to the ContactUpdate builder.
 func (cuo *ContactUpdateOne) Where(ps ...predicate.Contact) *ContactUpdateOne {
 	cuo.mutation.Where(ps...)
@@ -1121,6 +1239,51 @@ func (cuo *ContactUpdateOne) sqlSave(ctx context.Context) (_node *Contact, err e
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if cuo.mutation.ContactMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cuo.mutation.RemovedContactMessagesIDs(); len(nodes) > 0 && !cuo.mutation.ContactMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cuo.mutation.ContactMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactMessagesTable,
+			Columns: []string{contact.ContactMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	_node = &Contact{config: cuo.config}
 	_spec.Assign = _node.assignValues
 	_spec.ScanValues = _node.scanValues

+ 73 - 6
ent/messagerecords.go

@@ -6,7 +6,10 @@ import (
 	"fmt"
 	"strings"
 	"time"
+	"wechat-api/ent/contact"
 	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/sopnode"
+	"wechat-api/ent/sopstage"
 
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/sql"
@@ -28,7 +31,7 @@ type MessageRecords struct {
 	// 机器人微信 id
 	BotWxid string `json:"bot_wxid,omitempty"`
 	// 联系人 id
-	ContactID int `json:"contact_id,omitempty"`
+	ContactID uint64 `json:"contact_id,omitempty"`
 	// 类型:1好友,2群组,3企业微信联系人
 	ContactType int `json:"contact_type,omitempty"`
 	// 接收方微信 id
@@ -44,12 +47,61 @@ type MessageRecords struct {
 	// 源类型 1 点发 2 群发 3 SOP
 	SourceType int `json:"source_type,omitempty"`
 	// 源 ID
-	SourceID int `json:"source_id,omitempty"`
+	SourceID uint64 `json:"source_id,omitempty"`
 	// 次源 ID
-	SubSourceID  int `json:"sub_source_id,omitempty"`
+	SubSourceID uint64 `json:"sub_source_id,omitempty"`
+	// Edges holds the relations/edges for other nodes in the graph.
+	// The values are being populated by the MessageRecordsQuery when eager-loading is set.
+	Edges        MessageRecordsEdges `json:"edges"`
 	selectValues sql.SelectValues
 }
 
+// MessageRecordsEdges holds the relations/edges for other nodes in the graph.
+type MessageRecordsEdges struct {
+	// SopStage holds the value of the sop_stage edge.
+	SopStage *SopStage `json:"sop_stage,omitempty"`
+	// SopNode holds the value of the sop_node edge.
+	SopNode *SopNode `json:"sop_node,omitempty"`
+	// MessageContact holds the value of the message_contact edge.
+	MessageContact *Contact `json:"message_contact,omitempty"`
+	// loadedTypes holds the information for reporting if a
+	// type was loaded (or requested) in eager-loading or not.
+	loadedTypes [3]bool
+}
+
+// SopStageOrErr returns the SopStage value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e MessageRecordsEdges) SopStageOrErr() (*SopStage, error) {
+	if e.SopStage != nil {
+		return e.SopStage, nil
+	} else if e.loadedTypes[0] {
+		return nil, &NotFoundError{label: sopstage.Label}
+	}
+	return nil, &NotLoadedError{edge: "sop_stage"}
+}
+
+// SopNodeOrErr returns the SopNode value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e MessageRecordsEdges) SopNodeOrErr() (*SopNode, error) {
+	if e.SopNode != nil {
+		return e.SopNode, nil
+	} else if e.loadedTypes[1] {
+		return nil, &NotFoundError{label: sopnode.Label}
+	}
+	return nil, &NotLoadedError{edge: "sop_node"}
+}
+
+// MessageContactOrErr returns the MessageContact value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e MessageRecordsEdges) MessageContactOrErr() (*Contact, error) {
+	if e.MessageContact != nil {
+		return e.MessageContact, nil
+	} else if e.loadedTypes[2] {
+		return nil, &NotFoundError{label: contact.Label}
+	}
+	return nil, &NotLoadedError{edge: "message_contact"}
+}
+
 // scanValues returns the types for scanning values from sql.Rows.
 func (*MessageRecords) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
@@ -116,7 +168,7 @@ func (mr *MessageRecords) assignValues(columns []string, values []any) error {
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field contact_id", values[i])
 			} else if value.Valid {
-				mr.ContactID = int(value.Int64)
+				mr.ContactID = uint64(value.Int64)
 			}
 		case messagerecords.FieldContactType:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
@@ -164,13 +216,13 @@ func (mr *MessageRecords) assignValues(columns []string, values []any) error {
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field source_id", values[i])
 			} else if value.Valid {
-				mr.SourceID = int(value.Int64)
+				mr.SourceID = uint64(value.Int64)
 			}
 		case messagerecords.FieldSubSourceID:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field sub_source_id", values[i])
 			} else if value.Valid {
-				mr.SubSourceID = int(value.Int64)
+				mr.SubSourceID = uint64(value.Int64)
 			}
 		default:
 			mr.selectValues.Set(columns[i], values[i])
@@ -185,6 +237,21 @@ func (mr *MessageRecords) Value(name string) (ent.Value, error) {
 	return mr.selectValues.Get(name)
 }
 
+// QuerySopStage queries the "sop_stage" edge of the MessageRecords entity.
+func (mr *MessageRecords) QuerySopStage() *SopStageQuery {
+	return NewMessageRecordsClient(mr.config).QuerySopStage(mr)
+}
+
+// QuerySopNode queries the "sop_node" edge of the MessageRecords entity.
+func (mr *MessageRecords) QuerySopNode() *SopNodeQuery {
+	return NewMessageRecordsClient(mr.config).QuerySopNode(mr)
+}
+
+// QueryMessageContact queries the "message_contact" edge of the MessageRecords entity.
+func (mr *MessageRecords) QueryMessageContact() *ContactQuery {
+	return NewMessageRecordsClient(mr.config).QueryMessageContact(mr)
+}
+
 // Update returns a builder for updating this MessageRecords.
 // Note that you need to call MessageRecords.Unwrap() before calling this method if this MessageRecords
 // was returned from a transaction, and the transaction was committed or rolled back.

+ 72 - 2
ent/messagerecords/messagerecords.go

@@ -7,6 +7,7 @@ import (
 
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
 )
 
 const (
@@ -44,8 +45,35 @@ const (
 	FieldSourceID = "source_id"
 	// FieldSubSourceID holds the string denoting the sub_source_id field in the database.
 	FieldSubSourceID = "sub_source_id"
+	// EdgeSopStage holds the string denoting the sop_stage edge name in mutations.
+	EdgeSopStage = "sop_stage"
+	// EdgeSopNode holds the string denoting the sop_node edge name in mutations.
+	EdgeSopNode = "sop_node"
+	// EdgeMessageContact holds the string denoting the message_contact edge name in mutations.
+	EdgeMessageContact = "message_contact"
 	// Table holds the table name of the messagerecords in the database.
 	Table = "message_records"
+	// SopStageTable is the table that holds the sop_stage relation/edge.
+	SopStageTable = "message_records"
+	// SopStageInverseTable is the table name for the SopStage entity.
+	// It exists in this package in order to avoid circular dependency with the "sopstage" package.
+	SopStageInverseTable = "sop_stage"
+	// SopStageColumn is the table column denoting the sop_stage relation/edge.
+	SopStageColumn = "source_id"
+	// SopNodeTable is the table that holds the sop_node relation/edge.
+	SopNodeTable = "message_records"
+	// SopNodeInverseTable is the table name for the SopNode entity.
+	// It exists in this package in order to avoid circular dependency with the "sopnode" package.
+	SopNodeInverseTable = "sop_node"
+	// SopNodeColumn is the table column denoting the sop_node relation/edge.
+	SopNodeColumn = "sub_source_id"
+	// MessageContactTable is the table that holds the message_contact relation/edge.
+	MessageContactTable = "message_records"
+	// MessageContactInverseTable is the table name for the Contact entity.
+	// It exists in this package in order to avoid circular dependency with the "contact" package.
+	MessageContactInverseTable = "contact"
+	// MessageContactColumn is the table column denoting the message_contact relation/edge.
+	MessageContactColumn = "contact_id"
 )
 
 // Columns holds all SQL columns for messagerecords fields.
@@ -107,9 +135,9 @@ var (
 	// DefaultSourceType holds the default value on creation for the "source_type" field.
 	DefaultSourceType int
 	// DefaultSourceID holds the default value on creation for the "source_id" field.
-	DefaultSourceID int
+	DefaultSourceID uint64
 	// DefaultSubSourceID holds the default value on creation for the "sub_source_id" field.
-	DefaultSubSourceID int
+	DefaultSubSourceID uint64
 )
 
 // OrderOption defines the ordering options for the MessageRecords queries.
@@ -194,3 +222,45 @@ func BySourceID(opts ...sql.OrderTermOption) OrderOption {
 func BySubSourceID(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldSubSourceID, opts...).ToFunc()
 }
+
+// BySopStageField orders the results by sop_stage field.
+func BySopStageField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newSopStageStep(), sql.OrderByField(field, opts...))
+	}
+}
+
+// BySopNodeField orders the results by sop_node field.
+func BySopNodeField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newSopNodeStep(), sql.OrderByField(field, opts...))
+	}
+}
+
+// ByMessageContactField orders the results by message_contact field.
+func ByMessageContactField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newMessageContactStep(), sql.OrderByField(field, opts...))
+	}
+}
+func newSopStageStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(SopStageInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, SopStageTable, SopStageColumn),
+	)
+}
+func newSopNodeStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(SopNodeInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, SopNodeTable, SopNodeColumn),
+	)
+}
+func newMessageContactStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(MessageContactInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, MessageContactTable, MessageContactColumn),
+	)
+}

+ 105 - 65
ent/messagerecords/where.go

@@ -7,6 +7,7 @@ import (
 	"wechat-api/ent/predicate"
 
 	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
 )
 
 // ID filters vertices based on their ID field.
@@ -80,7 +81,7 @@ func BotWxid(v string) predicate.MessageRecords {
 }
 
 // ContactID applies equality check predicate on the "contact_id" field. It's identical to ContactIDEQ.
-func ContactID(v int) predicate.MessageRecords {
+func ContactID(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldContactID, v))
 }
 
@@ -120,12 +121,12 @@ func SourceType(v int) predicate.MessageRecords {
 }
 
 // SourceID applies equality check predicate on the "source_id" field. It's identical to SourceIDEQ.
-func SourceID(v int) predicate.MessageRecords {
+func SourceID(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldSourceID, v))
 }
 
 // SubSourceID applies equality check predicate on the "sub_source_id" field. It's identical to SubSourceIDEQ.
-func SubSourceID(v int) predicate.MessageRecords {
+func SubSourceID(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldSubSourceID, v))
 }
 
@@ -375,43 +376,33 @@ func BotWxidContainsFold(v string) predicate.MessageRecords {
 }
 
 // ContactIDEQ applies the EQ predicate on the "contact_id" field.
-func ContactIDEQ(v int) predicate.MessageRecords {
+func ContactIDEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldContactID, v))
 }
 
 // ContactIDNEQ applies the NEQ predicate on the "contact_id" field.
-func ContactIDNEQ(v int) predicate.MessageRecords {
+func ContactIDNEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNEQ(FieldContactID, v))
 }
 
 // ContactIDIn applies the In predicate on the "contact_id" field.
-func ContactIDIn(vs ...int) predicate.MessageRecords {
+func ContactIDIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldIn(FieldContactID, vs...))
 }
 
 // ContactIDNotIn applies the NotIn predicate on the "contact_id" field.
-func ContactIDNotIn(vs ...int) predicate.MessageRecords {
+func ContactIDNotIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNotIn(FieldContactID, vs...))
 }
 
-// ContactIDGT applies the GT predicate on the "contact_id" field.
-func ContactIDGT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGT(FieldContactID, v))
+// ContactIDIsNil applies the IsNil predicate on the "contact_id" field.
+func ContactIDIsNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldIsNull(FieldContactID))
 }
 
-// ContactIDGTE applies the GTE predicate on the "contact_id" field.
-func ContactIDGTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGTE(FieldContactID, v))
-}
-
-// ContactIDLT applies the LT predicate on the "contact_id" field.
-func ContactIDLT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLT(FieldContactID, v))
-}
-
-// ContactIDLTE applies the LTE predicate on the "contact_id" field.
-func ContactIDLTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLTE(FieldContactID, v))
+// ContactIDNotNil applies the NotNil predicate on the "contact_id" field.
+func ContactIDNotNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldNotNull(FieldContactID))
 }
 
 // ContactTypeEQ applies the EQ predicate on the "contact_type" field.
@@ -780,83 +771,132 @@ func SourceTypeLTE(v int) predicate.MessageRecords {
 }
 
 // SourceIDEQ applies the EQ predicate on the "source_id" field.
-func SourceIDEQ(v int) predicate.MessageRecords {
+func SourceIDEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldSourceID, v))
 }
 
 // SourceIDNEQ applies the NEQ predicate on the "source_id" field.
-func SourceIDNEQ(v int) predicate.MessageRecords {
+func SourceIDNEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNEQ(FieldSourceID, v))
 }
 
 // SourceIDIn applies the In predicate on the "source_id" field.
-func SourceIDIn(vs ...int) predicate.MessageRecords {
+func SourceIDIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldIn(FieldSourceID, vs...))
 }
 
 // SourceIDNotIn applies the NotIn predicate on the "source_id" field.
-func SourceIDNotIn(vs ...int) predicate.MessageRecords {
+func SourceIDNotIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNotIn(FieldSourceID, vs...))
 }
 
-// SourceIDGT applies the GT predicate on the "source_id" field.
-func SourceIDGT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGT(FieldSourceID, v))
-}
-
-// SourceIDGTE applies the GTE predicate on the "source_id" field.
-func SourceIDGTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGTE(FieldSourceID, v))
-}
-
-// SourceIDLT applies the LT predicate on the "source_id" field.
-func SourceIDLT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLT(FieldSourceID, v))
+// SourceIDIsNil applies the IsNil predicate on the "source_id" field.
+func SourceIDIsNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldIsNull(FieldSourceID))
 }
 
-// SourceIDLTE applies the LTE predicate on the "source_id" field.
-func SourceIDLTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLTE(FieldSourceID, v))
+// SourceIDNotNil applies the NotNil predicate on the "source_id" field.
+func SourceIDNotNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldNotNull(FieldSourceID))
 }
 
 // SubSourceIDEQ applies the EQ predicate on the "sub_source_id" field.
-func SubSourceIDEQ(v int) predicate.MessageRecords {
+func SubSourceIDEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldEQ(FieldSubSourceID, v))
 }
 
 // SubSourceIDNEQ applies the NEQ predicate on the "sub_source_id" field.
-func SubSourceIDNEQ(v int) predicate.MessageRecords {
+func SubSourceIDNEQ(v uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNEQ(FieldSubSourceID, v))
 }
 
 // SubSourceIDIn applies the In predicate on the "sub_source_id" field.
-func SubSourceIDIn(vs ...int) predicate.MessageRecords {
+func SubSourceIDIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldIn(FieldSubSourceID, vs...))
 }
 
 // SubSourceIDNotIn applies the NotIn predicate on the "sub_source_id" field.
-func SubSourceIDNotIn(vs ...int) predicate.MessageRecords {
+func SubSourceIDNotIn(vs ...uint64) predicate.MessageRecords {
 	return predicate.MessageRecords(sql.FieldNotIn(FieldSubSourceID, vs...))
 }
 
-// SubSourceIDGT applies the GT predicate on the "sub_source_id" field.
-func SubSourceIDGT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGT(FieldSubSourceID, v))
-}
-
-// SubSourceIDGTE applies the GTE predicate on the "sub_source_id" field.
-func SubSourceIDGTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldGTE(FieldSubSourceID, v))
-}
-
-// SubSourceIDLT applies the LT predicate on the "sub_source_id" field.
-func SubSourceIDLT(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLT(FieldSubSourceID, v))
-}
-
-// SubSourceIDLTE applies the LTE predicate on the "sub_source_id" field.
-func SubSourceIDLTE(v int) predicate.MessageRecords {
-	return predicate.MessageRecords(sql.FieldLTE(FieldSubSourceID, v))
+// SubSourceIDIsNil applies the IsNil predicate on the "sub_source_id" field.
+func SubSourceIDIsNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldIsNull(FieldSubSourceID))
+}
+
+// SubSourceIDNotNil applies the NotNil predicate on the "sub_source_id" field.
+func SubSourceIDNotNil() predicate.MessageRecords {
+	return predicate.MessageRecords(sql.FieldNotNull(FieldSubSourceID))
+}
+
+// HasSopStage applies the HasEdge predicate on the "sop_stage" edge.
+func HasSopStage() predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, SopStageTable, SopStageColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasSopStageWith applies the HasEdge predicate on the "sop_stage" edge with a given conditions (other predicates).
+func HasSopStageWith(preds ...predicate.SopStage) predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := newSopStageStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// HasSopNode applies the HasEdge predicate on the "sop_node" edge.
+func HasSopNode() predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, SopNodeTable, SopNodeColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasSopNodeWith applies the HasEdge predicate on the "sop_node" edge with a given conditions (other predicates).
+func HasSopNodeWith(preds ...predicate.SopNode) predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := newSopNodeStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// HasMessageContact applies the HasEdge predicate on the "message_contact" edge.
+func HasMessageContact() predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, MessageContactTable, MessageContactColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasMessageContactWith applies the HasEdge predicate on the "message_contact" edge with a given conditions (other predicates).
+func HasMessageContactWith(preds ...predicate.Contact) predicate.MessageRecords {
+	return predicate.MessageRecords(func(s *sql.Selector) {
+		step := newMessageContactStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
 }
 
 // And groups predicates with the AND operator between them.

+ 184 - 86
ent/messagerecords_create.go

@@ -7,7 +7,10 @@ import (
 	"errors"
 	"fmt"
 	"time"
+	"wechat-api/ent/contact"
 	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/sopnode"
+	"wechat-api/ent/sopstage"
 
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
@@ -85,8 +88,16 @@ func (mrc *MessageRecordsCreate) SetBotWxid(s string) *MessageRecordsCreate {
 }
 
 // SetContactID sets the "contact_id" field.
-func (mrc *MessageRecordsCreate) SetContactID(i int) *MessageRecordsCreate {
-	mrc.mutation.SetContactID(i)
+func (mrc *MessageRecordsCreate) SetContactID(u uint64) *MessageRecordsCreate {
+	mrc.mutation.SetContactID(u)
+	return mrc
+}
+
+// SetNillableContactID sets the "contact_id" field if the given value is not nil.
+func (mrc *MessageRecordsCreate) SetNillableContactID(u *uint64) *MessageRecordsCreate {
+	if u != nil {
+		mrc.SetContactID(*u)
+	}
 	return mrc
 }
 
@@ -189,29 +200,29 @@ func (mrc *MessageRecordsCreate) SetNillableSourceType(i *int) *MessageRecordsCr
 }
 
 // SetSourceID sets the "source_id" field.
-func (mrc *MessageRecordsCreate) SetSourceID(i int) *MessageRecordsCreate {
-	mrc.mutation.SetSourceID(i)
+func (mrc *MessageRecordsCreate) SetSourceID(u uint64) *MessageRecordsCreate {
+	mrc.mutation.SetSourceID(u)
 	return mrc
 }
 
 // SetNillableSourceID sets the "source_id" field if the given value is not nil.
-func (mrc *MessageRecordsCreate) SetNillableSourceID(i *int) *MessageRecordsCreate {
-	if i != nil {
-		mrc.SetSourceID(*i)
+func (mrc *MessageRecordsCreate) SetNillableSourceID(u *uint64) *MessageRecordsCreate {
+	if u != nil {
+		mrc.SetSourceID(*u)
 	}
 	return mrc
 }
 
 // SetSubSourceID sets the "sub_source_id" field.
-func (mrc *MessageRecordsCreate) SetSubSourceID(i int) *MessageRecordsCreate {
-	mrc.mutation.SetSubSourceID(i)
+func (mrc *MessageRecordsCreate) SetSubSourceID(u uint64) *MessageRecordsCreate {
+	mrc.mutation.SetSubSourceID(u)
 	return mrc
 }
 
 // SetNillableSubSourceID sets the "sub_source_id" field if the given value is not nil.
-func (mrc *MessageRecordsCreate) SetNillableSubSourceID(i *int) *MessageRecordsCreate {
-	if i != nil {
-		mrc.SetSubSourceID(*i)
+func (mrc *MessageRecordsCreate) SetNillableSubSourceID(u *uint64) *MessageRecordsCreate {
+	if u != nil {
+		mrc.SetSubSourceID(*u)
 	}
 	return mrc
 }
@@ -222,6 +233,63 @@ func (mrc *MessageRecordsCreate) SetID(u uint64) *MessageRecordsCreate {
 	return mrc
 }
 
+// SetSopStageID sets the "sop_stage" edge to the SopStage entity by ID.
+func (mrc *MessageRecordsCreate) SetSopStageID(id uint64) *MessageRecordsCreate {
+	mrc.mutation.SetSopStageID(id)
+	return mrc
+}
+
+// SetNillableSopStageID sets the "sop_stage" edge to the SopStage entity by ID if the given value is not nil.
+func (mrc *MessageRecordsCreate) SetNillableSopStageID(id *uint64) *MessageRecordsCreate {
+	if id != nil {
+		mrc = mrc.SetSopStageID(*id)
+	}
+	return mrc
+}
+
+// SetSopStage sets the "sop_stage" edge to the SopStage entity.
+func (mrc *MessageRecordsCreate) SetSopStage(s *SopStage) *MessageRecordsCreate {
+	return mrc.SetSopStageID(s.ID)
+}
+
+// SetSopNodeID sets the "sop_node" edge to the SopNode entity by ID.
+func (mrc *MessageRecordsCreate) SetSopNodeID(id uint64) *MessageRecordsCreate {
+	mrc.mutation.SetSopNodeID(id)
+	return mrc
+}
+
+// SetNillableSopNodeID sets the "sop_node" edge to the SopNode entity by ID if the given value is not nil.
+func (mrc *MessageRecordsCreate) SetNillableSopNodeID(id *uint64) *MessageRecordsCreate {
+	if id != nil {
+		mrc = mrc.SetSopNodeID(*id)
+	}
+	return mrc
+}
+
+// SetSopNode sets the "sop_node" edge to the SopNode entity.
+func (mrc *MessageRecordsCreate) SetSopNode(s *SopNode) *MessageRecordsCreate {
+	return mrc.SetSopNodeID(s.ID)
+}
+
+// SetMessageContactID sets the "message_contact" edge to the Contact entity by ID.
+func (mrc *MessageRecordsCreate) SetMessageContactID(id uint64) *MessageRecordsCreate {
+	mrc.mutation.SetMessageContactID(id)
+	return mrc
+}
+
+// SetNillableMessageContactID sets the "message_contact" edge to the Contact entity by ID if the given value is not nil.
+func (mrc *MessageRecordsCreate) SetNillableMessageContactID(id *uint64) *MessageRecordsCreate {
+	if id != nil {
+		mrc = mrc.SetMessageContactID(*id)
+	}
+	return mrc
+}
+
+// SetMessageContact sets the "message_contact" edge to the Contact entity.
+func (mrc *MessageRecordsCreate) SetMessageContact(c *Contact) *MessageRecordsCreate {
+	return mrc.SetMessageContactID(c.ID)
+}
+
 // Mutation returns the MessageRecordsMutation object of the builder.
 func (mrc *MessageRecordsCreate) Mutation() *MessageRecordsMutation {
 	return mrc.mutation
@@ -323,9 +391,6 @@ func (mrc *MessageRecordsCreate) check() error {
 	if _, ok := mrc.mutation.BotWxid(); !ok {
 		return &ValidationError{Name: "bot_wxid", err: errors.New(`ent: missing required field "MessageRecords.bot_wxid"`)}
 	}
-	if _, ok := mrc.mutation.ContactID(); !ok {
-		return &ValidationError{Name: "contact_id", err: errors.New(`ent: missing required field "MessageRecords.contact_id"`)}
-	}
 	if _, ok := mrc.mutation.ContactType(); !ok {
 		return &ValidationError{Name: "contact_type", err: errors.New(`ent: missing required field "MessageRecords.contact_type"`)}
 	}
@@ -344,12 +409,6 @@ func (mrc *MessageRecordsCreate) check() error {
 	if _, ok := mrc.mutation.SourceType(); !ok {
 		return &ValidationError{Name: "source_type", err: errors.New(`ent: missing required field "MessageRecords.source_type"`)}
 	}
-	if _, ok := mrc.mutation.SourceID(); !ok {
-		return &ValidationError{Name: "source_id", err: errors.New(`ent: missing required field "MessageRecords.source_id"`)}
-	}
-	if _, ok := mrc.mutation.SubSourceID(); !ok {
-		return &ValidationError{Name: "sub_source_id", err: errors.New(`ent: missing required field "MessageRecords.sub_source_id"`)}
-	}
 	return nil
 }
 
@@ -403,10 +462,6 @@ func (mrc *MessageRecordsCreate) createSpec() (*MessageRecords, *sqlgraph.Create
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 		_node.BotWxid = value
 	}
-	if value, ok := mrc.mutation.ContactID(); ok {
-		_spec.SetField(messagerecords.FieldContactID, field.TypeInt, value)
-		_node.ContactID = value
-	}
 	if value, ok := mrc.mutation.ContactType(); ok {
 		_spec.SetField(messagerecords.FieldContactType, field.TypeInt, value)
 		_node.ContactType = value
@@ -435,13 +490,56 @@ func (mrc *MessageRecordsCreate) createSpec() (*MessageRecords, *sqlgraph.Create
 		_spec.SetField(messagerecords.FieldSourceType, field.TypeInt, value)
 		_node.SourceType = value
 	}
-	if value, ok := mrc.mutation.SourceID(); ok {
-		_spec.SetField(messagerecords.FieldSourceID, field.TypeInt, value)
-		_node.SourceID = value
-	}
-	if value, ok := mrc.mutation.SubSourceID(); ok {
-		_spec.SetField(messagerecords.FieldSubSourceID, field.TypeInt, value)
-		_node.SubSourceID = value
+	if nodes := mrc.mutation.SopStageIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopStageTable,
+			Columns: []string{messagerecords.SopStageColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopstage.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_node.SourceID = nodes[0]
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	if nodes := mrc.mutation.SopNodeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopNodeTable,
+			Columns: []string{messagerecords.SopNodeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopnode.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_node.SubSourceID = nodes[0]
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	if nodes := mrc.mutation.MessageContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.MessageContactTable,
+			Columns: []string{messagerecords.MessageContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_node.ContactID = nodes[0]
+		_spec.Edges = append(_spec.Edges, edge)
 	}
 	return _node, _spec
 }
@@ -562,7 +660,7 @@ func (u *MessageRecordsUpsert) UpdateBotWxid() *MessageRecordsUpsert {
 }
 
 // SetContactID sets the "contact_id" field.
-func (u *MessageRecordsUpsert) SetContactID(v int) *MessageRecordsUpsert {
+func (u *MessageRecordsUpsert) SetContactID(v uint64) *MessageRecordsUpsert {
 	u.Set(messagerecords.FieldContactID, v)
 	return u
 }
@@ -573,9 +671,9 @@ func (u *MessageRecordsUpsert) UpdateContactID() *MessageRecordsUpsert {
 	return u
 }
 
-// AddContactID adds v to the "contact_id" field.
-func (u *MessageRecordsUpsert) AddContactID(v int) *MessageRecordsUpsert {
-	u.Add(messagerecords.FieldContactID, v)
+// ClearContactID clears the value of the "contact_id" field.
+func (u *MessageRecordsUpsert) ClearContactID() *MessageRecordsUpsert {
+	u.SetNull(messagerecords.FieldContactID)
 	return u
 }
 
@@ -688,7 +786,7 @@ func (u *MessageRecordsUpsert) AddSourceType(v int) *MessageRecordsUpsert {
 }
 
 // SetSourceID sets the "source_id" field.
-func (u *MessageRecordsUpsert) SetSourceID(v int) *MessageRecordsUpsert {
+func (u *MessageRecordsUpsert) SetSourceID(v uint64) *MessageRecordsUpsert {
 	u.Set(messagerecords.FieldSourceID, v)
 	return u
 }
@@ -699,14 +797,14 @@ func (u *MessageRecordsUpsert) UpdateSourceID() *MessageRecordsUpsert {
 	return u
 }
 
-// AddSourceID adds v to the "source_id" field.
-func (u *MessageRecordsUpsert) AddSourceID(v int) *MessageRecordsUpsert {
-	u.Add(messagerecords.FieldSourceID, v)
+// ClearSourceID clears the value of the "source_id" field.
+func (u *MessageRecordsUpsert) ClearSourceID() *MessageRecordsUpsert {
+	u.SetNull(messagerecords.FieldSourceID)
 	return u
 }
 
 // SetSubSourceID sets the "sub_source_id" field.
-func (u *MessageRecordsUpsert) SetSubSourceID(v int) *MessageRecordsUpsert {
+func (u *MessageRecordsUpsert) SetSubSourceID(v uint64) *MessageRecordsUpsert {
 	u.Set(messagerecords.FieldSubSourceID, v)
 	return u
 }
@@ -717,9 +815,9 @@ func (u *MessageRecordsUpsert) UpdateSubSourceID() *MessageRecordsUpsert {
 	return u
 }
 
-// AddSubSourceID adds v to the "sub_source_id" field.
-func (u *MessageRecordsUpsert) AddSubSourceID(v int) *MessageRecordsUpsert {
-	u.Add(messagerecords.FieldSubSourceID, v)
+// ClearSubSourceID clears the value of the "sub_source_id" field.
+func (u *MessageRecordsUpsert) ClearSubSourceID() *MessageRecordsUpsert {
+	u.SetNull(messagerecords.FieldSubSourceID)
 	return u
 }
 
@@ -852,23 +950,23 @@ func (u *MessageRecordsUpsertOne) UpdateBotWxid() *MessageRecordsUpsertOne {
 }
 
 // SetContactID sets the "contact_id" field.
-func (u *MessageRecordsUpsertOne) SetContactID(v int) *MessageRecordsUpsertOne {
+func (u *MessageRecordsUpsertOne) SetContactID(v uint64) *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
 		s.SetContactID(v)
 	})
 }
 
-// AddContactID adds v to the "contact_id" field.
-func (u *MessageRecordsUpsertOne) AddContactID(v int) *MessageRecordsUpsertOne {
+// UpdateContactID sets the "contact_id" field to the value that was provided on create.
+func (u *MessageRecordsUpsertOne) UpdateContactID() *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddContactID(v)
+		s.UpdateContactID()
 	})
 }
 
-// UpdateContactID sets the "contact_id" field to the value that was provided on create.
-func (u *MessageRecordsUpsertOne) UpdateContactID() *MessageRecordsUpsertOne {
+// ClearContactID clears the value of the "contact_id" field.
+func (u *MessageRecordsUpsertOne) ClearContactID() *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.UpdateContactID()
+		s.ClearContactID()
 	})
 }
 
@@ -999,19 +1097,12 @@ func (u *MessageRecordsUpsertOne) UpdateSourceType() *MessageRecordsUpsertOne {
 }
 
 // SetSourceID sets the "source_id" field.
-func (u *MessageRecordsUpsertOne) SetSourceID(v int) *MessageRecordsUpsertOne {
+func (u *MessageRecordsUpsertOne) SetSourceID(v uint64) *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
 		s.SetSourceID(v)
 	})
 }
 
-// AddSourceID adds v to the "source_id" field.
-func (u *MessageRecordsUpsertOne) AddSourceID(v int) *MessageRecordsUpsertOne {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddSourceID(v)
-	})
-}
-
 // UpdateSourceID sets the "source_id" field to the value that was provided on create.
 func (u *MessageRecordsUpsertOne) UpdateSourceID() *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
@@ -1019,17 +1110,17 @@ func (u *MessageRecordsUpsertOne) UpdateSourceID() *MessageRecordsUpsertOne {
 	})
 }
 
-// SetSubSourceID sets the "sub_source_id" field.
-func (u *MessageRecordsUpsertOne) SetSubSourceID(v int) *MessageRecordsUpsertOne {
+// ClearSourceID clears the value of the "source_id" field.
+func (u *MessageRecordsUpsertOne) ClearSourceID() *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.SetSubSourceID(v)
+		s.ClearSourceID()
 	})
 }
 
-// AddSubSourceID adds v to the "sub_source_id" field.
-func (u *MessageRecordsUpsertOne) AddSubSourceID(v int) *MessageRecordsUpsertOne {
+// SetSubSourceID sets the "sub_source_id" field.
+func (u *MessageRecordsUpsertOne) SetSubSourceID(v uint64) *MessageRecordsUpsertOne {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddSubSourceID(v)
+		s.SetSubSourceID(v)
 	})
 }
 
@@ -1040,6 +1131,13 @@ func (u *MessageRecordsUpsertOne) UpdateSubSourceID() *MessageRecordsUpsertOne {
 	})
 }
 
+// ClearSubSourceID clears the value of the "sub_source_id" field.
+func (u *MessageRecordsUpsertOne) ClearSubSourceID() *MessageRecordsUpsertOne {
+	return u.Update(func(s *MessageRecordsUpsert) {
+		s.ClearSubSourceID()
+	})
+}
+
 // Exec executes the query.
 func (u *MessageRecordsUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1335,23 +1433,23 @@ func (u *MessageRecordsUpsertBulk) UpdateBotWxid() *MessageRecordsUpsertBulk {
 }
 
 // SetContactID sets the "contact_id" field.
-func (u *MessageRecordsUpsertBulk) SetContactID(v int) *MessageRecordsUpsertBulk {
+func (u *MessageRecordsUpsertBulk) SetContactID(v uint64) *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
 		s.SetContactID(v)
 	})
 }
 
-// AddContactID adds v to the "contact_id" field.
-func (u *MessageRecordsUpsertBulk) AddContactID(v int) *MessageRecordsUpsertBulk {
+// UpdateContactID sets the "contact_id" field to the value that was provided on create.
+func (u *MessageRecordsUpsertBulk) UpdateContactID() *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddContactID(v)
+		s.UpdateContactID()
 	})
 }
 
-// UpdateContactID sets the "contact_id" field to the value that was provided on create.
-func (u *MessageRecordsUpsertBulk) UpdateContactID() *MessageRecordsUpsertBulk {
+// ClearContactID clears the value of the "contact_id" field.
+func (u *MessageRecordsUpsertBulk) ClearContactID() *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.UpdateContactID()
+		s.ClearContactID()
 	})
 }
 
@@ -1482,19 +1580,12 @@ func (u *MessageRecordsUpsertBulk) UpdateSourceType() *MessageRecordsUpsertBulk
 }
 
 // SetSourceID sets the "source_id" field.
-func (u *MessageRecordsUpsertBulk) SetSourceID(v int) *MessageRecordsUpsertBulk {
+func (u *MessageRecordsUpsertBulk) SetSourceID(v uint64) *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
 		s.SetSourceID(v)
 	})
 }
 
-// AddSourceID adds v to the "source_id" field.
-func (u *MessageRecordsUpsertBulk) AddSourceID(v int) *MessageRecordsUpsertBulk {
-	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddSourceID(v)
-	})
-}
-
 // UpdateSourceID sets the "source_id" field to the value that was provided on create.
 func (u *MessageRecordsUpsertBulk) UpdateSourceID() *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
@@ -1502,17 +1593,17 @@ func (u *MessageRecordsUpsertBulk) UpdateSourceID() *MessageRecordsUpsertBulk {
 	})
 }
 
-// SetSubSourceID sets the "sub_source_id" field.
-func (u *MessageRecordsUpsertBulk) SetSubSourceID(v int) *MessageRecordsUpsertBulk {
+// ClearSourceID clears the value of the "source_id" field.
+func (u *MessageRecordsUpsertBulk) ClearSourceID() *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.SetSubSourceID(v)
+		s.ClearSourceID()
 	})
 }
 
-// AddSubSourceID adds v to the "sub_source_id" field.
-func (u *MessageRecordsUpsertBulk) AddSubSourceID(v int) *MessageRecordsUpsertBulk {
+// SetSubSourceID sets the "sub_source_id" field.
+func (u *MessageRecordsUpsertBulk) SetSubSourceID(v uint64) *MessageRecordsUpsertBulk {
 	return u.Update(func(s *MessageRecordsUpsert) {
-		s.AddSubSourceID(v)
+		s.SetSubSourceID(v)
 	})
 }
 
@@ -1523,6 +1614,13 @@ func (u *MessageRecordsUpsertBulk) UpdateSubSourceID() *MessageRecordsUpsertBulk
 	})
 }
 
+// ClearSubSourceID clears the value of the "sub_source_id" field.
+func (u *MessageRecordsUpsertBulk) ClearSubSourceID() *MessageRecordsUpsertBulk {
+	return u.Update(func(s *MessageRecordsUpsert) {
+		s.ClearSubSourceID()
+	})
+}
+
 // Exec executes the query.
 func (u *MessageRecordsUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 240 - 11
ent/messagerecords_query.go

@@ -6,8 +6,11 @@ import (
 	"context"
 	"fmt"
 	"math"
+	"wechat-api/ent/contact"
 	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
+	"wechat-api/ent/sopnode"
+	"wechat-api/ent/sopstage"
 
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
@@ -17,10 +20,13 @@ import (
 // MessageRecordsQuery is the builder for querying MessageRecords entities.
 type MessageRecordsQuery struct {
 	config
-	ctx        *QueryContext
-	order      []messagerecords.OrderOption
-	inters     []Interceptor
-	predicates []predicate.MessageRecords
+	ctx                *QueryContext
+	order              []messagerecords.OrderOption
+	inters             []Interceptor
+	predicates         []predicate.MessageRecords
+	withSopStage       *SopStageQuery
+	withSopNode        *SopNodeQuery
+	withMessageContact *ContactQuery
 	// intermediate query (i.e. traversal path).
 	sql  *sql.Selector
 	path func(context.Context) (*sql.Selector, error)
@@ -57,6 +63,72 @@ func (mrq *MessageRecordsQuery) Order(o ...messagerecords.OrderOption) *MessageR
 	return mrq
 }
 
+// QuerySopStage chains the current query on the "sop_stage" edge.
+func (mrq *MessageRecordsQuery) QuerySopStage() *SopStageQuery {
+	query := (&SopStageClient{config: mrq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := mrq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := mrq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, selector),
+			sqlgraph.To(sopstage.Table, sopstage.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.SopStageTable, messagerecords.SopStageColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(mrq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// QuerySopNode chains the current query on the "sop_node" edge.
+func (mrq *MessageRecordsQuery) QuerySopNode() *SopNodeQuery {
+	query := (&SopNodeClient{config: mrq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := mrq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := mrq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, selector),
+			sqlgraph.To(sopnode.Table, sopnode.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.SopNodeTable, messagerecords.SopNodeColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(mrq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// QueryMessageContact chains the current query on the "message_contact" edge.
+func (mrq *MessageRecordsQuery) QueryMessageContact() *ContactQuery {
+	query := (&ContactClient{config: mrq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := mrq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := mrq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(messagerecords.Table, messagerecords.FieldID, selector),
+			sqlgraph.To(contact.Table, contact.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, messagerecords.MessageContactTable, messagerecords.MessageContactColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(mrq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
 // First returns the first MessageRecords entity from the query.
 // Returns a *NotFoundError when no MessageRecords was found.
 func (mrq *MessageRecordsQuery) First(ctx context.Context) (*MessageRecords, error) {
@@ -244,17 +316,53 @@ func (mrq *MessageRecordsQuery) Clone() *MessageRecordsQuery {
 		return nil
 	}
 	return &MessageRecordsQuery{
-		config:     mrq.config,
-		ctx:        mrq.ctx.Clone(),
-		order:      append([]messagerecords.OrderOption{}, mrq.order...),
-		inters:     append([]Interceptor{}, mrq.inters...),
-		predicates: append([]predicate.MessageRecords{}, mrq.predicates...),
+		config:             mrq.config,
+		ctx:                mrq.ctx.Clone(),
+		order:              append([]messagerecords.OrderOption{}, mrq.order...),
+		inters:             append([]Interceptor{}, mrq.inters...),
+		predicates:         append([]predicate.MessageRecords{}, mrq.predicates...),
+		withSopStage:       mrq.withSopStage.Clone(),
+		withSopNode:        mrq.withSopNode.Clone(),
+		withMessageContact: mrq.withMessageContact.Clone(),
 		// clone intermediate query.
 		sql:  mrq.sql.Clone(),
 		path: mrq.path,
 	}
 }
 
+// WithSopStage tells the query-builder to eager-load the nodes that are connected to
+// the "sop_stage" edge. The optional arguments are used to configure the query builder of the edge.
+func (mrq *MessageRecordsQuery) WithSopStage(opts ...func(*SopStageQuery)) *MessageRecordsQuery {
+	query := (&SopStageClient{config: mrq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	mrq.withSopStage = query
+	return mrq
+}
+
+// WithSopNode tells the query-builder to eager-load the nodes that are connected to
+// the "sop_node" edge. The optional arguments are used to configure the query builder of the edge.
+func (mrq *MessageRecordsQuery) WithSopNode(opts ...func(*SopNodeQuery)) *MessageRecordsQuery {
+	query := (&SopNodeClient{config: mrq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	mrq.withSopNode = query
+	return mrq
+}
+
+// WithMessageContact tells the query-builder to eager-load the nodes that are connected to
+// the "message_contact" edge. The optional arguments are used to configure the query builder of the edge.
+func (mrq *MessageRecordsQuery) WithMessageContact(opts ...func(*ContactQuery)) *MessageRecordsQuery {
+	query := (&ContactClient{config: mrq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	mrq.withMessageContact = query
+	return mrq
+}
+
 // 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.
 //
@@ -331,8 +439,13 @@ func (mrq *MessageRecordsQuery) prepareQuery(ctx context.Context) error {
 
 func (mrq *MessageRecordsQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*MessageRecords, error) {
 	var (
-		nodes = []*MessageRecords{}
-		_spec = mrq.querySpec()
+		nodes       = []*MessageRecords{}
+		_spec       = mrq.querySpec()
+		loadedTypes = [3]bool{
+			mrq.withSopStage != nil,
+			mrq.withSopNode != nil,
+			mrq.withMessageContact != nil,
+		}
 	)
 	_spec.ScanValues = func(columns []string) ([]any, error) {
 		return (*MessageRecords).scanValues(nil, columns)
@@ -340,6 +453,7 @@ func (mrq *MessageRecordsQuery) sqlAll(ctx context.Context, hooks ...queryHook)
 	_spec.Assign = func(columns []string, values []any) error {
 		node := &MessageRecords{config: mrq.config}
 		nodes = append(nodes, node)
+		node.Edges.loadedTypes = loadedTypes
 		return node.assignValues(columns, values)
 	}
 	for i := range hooks {
@@ -351,9 +465,115 @@ func (mrq *MessageRecordsQuery) sqlAll(ctx context.Context, hooks ...queryHook)
 	if len(nodes) == 0 {
 		return nodes, nil
 	}
+	if query := mrq.withSopStage; query != nil {
+		if err := mrq.loadSopStage(ctx, query, nodes, nil,
+			func(n *MessageRecords, e *SopStage) { n.Edges.SopStage = e }); err != nil {
+			return nil, err
+		}
+	}
+	if query := mrq.withSopNode; query != nil {
+		if err := mrq.loadSopNode(ctx, query, nodes, nil,
+			func(n *MessageRecords, e *SopNode) { n.Edges.SopNode = e }); err != nil {
+			return nil, err
+		}
+	}
+	if query := mrq.withMessageContact; query != nil {
+		if err := mrq.loadMessageContact(ctx, query, nodes, nil,
+			func(n *MessageRecords, e *Contact) { n.Edges.MessageContact = e }); err != nil {
+			return nil, err
+		}
+	}
 	return nodes, nil
 }
 
+func (mrq *MessageRecordsQuery) loadSopStage(ctx context.Context, query *SopStageQuery, nodes []*MessageRecords, init func(*MessageRecords), assign func(*MessageRecords, *SopStage)) error {
+	ids := make([]uint64, 0, len(nodes))
+	nodeids := make(map[uint64][]*MessageRecords)
+	for i := range nodes {
+		fk := nodes[i].SourceID
+		if _, ok := nodeids[fk]; !ok {
+			ids = append(ids, fk)
+		}
+		nodeids[fk] = append(nodeids[fk], nodes[i])
+	}
+	if len(ids) == 0 {
+		return nil
+	}
+	query.Where(sopstage.IDIn(ids...))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		nodes, ok := nodeids[n.ID]
+		if !ok {
+			return fmt.Errorf(`unexpected foreign-key "source_id" returned %v`, n.ID)
+		}
+		for i := range nodes {
+			assign(nodes[i], n)
+		}
+	}
+	return nil
+}
+func (mrq *MessageRecordsQuery) loadSopNode(ctx context.Context, query *SopNodeQuery, nodes []*MessageRecords, init func(*MessageRecords), assign func(*MessageRecords, *SopNode)) error {
+	ids := make([]uint64, 0, len(nodes))
+	nodeids := make(map[uint64][]*MessageRecords)
+	for i := range nodes {
+		fk := nodes[i].SubSourceID
+		if _, ok := nodeids[fk]; !ok {
+			ids = append(ids, fk)
+		}
+		nodeids[fk] = append(nodeids[fk], nodes[i])
+	}
+	if len(ids) == 0 {
+		return nil
+	}
+	query.Where(sopnode.IDIn(ids...))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		nodes, ok := nodeids[n.ID]
+		if !ok {
+			return fmt.Errorf(`unexpected foreign-key "sub_source_id" returned %v`, n.ID)
+		}
+		for i := range nodes {
+			assign(nodes[i], n)
+		}
+	}
+	return nil
+}
+func (mrq *MessageRecordsQuery) loadMessageContact(ctx context.Context, query *ContactQuery, nodes []*MessageRecords, init func(*MessageRecords), assign func(*MessageRecords, *Contact)) error {
+	ids := make([]uint64, 0, len(nodes))
+	nodeids := make(map[uint64][]*MessageRecords)
+	for i := range nodes {
+		fk := nodes[i].ContactID
+		if _, ok := nodeids[fk]; !ok {
+			ids = append(ids, fk)
+		}
+		nodeids[fk] = append(nodeids[fk], nodes[i])
+	}
+	if len(ids) == 0 {
+		return nil
+	}
+	query.Where(contact.IDIn(ids...))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		nodes, ok := nodeids[n.ID]
+		if !ok {
+			return fmt.Errorf(`unexpected foreign-key "contact_id" returned %v`, n.ID)
+		}
+		for i := range nodes {
+			assign(nodes[i], n)
+		}
+	}
+	return nil
+}
+
 func (mrq *MessageRecordsQuery) sqlCount(ctx context.Context) (int, error) {
 	_spec := mrq.querySpec()
 	_spec.Node.Columns = mrq.ctx.Fields
@@ -379,6 +599,15 @@ func (mrq *MessageRecordsQuery) querySpec() *sqlgraph.QuerySpec {
 				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
 			}
 		}
+		if mrq.withSopStage != nil {
+			_spec.Node.AddColumnOnce(messagerecords.FieldSourceID)
+		}
+		if mrq.withSopNode != nil {
+			_spec.Node.AddColumnOnce(messagerecords.FieldSubSourceID)
+		}
+		if mrq.withMessageContact != nil {
+			_spec.Node.AddColumnOnce(messagerecords.FieldContactID)
+		}
 	}
 	if ps := mrq.predicates; len(ps) > 0 {
 		_spec.Predicate = func(selector *sql.Selector) {

+ 373 - 88
ent/messagerecords_update.go

@@ -7,8 +7,11 @@ import (
 	"errors"
 	"fmt"
 	"time"
+	"wechat-api/ent/contact"
 	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
+	"wechat-api/ent/sopnode"
+	"wechat-api/ent/sopstage"
 
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
@@ -96,23 +99,22 @@ func (mru *MessageRecordsUpdate) SetNillableBotWxid(s *string) *MessageRecordsUp
 }
 
 // SetContactID sets the "contact_id" field.
-func (mru *MessageRecordsUpdate) SetContactID(i int) *MessageRecordsUpdate {
-	mru.mutation.ResetContactID()
-	mru.mutation.SetContactID(i)
+func (mru *MessageRecordsUpdate) SetContactID(u uint64) *MessageRecordsUpdate {
+	mru.mutation.SetContactID(u)
 	return mru
 }
 
 // SetNillableContactID sets the "contact_id" field if the given value is not nil.
-func (mru *MessageRecordsUpdate) SetNillableContactID(i *int) *MessageRecordsUpdate {
-	if i != nil {
-		mru.SetContactID(*i)
+func (mru *MessageRecordsUpdate) SetNillableContactID(u *uint64) *MessageRecordsUpdate {
+	if u != nil {
+		mru.SetContactID(*u)
 	}
 	return mru
 }
 
-// AddContactID adds i to the "contact_id" field.
-func (mru *MessageRecordsUpdate) AddContactID(i int) *MessageRecordsUpdate {
-	mru.mutation.AddContactID(i)
+// ClearContactID clears the value of the "contact_id" field.
+func (mru *MessageRecordsUpdate) ClearContactID() *MessageRecordsUpdate {
+	mru.mutation.ClearContactID()
 	return mru
 }
 
@@ -242,52 +244,125 @@ func (mru *MessageRecordsUpdate) AddSourceType(i int) *MessageRecordsUpdate {
 }
 
 // SetSourceID sets the "source_id" field.
-func (mru *MessageRecordsUpdate) SetSourceID(i int) *MessageRecordsUpdate {
-	mru.mutation.ResetSourceID()
-	mru.mutation.SetSourceID(i)
+func (mru *MessageRecordsUpdate) SetSourceID(u uint64) *MessageRecordsUpdate {
+	mru.mutation.SetSourceID(u)
 	return mru
 }
 
 // SetNillableSourceID sets the "source_id" field if the given value is not nil.
-func (mru *MessageRecordsUpdate) SetNillableSourceID(i *int) *MessageRecordsUpdate {
-	if i != nil {
-		mru.SetSourceID(*i)
+func (mru *MessageRecordsUpdate) SetNillableSourceID(u *uint64) *MessageRecordsUpdate {
+	if u != nil {
+		mru.SetSourceID(*u)
 	}
 	return mru
 }
 
-// AddSourceID adds i to the "source_id" field.
-func (mru *MessageRecordsUpdate) AddSourceID(i int) *MessageRecordsUpdate {
-	mru.mutation.AddSourceID(i)
+// ClearSourceID clears the value of the "source_id" field.
+func (mru *MessageRecordsUpdate) ClearSourceID() *MessageRecordsUpdate {
+	mru.mutation.ClearSourceID()
 	return mru
 }
 
 // SetSubSourceID sets the "sub_source_id" field.
-func (mru *MessageRecordsUpdate) SetSubSourceID(i int) *MessageRecordsUpdate {
-	mru.mutation.ResetSubSourceID()
-	mru.mutation.SetSubSourceID(i)
+func (mru *MessageRecordsUpdate) SetSubSourceID(u uint64) *MessageRecordsUpdate {
+	mru.mutation.SetSubSourceID(u)
 	return mru
 }
 
 // SetNillableSubSourceID sets the "sub_source_id" field if the given value is not nil.
-func (mru *MessageRecordsUpdate) SetNillableSubSourceID(i *int) *MessageRecordsUpdate {
-	if i != nil {
-		mru.SetSubSourceID(*i)
+func (mru *MessageRecordsUpdate) SetNillableSubSourceID(u *uint64) *MessageRecordsUpdate {
+	if u != nil {
+		mru.SetSubSourceID(*u)
+	}
+	return mru
+}
+
+// ClearSubSourceID clears the value of the "sub_source_id" field.
+func (mru *MessageRecordsUpdate) ClearSubSourceID() *MessageRecordsUpdate {
+	mru.mutation.ClearSubSourceID()
+	return mru
+}
+
+// SetSopStageID sets the "sop_stage" edge to the SopStage entity by ID.
+func (mru *MessageRecordsUpdate) SetSopStageID(id uint64) *MessageRecordsUpdate {
+	mru.mutation.SetSopStageID(id)
+	return mru
+}
+
+// SetNillableSopStageID sets the "sop_stage" edge to the SopStage entity by ID if the given value is not nil.
+func (mru *MessageRecordsUpdate) SetNillableSopStageID(id *uint64) *MessageRecordsUpdate {
+	if id != nil {
+		mru = mru.SetSopStageID(*id)
+	}
+	return mru
+}
+
+// SetSopStage sets the "sop_stage" edge to the SopStage entity.
+func (mru *MessageRecordsUpdate) SetSopStage(s *SopStage) *MessageRecordsUpdate {
+	return mru.SetSopStageID(s.ID)
+}
+
+// SetSopNodeID sets the "sop_node" edge to the SopNode entity by ID.
+func (mru *MessageRecordsUpdate) SetSopNodeID(id uint64) *MessageRecordsUpdate {
+	mru.mutation.SetSopNodeID(id)
+	return mru
+}
+
+// SetNillableSopNodeID sets the "sop_node" edge to the SopNode entity by ID if the given value is not nil.
+func (mru *MessageRecordsUpdate) SetNillableSopNodeID(id *uint64) *MessageRecordsUpdate {
+	if id != nil {
+		mru = mru.SetSopNodeID(*id)
 	}
 	return mru
 }
 
-// AddSubSourceID adds i to the "sub_source_id" field.
-func (mru *MessageRecordsUpdate) AddSubSourceID(i int) *MessageRecordsUpdate {
-	mru.mutation.AddSubSourceID(i)
+// SetSopNode sets the "sop_node" edge to the SopNode entity.
+func (mru *MessageRecordsUpdate) SetSopNode(s *SopNode) *MessageRecordsUpdate {
+	return mru.SetSopNodeID(s.ID)
+}
+
+// SetMessageContactID sets the "message_contact" edge to the Contact entity by ID.
+func (mru *MessageRecordsUpdate) SetMessageContactID(id uint64) *MessageRecordsUpdate {
+	mru.mutation.SetMessageContactID(id)
+	return mru
+}
+
+// SetNillableMessageContactID sets the "message_contact" edge to the Contact entity by ID if the given value is not nil.
+func (mru *MessageRecordsUpdate) SetNillableMessageContactID(id *uint64) *MessageRecordsUpdate {
+	if id != nil {
+		mru = mru.SetMessageContactID(*id)
+	}
 	return mru
 }
 
+// SetMessageContact sets the "message_contact" edge to the Contact entity.
+func (mru *MessageRecordsUpdate) SetMessageContact(c *Contact) *MessageRecordsUpdate {
+	return mru.SetMessageContactID(c.ID)
+}
+
 // Mutation returns the MessageRecordsMutation object of the builder.
 func (mru *MessageRecordsUpdate) Mutation() *MessageRecordsMutation {
 	return mru.mutation
 }
 
+// ClearSopStage clears the "sop_stage" edge to the SopStage entity.
+func (mru *MessageRecordsUpdate) ClearSopStage() *MessageRecordsUpdate {
+	mru.mutation.ClearSopStage()
+	return mru
+}
+
+// ClearSopNode clears the "sop_node" edge to the SopNode entity.
+func (mru *MessageRecordsUpdate) ClearSopNode() *MessageRecordsUpdate {
+	mru.mutation.ClearSopNode()
+	return mru
+}
+
+// ClearMessageContact clears the "message_contact" edge to the Contact entity.
+func (mru *MessageRecordsUpdate) ClearMessageContact() *MessageRecordsUpdate {
+	mru.mutation.ClearMessageContact()
+	return mru
+}
+
 // Save executes the query and returns the number of nodes affected by the update operation.
 func (mru *MessageRecordsUpdate) Save(ctx context.Context) (int, error) {
 	if err := mru.defaults(); err != nil {
@@ -360,12 +435,6 @@ func (mru *MessageRecordsUpdate) sqlSave(ctx context.Context) (n int, err error)
 	if value, ok := mru.mutation.BotWxid(); ok {
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 	}
-	if value, ok := mru.mutation.ContactID(); ok {
-		_spec.SetField(messagerecords.FieldContactID, field.TypeInt, value)
-	}
-	if value, ok := mru.mutation.AddedContactID(); ok {
-		_spec.AddField(messagerecords.FieldContactID, field.TypeInt, value)
-	}
 	if value, ok := mru.mutation.ContactType(); ok {
 		_spec.SetField(messagerecords.FieldContactType, field.TypeInt, value)
 	}
@@ -399,17 +468,92 @@ func (mru *MessageRecordsUpdate) sqlSave(ctx context.Context) (n int, err error)
 	if value, ok := mru.mutation.AddedSourceType(); ok {
 		_spec.AddField(messagerecords.FieldSourceType, field.TypeInt, value)
 	}
-	if value, ok := mru.mutation.SourceID(); ok {
-		_spec.SetField(messagerecords.FieldSourceID, field.TypeInt, value)
-	}
-	if value, ok := mru.mutation.AddedSourceID(); ok {
-		_spec.AddField(messagerecords.FieldSourceID, field.TypeInt, value)
-	}
-	if value, ok := mru.mutation.SubSourceID(); ok {
-		_spec.SetField(messagerecords.FieldSubSourceID, field.TypeInt, value)
-	}
-	if value, ok := mru.mutation.AddedSubSourceID(); ok {
-		_spec.AddField(messagerecords.FieldSubSourceID, field.TypeInt, value)
+	if mru.mutation.SopStageCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopStageTable,
+			Columns: []string{messagerecords.SopStageColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopstage.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mru.mutation.SopStageIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopStageTable,
+			Columns: []string{messagerecords.SopStageColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopstage.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if mru.mutation.SopNodeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopNodeTable,
+			Columns: []string{messagerecords.SopNodeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopnode.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mru.mutation.SopNodeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopNodeTable,
+			Columns: []string{messagerecords.SopNodeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopnode.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if mru.mutation.MessageContactCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.MessageContactTable,
+			Columns: []string{messagerecords.MessageContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mru.mutation.MessageContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.MessageContactTable,
+			Columns: []string{messagerecords.MessageContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
 	if n, err = sqlgraph.UpdateNodes(ctx, mru.driver, _spec); err != nil {
 		if _, ok := err.(*sqlgraph.NotFoundError); ok {
@@ -499,23 +643,22 @@ func (mruo *MessageRecordsUpdateOne) SetNillableBotWxid(s *string) *MessageRecor
 }
 
 // SetContactID sets the "contact_id" field.
-func (mruo *MessageRecordsUpdateOne) SetContactID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.ResetContactID()
-	mruo.mutation.SetContactID(i)
+func (mruo *MessageRecordsUpdateOne) SetContactID(u uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetContactID(u)
 	return mruo
 }
 
 // SetNillableContactID sets the "contact_id" field if the given value is not nil.
-func (mruo *MessageRecordsUpdateOne) SetNillableContactID(i *int) *MessageRecordsUpdateOne {
-	if i != nil {
-		mruo.SetContactID(*i)
+func (mruo *MessageRecordsUpdateOne) SetNillableContactID(u *uint64) *MessageRecordsUpdateOne {
+	if u != nil {
+		mruo.SetContactID(*u)
 	}
 	return mruo
 }
 
-// AddContactID adds i to the "contact_id" field.
-func (mruo *MessageRecordsUpdateOne) AddContactID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.AddContactID(i)
+// ClearContactID clears the value of the "contact_id" field.
+func (mruo *MessageRecordsUpdateOne) ClearContactID() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearContactID()
 	return mruo
 }
 
@@ -645,52 +788,125 @@ func (mruo *MessageRecordsUpdateOne) AddSourceType(i int) *MessageRecordsUpdateO
 }
 
 // SetSourceID sets the "source_id" field.
-func (mruo *MessageRecordsUpdateOne) SetSourceID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.ResetSourceID()
-	mruo.mutation.SetSourceID(i)
+func (mruo *MessageRecordsUpdateOne) SetSourceID(u uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetSourceID(u)
 	return mruo
 }
 
 // SetNillableSourceID sets the "source_id" field if the given value is not nil.
-func (mruo *MessageRecordsUpdateOne) SetNillableSourceID(i *int) *MessageRecordsUpdateOne {
-	if i != nil {
-		mruo.SetSourceID(*i)
+func (mruo *MessageRecordsUpdateOne) SetNillableSourceID(u *uint64) *MessageRecordsUpdateOne {
+	if u != nil {
+		mruo.SetSourceID(*u)
 	}
 	return mruo
 }
 
-// AddSourceID adds i to the "source_id" field.
-func (mruo *MessageRecordsUpdateOne) AddSourceID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.AddSourceID(i)
+// ClearSourceID clears the value of the "source_id" field.
+func (mruo *MessageRecordsUpdateOne) ClearSourceID() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearSourceID()
 	return mruo
 }
 
 // SetSubSourceID sets the "sub_source_id" field.
-func (mruo *MessageRecordsUpdateOne) SetSubSourceID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.ResetSubSourceID()
-	mruo.mutation.SetSubSourceID(i)
+func (mruo *MessageRecordsUpdateOne) SetSubSourceID(u uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetSubSourceID(u)
 	return mruo
 }
 
 // SetNillableSubSourceID sets the "sub_source_id" field if the given value is not nil.
-func (mruo *MessageRecordsUpdateOne) SetNillableSubSourceID(i *int) *MessageRecordsUpdateOne {
-	if i != nil {
-		mruo.SetSubSourceID(*i)
+func (mruo *MessageRecordsUpdateOne) SetNillableSubSourceID(u *uint64) *MessageRecordsUpdateOne {
+	if u != nil {
+		mruo.SetSubSourceID(*u)
+	}
+	return mruo
+}
+
+// ClearSubSourceID clears the value of the "sub_source_id" field.
+func (mruo *MessageRecordsUpdateOne) ClearSubSourceID() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearSubSourceID()
+	return mruo
+}
+
+// SetSopStageID sets the "sop_stage" edge to the SopStage entity by ID.
+func (mruo *MessageRecordsUpdateOne) SetSopStageID(id uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetSopStageID(id)
+	return mruo
+}
+
+// SetNillableSopStageID sets the "sop_stage" edge to the SopStage entity by ID if the given value is not nil.
+func (mruo *MessageRecordsUpdateOne) SetNillableSopStageID(id *uint64) *MessageRecordsUpdateOne {
+	if id != nil {
+		mruo = mruo.SetSopStageID(*id)
+	}
+	return mruo
+}
+
+// SetSopStage sets the "sop_stage" edge to the SopStage entity.
+func (mruo *MessageRecordsUpdateOne) SetSopStage(s *SopStage) *MessageRecordsUpdateOne {
+	return mruo.SetSopStageID(s.ID)
+}
+
+// SetSopNodeID sets the "sop_node" edge to the SopNode entity by ID.
+func (mruo *MessageRecordsUpdateOne) SetSopNodeID(id uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetSopNodeID(id)
+	return mruo
+}
+
+// SetNillableSopNodeID sets the "sop_node" edge to the SopNode entity by ID if the given value is not nil.
+func (mruo *MessageRecordsUpdateOne) SetNillableSopNodeID(id *uint64) *MessageRecordsUpdateOne {
+	if id != nil {
+		mruo = mruo.SetSopNodeID(*id)
 	}
 	return mruo
 }
 
-// AddSubSourceID adds i to the "sub_source_id" field.
-func (mruo *MessageRecordsUpdateOne) AddSubSourceID(i int) *MessageRecordsUpdateOne {
-	mruo.mutation.AddSubSourceID(i)
+// SetSopNode sets the "sop_node" edge to the SopNode entity.
+func (mruo *MessageRecordsUpdateOne) SetSopNode(s *SopNode) *MessageRecordsUpdateOne {
+	return mruo.SetSopNodeID(s.ID)
+}
+
+// SetMessageContactID sets the "message_contact" edge to the Contact entity by ID.
+func (mruo *MessageRecordsUpdateOne) SetMessageContactID(id uint64) *MessageRecordsUpdateOne {
+	mruo.mutation.SetMessageContactID(id)
+	return mruo
+}
+
+// SetNillableMessageContactID sets the "message_contact" edge to the Contact entity by ID if the given value is not nil.
+func (mruo *MessageRecordsUpdateOne) SetNillableMessageContactID(id *uint64) *MessageRecordsUpdateOne {
+	if id != nil {
+		mruo = mruo.SetMessageContactID(*id)
+	}
 	return mruo
 }
 
+// SetMessageContact sets the "message_contact" edge to the Contact entity.
+func (mruo *MessageRecordsUpdateOne) SetMessageContact(c *Contact) *MessageRecordsUpdateOne {
+	return mruo.SetMessageContactID(c.ID)
+}
+
 // Mutation returns the MessageRecordsMutation object of the builder.
 func (mruo *MessageRecordsUpdateOne) Mutation() *MessageRecordsMutation {
 	return mruo.mutation
 }
 
+// ClearSopStage clears the "sop_stage" edge to the SopStage entity.
+func (mruo *MessageRecordsUpdateOne) ClearSopStage() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearSopStage()
+	return mruo
+}
+
+// ClearSopNode clears the "sop_node" edge to the SopNode entity.
+func (mruo *MessageRecordsUpdateOne) ClearSopNode() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearSopNode()
+	return mruo
+}
+
+// ClearMessageContact clears the "message_contact" edge to the Contact entity.
+func (mruo *MessageRecordsUpdateOne) ClearMessageContact() *MessageRecordsUpdateOne {
+	mruo.mutation.ClearMessageContact()
+	return mruo
+}
+
 // Where appends a list predicates to the MessageRecordsUpdate builder.
 func (mruo *MessageRecordsUpdateOne) Where(ps ...predicate.MessageRecords) *MessageRecordsUpdateOne {
 	mruo.mutation.Where(ps...)
@@ -793,12 +1009,6 @@ func (mruo *MessageRecordsUpdateOne) sqlSave(ctx context.Context) (_node *Messag
 	if value, ok := mruo.mutation.BotWxid(); ok {
 		_spec.SetField(messagerecords.FieldBotWxid, field.TypeString, value)
 	}
-	if value, ok := mruo.mutation.ContactID(); ok {
-		_spec.SetField(messagerecords.FieldContactID, field.TypeInt, value)
-	}
-	if value, ok := mruo.mutation.AddedContactID(); ok {
-		_spec.AddField(messagerecords.FieldContactID, field.TypeInt, value)
-	}
 	if value, ok := mruo.mutation.ContactType(); ok {
 		_spec.SetField(messagerecords.FieldContactType, field.TypeInt, value)
 	}
@@ -832,17 +1042,92 @@ func (mruo *MessageRecordsUpdateOne) sqlSave(ctx context.Context) (_node *Messag
 	if value, ok := mruo.mutation.AddedSourceType(); ok {
 		_spec.AddField(messagerecords.FieldSourceType, field.TypeInt, value)
 	}
-	if value, ok := mruo.mutation.SourceID(); ok {
-		_spec.SetField(messagerecords.FieldSourceID, field.TypeInt, value)
-	}
-	if value, ok := mruo.mutation.AddedSourceID(); ok {
-		_spec.AddField(messagerecords.FieldSourceID, field.TypeInt, value)
-	}
-	if value, ok := mruo.mutation.SubSourceID(); ok {
-		_spec.SetField(messagerecords.FieldSubSourceID, field.TypeInt, value)
-	}
-	if value, ok := mruo.mutation.AddedSubSourceID(); ok {
-		_spec.AddField(messagerecords.FieldSubSourceID, field.TypeInt, value)
+	if mruo.mutation.SopStageCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopStageTable,
+			Columns: []string{messagerecords.SopStageColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopstage.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mruo.mutation.SopStageIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopStageTable,
+			Columns: []string{messagerecords.SopStageColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopstage.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if mruo.mutation.SopNodeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopNodeTable,
+			Columns: []string{messagerecords.SopNodeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopnode.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mruo.mutation.SopNodeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.SopNodeTable,
+			Columns: []string{messagerecords.SopNodeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(sopnode.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if mruo.mutation.MessageContactCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.MessageContactTable,
+			Columns: []string{messagerecords.MessageContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := mruo.mutation.MessageContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   messagerecords.MessageContactTable,
+			Columns: []string{messagerecords.MessageContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
 	_node = &MessageRecords{config: mruo.config}
 	_spec.Assign = _node.assignValues

+ 27 - 4
ent/migrate/schema.go

@@ -149,7 +149,6 @@ var (
 		{Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
 		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
 		{Name: "bot_wxid", Type: field.TypeString, Comment: "机器人微信 id"},
-		{Name: "contact_id", Type: field.TypeInt, Comment: "联系人 id"},
 		{Name: "contact_type", Type: field.TypeInt, Comment: "类型:1好友,2群组,3企业微信联系人", Default: 1},
 		{Name: "contact_wxid", Type: field.TypeString, Comment: "接收方微信 id", Default: ""},
 		{Name: "content_type", Type: field.TypeInt, Comment: "内容类型 1 文本 2 文件", Default: 1},
@@ -157,19 +156,40 @@ var (
 		{Name: "error_detail", Type: field.TypeString, Comment: "异常原因", Default: ""},
 		{Name: "send_time", Type: field.TypeTime, Nullable: true, Comment: "发送时间"},
 		{Name: "source_type", Type: field.TypeInt, Comment: "源类型 1 点发 2 群发 3 SOP", Default: 1},
-		{Name: "source_id", Type: field.TypeInt, Comment: "源 ID", Default: 1},
-		{Name: "sub_source_id", Type: field.TypeInt, Comment: "次源 ID", Default: 1},
+		{Name: "contact_id", Type: field.TypeUint64, Nullable: true, Comment: "联系人 id"},
+		{Name: "sub_source_id", Type: field.TypeUint64, Nullable: true, Comment: "次源 ID", Default: 1},
+		{Name: "source_id", Type: field.TypeUint64, Nullable: true, Comment: "源 ID", Default: 1},
 	}
 	// MessageRecordsTable holds the schema information for the "message_records" table.
 	MessageRecordsTable = &schema.Table{
 		Name:       "message_records",
 		Columns:    MessageRecordsColumns,
 		PrimaryKey: []*schema.Column{MessageRecordsColumns[0]},
+		ForeignKeys: []*schema.ForeignKey{
+			{
+				Symbol:     "message_records_contact_contact_messages",
+				Columns:    []*schema.Column{MessageRecordsColumns[13]},
+				RefColumns: []*schema.Column{ContactColumns[0]},
+				OnDelete:   schema.SetNull,
+			},
+			{
+				Symbol:     "message_records_sop_node_node_messages",
+				Columns:    []*schema.Column{MessageRecordsColumns[14]},
+				RefColumns: []*schema.Column{SopNodeColumns[0]},
+				OnDelete:   schema.SetNull,
+			},
+			{
+				Symbol:     "message_records_sop_stage_stage_messages",
+				Columns:    []*schema.Column{MessageRecordsColumns[15]},
+				RefColumns: []*schema.Column{SopStageColumns[0]},
+				OnDelete:   schema.SetNull,
+			},
+		},
 		Indexes: []*schema.Index{
 			{
 				Name:    "messagerecords_source_type",
 				Unique:  false,
-				Columns: []*schema.Column{MessageRecordsColumns[13]},
+				Columns: []*schema.Column{MessageRecordsColumns[12]},
 			},
 		},
 	}
@@ -396,6 +416,9 @@ func init() {
 	MessageTable.Annotation = &entsql.Annotation{
 		Table: "message",
 	}
+	MessageRecordsTable.ForeignKeys[0].RefTable = ContactTable
+	MessageRecordsTable.ForeignKeys[1].RefTable = SopNodeTable
+	MessageRecordsTable.ForeignKeys[2].RefTable = SopStageTable
 	MessageRecordsTable.Annotation = &entsql.Annotation{
 		Table: "message_records",
 	}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 463 - 157
ent/mutation.go


+ 2 - 2
ent/runtime/runtime.go

@@ -250,11 +250,11 @@ func init() {
 	// messagerecordsDescSourceID is the schema descriptor for source_id field.
 	messagerecordsDescSourceID := messagerecordsFields[9].Descriptor()
 	// messagerecords.DefaultSourceID holds the default value on creation for the source_id field.
-	messagerecords.DefaultSourceID = messagerecordsDescSourceID.Default.(int)
+	messagerecords.DefaultSourceID = messagerecordsDescSourceID.Default.(uint64)
 	// messagerecordsDescSubSourceID is the schema descriptor for sub_source_id field.
 	messagerecordsDescSubSourceID := messagerecordsFields[10].Descriptor()
 	// messagerecords.DefaultSubSourceID holds the default value on creation for the sub_source_id field.
-	messagerecords.DefaultSubSourceID = messagerecordsDescSubSourceID.Default.(int)
+	messagerecords.DefaultSubSourceID = messagerecordsDescSubSourceID.Default.(uint64)
 	serverMixin := schema.Server{}.Mixin()
 	serverMixinHooks2 := serverMixin[2].Hooks()
 	server.Hooks[0] = serverMixinHooks2[0]

+ 1 - 0
ent/schema/contact.go

@@ -85,6 +85,7 @@ func (Contact) Indexes() []ent.Index {
 func (Contact) Edges() []ent.Edge {
 	return []ent.Edge{
 		edge.To("contact_relationships", LabelRelationship.Type),
+		edge.To("contact_messages", MessageRecords.Type),
 	}
 }
 func (Contact) Annotations() []schema.Annotation {

+ 18 - 4
ent/schema/message_records.go

@@ -4,6 +4,7 @@ import (
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/entsql"
 	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/edge"
 	"entgo.io/ent/schema/field"
 	"entgo.io/ent/schema/index"
 	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
@@ -19,7 +20,7 @@ func (MessageRecords) Fields() []ent.Field {
 		field.String("bot_wxid").
 			Annotations(entsql.WithComments(true)).
 			Comment("机器人微信 id"),
-		field.Int("contact_id").
+		field.Uint64("contact_id").Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("联系人 id"),
 		field.Int("contact_type").Default(1).
@@ -43,10 +44,10 @@ func (MessageRecords) Fields() []ent.Field {
 		field.Int("source_type").Default(1).
 			Annotations(entsql.WithComments(true)).
 			Comment("源类型 1 点发 2 群发 3 SOP"),
-		field.Int("source_id").Default(1).
+		field.Uint64("source_id").Default(1).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("源 ID"),
-		field.Int("sub_source_id").Default(1).
+		field.Uint64("sub_source_id").Default(1).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("次源 ID"),
 	}
@@ -67,7 +68,20 @@ func (MessageRecords) Indexes() []ent.Index {
 }
 
 func (MessageRecords) Edges() []ent.Edge {
-	return nil
+	return []ent.Edge{
+		edge.From("sop_stage", SopStage.Type).
+			Ref("stage_messages").
+			Unique().
+			Field("source_id"),
+		edge.From("sop_node", SopNode.Type).
+			Ref("node_messages").
+			Unique().
+			Field("sub_source_id"),
+		edge.From("message_contact", Contact.Type).
+			Ref("contact_messages").
+			Unique().
+			Field("contact_id"),
+	}
 }
 
 func (MessageRecords) Annotations() []schema.Annotation {

+ 2 - 1
ent/schema/sop_node.go

@@ -36,7 +36,7 @@ func (SopNode) Fields() []ent.Field {
 		field.JSON("action_message", []custom_types.Action{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后发送的消息内容"),
-		field.JSON("action_label", []int{}).Optional().
+		field.JSON("action_label", []uint64{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后需要打的标签"),
 	}
@@ -63,6 +63,7 @@ func (SopNode) Edges() []ent.Edge {
 			Unique().
 			Field("stage_id").
 			Required(),
+		edge.To("node_messages", MessageRecords.Type),
 	}
 }
 

+ 2 - 1
ent/schema/sop_stage.go

@@ -36,7 +36,7 @@ func (SopStage) Fields() []ent.Field {
 		field.JSON("action_message", []custom_types.Action{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后发送的消息内容"),
-		field.JSON("action_label", []int{}).Optional().
+		field.JSON("action_label", []uint64{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后需要打的标签"),
 		field.Int("index_sort").Default(1).Optional().
@@ -67,6 +67,7 @@ func (SopStage) Edges() []ent.Edge {
 			Field("task_id").
 			Required(),
 		edge.To("stage_nodes", SopNode.Type),
+		edge.To("stage_messages", MessageRecords.Type),
 	}
 }
 func (SopStage) Annotations() []schema.Annotation {

+ 15 - 15
ent/set_not_nil.go

@@ -920,7 +920,7 @@ func (mr *MessageRecordsCreate) SetNotNilBotWxid(value *string) *MessageRecordsC
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdate) SetNotNilContactID(value *int) *MessageRecordsUpdate {
+func (mr *MessageRecordsUpdate) SetNotNilContactID(value *uint64) *MessageRecordsUpdate {
 	if value != nil {
 		return mr.SetContactID(*value)
 	}
@@ -928,7 +928,7 @@ func (mr *MessageRecordsUpdate) SetNotNilContactID(value *int) *MessageRecordsUp
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdateOne) SetNotNilContactID(value *int) *MessageRecordsUpdateOne {
+func (mr *MessageRecordsUpdateOne) SetNotNilContactID(value *uint64) *MessageRecordsUpdateOne {
 	if value != nil {
 		return mr.SetContactID(*value)
 	}
@@ -936,7 +936,7 @@ func (mr *MessageRecordsUpdateOne) SetNotNilContactID(value *int) *MessageRecord
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsCreate) SetNotNilContactID(value *int) *MessageRecordsCreate {
+func (mr *MessageRecordsCreate) SetNotNilContactID(value *uint64) *MessageRecordsCreate {
 	if value != nil {
 		return mr.SetContactID(*value)
 	}
@@ -1112,7 +1112,7 @@ func (mr *MessageRecordsCreate) SetNotNilSourceType(value *int) *MessageRecordsC
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdate) SetNotNilSourceID(value *int) *MessageRecordsUpdate {
+func (mr *MessageRecordsUpdate) SetNotNilSourceID(value *uint64) *MessageRecordsUpdate {
 	if value != nil {
 		return mr.SetSourceID(*value)
 	}
@@ -1120,7 +1120,7 @@ func (mr *MessageRecordsUpdate) SetNotNilSourceID(value *int) *MessageRecordsUpd
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdateOne) SetNotNilSourceID(value *int) *MessageRecordsUpdateOne {
+func (mr *MessageRecordsUpdateOne) SetNotNilSourceID(value *uint64) *MessageRecordsUpdateOne {
 	if value != nil {
 		return mr.SetSourceID(*value)
 	}
@@ -1128,7 +1128,7 @@ func (mr *MessageRecordsUpdateOne) SetNotNilSourceID(value *int) *MessageRecords
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsCreate) SetNotNilSourceID(value *int) *MessageRecordsCreate {
+func (mr *MessageRecordsCreate) SetNotNilSourceID(value *uint64) *MessageRecordsCreate {
 	if value != nil {
 		return mr.SetSourceID(*value)
 	}
@@ -1136,7 +1136,7 @@ func (mr *MessageRecordsCreate) SetNotNilSourceID(value *int) *MessageRecordsCre
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdate) SetNotNilSubSourceID(value *int) *MessageRecordsUpdate {
+func (mr *MessageRecordsUpdate) SetNotNilSubSourceID(value *uint64) *MessageRecordsUpdate {
 	if value != nil {
 		return mr.SetSubSourceID(*value)
 	}
@@ -1144,7 +1144,7 @@ func (mr *MessageRecordsUpdate) SetNotNilSubSourceID(value *int) *MessageRecords
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsUpdateOne) SetNotNilSubSourceID(value *int) *MessageRecordsUpdateOne {
+func (mr *MessageRecordsUpdateOne) SetNotNilSubSourceID(value *uint64) *MessageRecordsUpdateOne {
 	if value != nil {
 		return mr.SetSubSourceID(*value)
 	}
@@ -1152,7 +1152,7 @@ func (mr *MessageRecordsUpdateOne) SetNotNilSubSourceID(value *int) *MessageReco
 }
 
 // set field if value's pointer is not nil.
-func (mr *MessageRecordsCreate) SetNotNilSubSourceID(value *int) *MessageRecordsCreate {
+func (mr *MessageRecordsCreate) SetNotNilSubSourceID(value *uint64) *MessageRecordsCreate {
 	if value != nil {
 		return mr.SetSubSourceID(*value)
 	}
@@ -1544,7 +1544,7 @@ func (sn *SopNodeCreate) SetNotNilActionMessage(value []custom_types.Action) *So
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdate) SetNotNilActionLabel(value []int) *SopNodeUpdate {
+func (sn *SopNodeUpdate) SetNotNilActionLabel(value []uint64) *SopNodeUpdate {
 	if value != nil {
 		return sn.SetActionLabel(value)
 	}
@@ -1552,7 +1552,7 @@ func (sn *SopNodeUpdate) SetNotNilActionLabel(value []int) *SopNodeUpdate {
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdateOne) SetNotNilActionLabel(value []int) *SopNodeUpdateOne {
+func (sn *SopNodeUpdateOne) SetNotNilActionLabel(value []uint64) *SopNodeUpdateOne {
 	if value != nil {
 		return sn.SetActionLabel(value)
 	}
@@ -1560,7 +1560,7 @@ func (sn *SopNodeUpdateOne) SetNotNilActionLabel(value []int) *SopNodeUpdateOne
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeCreate) SetNotNilActionLabel(value []int) *SopNodeCreate {
+func (sn *SopNodeCreate) SetNotNilActionLabel(value []uint64) *SopNodeCreate {
 	if value != nil {
 		return sn.SetActionLabel(value)
 	}
@@ -1784,7 +1784,7 @@ func (ss *SopStageCreate) SetNotNilActionMessage(value []custom_types.Action) *S
 }
 
 // set field if value's pointer is not nil.
-func (ss *SopStageUpdate) SetNotNilActionLabel(value []int) *SopStageUpdate {
+func (ss *SopStageUpdate) SetNotNilActionLabel(value []uint64) *SopStageUpdate {
 	if value != nil {
 		return ss.SetActionLabel(value)
 	}
@@ -1792,7 +1792,7 @@ func (ss *SopStageUpdate) SetNotNilActionLabel(value []int) *SopStageUpdate {
 }
 
 // set field if value's pointer is not nil.
-func (ss *SopStageUpdateOne) SetNotNilActionLabel(value []int) *SopStageUpdateOne {
+func (ss *SopStageUpdateOne) SetNotNilActionLabel(value []uint64) *SopStageUpdateOne {
 	if value != nil {
 		return ss.SetActionLabel(value)
 	}
@@ -1800,7 +1800,7 @@ func (ss *SopStageUpdateOne) SetNotNilActionLabel(value []int) *SopStageUpdateOn
 }
 
 // set field if value's pointer is not nil.
-func (ss *SopStageCreate) SetNotNilActionLabel(value []int) *SopStageCreate {
+func (ss *SopStageCreate) SetNotNilActionLabel(value []uint64) *SopStageCreate {
 	if value != nil {
 		return ss.SetActionLabel(value)
 	}

+ 18 - 2
ent/sopnode.go

@@ -41,7 +41,7 @@ type SopNode struct {
 	// 命中后发送的消息内容
 	ActionMessage []custom_types.Action `json:"action_message,omitempty"`
 	// 命中后需要打的标签
-	ActionLabel []int `json:"action_label,omitempty"`
+	ActionLabel []uint64 `json:"action_label,omitempty"`
 	// Edges holds the relations/edges for other nodes in the graph.
 	// The values are being populated by the SopNodeQuery when eager-loading is set.
 	Edges        SopNodeEdges `json:"edges"`
@@ -52,9 +52,11 @@ type SopNode struct {
 type SopNodeEdges struct {
 	// SopStage holds the value of the sop_stage edge.
 	SopStage *SopStage `json:"sop_stage,omitempty"`
+	// NodeMessages holds the value of the node_messages edge.
+	NodeMessages []*MessageRecords `json:"node_messages,omitempty"`
 	// loadedTypes holds the information for reporting if a
 	// type was loaded (or requested) in eager-loading or not.
-	loadedTypes [1]bool
+	loadedTypes [2]bool
 }
 
 // SopStageOrErr returns the SopStage value or an error if the edge
@@ -68,6 +70,15 @@ func (e SopNodeEdges) SopStageOrErr() (*SopStage, error) {
 	return nil, &NotLoadedError{edge: "sop_stage"}
 }
 
+// NodeMessagesOrErr returns the NodeMessages value or an error if the edge
+// was not loaded in eager-loading.
+func (e SopNodeEdges) NodeMessagesOrErr() ([]*MessageRecords, error) {
+	if e.loadedTypes[1] {
+		return e.NodeMessages, nil
+	}
+	return nil, &NotLoadedError{edge: "node_messages"}
+}
+
 // scanValues returns the types for scanning values from sql.Rows.
 func (*SopNode) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
@@ -192,6 +203,11 @@ func (sn *SopNode) QuerySopStage() *SopStageQuery {
 	return NewSopNodeClient(sn.config).QuerySopStage(sn)
 }
 
+// QueryNodeMessages queries the "node_messages" edge of the SopNode entity.
+func (sn *SopNode) QueryNodeMessages() *MessageRecordsQuery {
+	return NewSopNodeClient(sn.config).QueryNodeMessages(sn)
+}
+
 // Update returns a builder for updating this SopNode.
 // Note that you need to call SopNode.Unwrap() before calling this method if this SopNode
 // was returned from a transaction, and the transaction was committed or rolled back.

+ 30 - 0
ent/sopnode/sopnode.go

@@ -39,6 +39,8 @@ const (
 	FieldActionLabel = "action_label"
 	// EdgeSopStage holds the string denoting the sop_stage edge name in mutations.
 	EdgeSopStage = "sop_stage"
+	// EdgeNodeMessages holds the string denoting the node_messages edge name in mutations.
+	EdgeNodeMessages = "node_messages"
 	// Table holds the table name of the sopnode in the database.
 	Table = "sop_node"
 	// SopStageTable is the table that holds the sop_stage relation/edge.
@@ -48,6 +50,13 @@ const (
 	SopStageInverseTable = "sop_stage"
 	// SopStageColumn is the table column denoting the sop_stage relation/edge.
 	SopStageColumn = "stage_id"
+	// NodeMessagesTable is the table that holds the node_messages relation/edge.
+	NodeMessagesTable = "message_records"
+	// NodeMessagesInverseTable is the table name for the MessageRecords entity.
+	// It exists in this package in order to avoid circular dependency with the "messagerecords" package.
+	NodeMessagesInverseTable = "message_records"
+	// NodeMessagesColumn is the table column denoting the node_messages relation/edge.
+	NodeMessagesColumn = "sub_source_id"
 )
 
 // Columns holds all SQL columns for sopnode fields.
@@ -152,6 +161,20 @@ func BySopStageField(field string, opts ...sql.OrderTermOption) OrderOption {
 		sqlgraph.OrderByNeighborTerms(s, newSopStageStep(), sql.OrderByField(field, opts...))
 	}
 }
+
+// ByNodeMessagesCount orders the results by node_messages count.
+func ByNodeMessagesCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newNodeMessagesStep(), opts...)
+	}
+}
+
+// ByNodeMessages orders the results by node_messages terms.
+func ByNodeMessages(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newNodeMessagesStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
 func newSopStageStep() *sqlgraph.Step {
 	return sqlgraph.NewStep(
 		sqlgraph.From(Table, FieldID),
@@ -159,3 +182,10 @@ func newSopStageStep() *sqlgraph.Step {
 		sqlgraph.Edge(sqlgraph.M2O, true, SopStageTable, SopStageColumn),
 	)
 }
+func newNodeMessagesStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(NodeMessagesInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, NodeMessagesTable, NodeMessagesColumn),
+	)
+}

+ 23 - 0
ent/sopnode/where.go

@@ -493,6 +493,29 @@ func HasSopStageWith(preds ...predicate.SopStage) predicate.SopNode {
 	})
 }
 
+// HasNodeMessages applies the HasEdge predicate on the "node_messages" edge.
+func HasNodeMessages() predicate.SopNode {
+	return predicate.SopNode(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, NodeMessagesTable, NodeMessagesColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasNodeMessagesWith applies the HasEdge predicate on the "node_messages" edge with a given conditions (other predicates).
+func HasNodeMessagesWith(preds ...predicate.MessageRecords) predicate.SopNode {
+	return predicate.SopNode(func(s *sql.Selector) {
+		step := newNodeMessagesStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
 // And groups predicates with the AND operator between them.
 func And(predicates ...predicate.SopNode) predicate.SopNode {
 	return predicate.SopNode(sql.AndPredicates(predicates...))

+ 37 - 5
ent/sopnode_create.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 
@@ -133,8 +134,8 @@ func (snc *SopNodeCreate) SetActionMessage(ct []custom_types.Action) *SopNodeCre
 }
 
 // SetActionLabel sets the "action_label" field.
-func (snc *SopNodeCreate) SetActionLabel(i []int) *SopNodeCreate {
-	snc.mutation.SetActionLabel(i)
+func (snc *SopNodeCreate) SetActionLabel(u []uint64) *SopNodeCreate {
+	snc.mutation.SetActionLabel(u)
 	return snc
 }
 
@@ -155,6 +156,21 @@ func (snc *SopNodeCreate) SetSopStage(s *SopStage) *SopNodeCreate {
 	return snc.SetSopStageID(s.ID)
 }
 
+// AddNodeMessageIDs adds the "node_messages" edge to the MessageRecords entity by IDs.
+func (snc *SopNodeCreate) AddNodeMessageIDs(ids ...uint64) *SopNodeCreate {
+	snc.mutation.AddNodeMessageIDs(ids...)
+	return snc
+}
+
+// AddNodeMessages adds the "node_messages" edges to the MessageRecords entity.
+func (snc *SopNodeCreate) AddNodeMessages(m ...*MessageRecords) *SopNodeCreate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return snc.AddNodeMessageIDs(ids...)
+}
+
 // Mutation returns the SopNodeMutation object of the builder.
 func (snc *SopNodeCreate) Mutation() *SopNodeMutation {
 	return snc.mutation
@@ -334,6 +350,22 @@ func (snc *SopNodeCreate) createSpec() (*SopNode, *sqlgraph.CreateSpec) {
 		_node.StageID = nodes[0]
 		_spec.Edges = append(_spec.Edges, edge)
 	}
+	if nodes := snc.mutation.NodeMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
 	return _node, _spec
 }
 
@@ -537,7 +569,7 @@ func (u *SopNodeUpsert) ClearActionMessage() *SopNodeUpsert {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopNodeUpsert) SetActionLabel(v []int) *SopNodeUpsert {
+func (u *SopNodeUpsert) SetActionLabel(v []uint64) *SopNodeUpsert {
 	u.Set(sopnode.FieldActionLabel, v)
 	return u
 }
@@ -781,7 +813,7 @@ func (u *SopNodeUpsertOne) ClearActionMessage() *SopNodeUpsertOne {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopNodeUpsertOne) SetActionLabel(v []int) *SopNodeUpsertOne {
+func (u *SopNodeUpsertOne) SetActionLabel(v []uint64) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetActionLabel(v)
 	})
@@ -1194,7 +1226,7 @@ func (u *SopNodeUpsertBulk) ClearActionMessage() *SopNodeUpsertBulk {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopNodeUpsertBulk) SetActionLabel(v []int) *SopNodeUpsertBulk {
+func (u *SopNodeUpsertBulk) SetActionLabel(v []uint64) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetActionLabel(v)
 	})

+ 87 - 12
ent/sopnode_query.go

@@ -4,8 +4,10 @@ package ent
 
 import (
 	"context"
+	"database/sql/driver"
 	"fmt"
 	"math"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
@@ -18,11 +20,12 @@ import (
 // SopNodeQuery is the builder for querying SopNode entities.
 type SopNodeQuery struct {
 	config
-	ctx          *QueryContext
-	order        []sopnode.OrderOption
-	inters       []Interceptor
-	predicates   []predicate.SopNode
-	withSopStage *SopStageQuery
+	ctx              *QueryContext
+	order            []sopnode.OrderOption
+	inters           []Interceptor
+	predicates       []predicate.SopNode
+	withSopStage     *SopStageQuery
+	withNodeMessages *MessageRecordsQuery
 	// intermediate query (i.e. traversal path).
 	sql  *sql.Selector
 	path func(context.Context) (*sql.Selector, error)
@@ -81,6 +84,28 @@ func (snq *SopNodeQuery) QuerySopStage() *SopStageQuery {
 	return query
 }
 
+// QueryNodeMessages chains the current query on the "node_messages" edge.
+func (snq *SopNodeQuery) QueryNodeMessages() *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: snq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := snq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := snq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(sopnode.Table, sopnode.FieldID, selector),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, sopnode.NodeMessagesTable, sopnode.NodeMessagesColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(snq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
 // First returns the first SopNode entity from the query.
 // Returns a *NotFoundError when no SopNode was found.
 func (snq *SopNodeQuery) First(ctx context.Context) (*SopNode, error) {
@@ -268,12 +293,13 @@ func (snq *SopNodeQuery) Clone() *SopNodeQuery {
 		return nil
 	}
 	return &SopNodeQuery{
-		config:       snq.config,
-		ctx:          snq.ctx.Clone(),
-		order:        append([]sopnode.OrderOption{}, snq.order...),
-		inters:       append([]Interceptor{}, snq.inters...),
-		predicates:   append([]predicate.SopNode{}, snq.predicates...),
-		withSopStage: snq.withSopStage.Clone(),
+		config:           snq.config,
+		ctx:              snq.ctx.Clone(),
+		order:            append([]sopnode.OrderOption{}, snq.order...),
+		inters:           append([]Interceptor{}, snq.inters...),
+		predicates:       append([]predicate.SopNode{}, snq.predicates...),
+		withSopStage:     snq.withSopStage.Clone(),
+		withNodeMessages: snq.withNodeMessages.Clone(),
 		// clone intermediate query.
 		sql:  snq.sql.Clone(),
 		path: snq.path,
@@ -291,6 +317,17 @@ func (snq *SopNodeQuery) WithSopStage(opts ...func(*SopStageQuery)) *SopNodeQuer
 	return snq
 }
 
+// WithNodeMessages tells the query-builder to eager-load the nodes that are connected to
+// the "node_messages" edge. The optional arguments are used to configure the query builder of the edge.
+func (snq *SopNodeQuery) WithNodeMessages(opts ...func(*MessageRecordsQuery)) *SopNodeQuery {
+	query := (&MessageRecordsClient{config: snq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	snq.withNodeMessages = query
+	return snq
+}
+
 // 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.
 //
@@ -369,8 +406,9 @@ func (snq *SopNodeQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Sop
 	var (
 		nodes       = []*SopNode{}
 		_spec       = snq.querySpec()
-		loadedTypes = [1]bool{
+		loadedTypes = [2]bool{
 			snq.withSopStage != nil,
+			snq.withNodeMessages != nil,
 		}
 	)
 	_spec.ScanValues = func(columns []string) ([]any, error) {
@@ -397,6 +435,13 @@ func (snq *SopNodeQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Sop
 			return nil, err
 		}
 	}
+	if query := snq.withNodeMessages; query != nil {
+		if err := snq.loadNodeMessages(ctx, query, nodes,
+			func(n *SopNode) { n.Edges.NodeMessages = []*MessageRecords{} },
+			func(n *SopNode, e *MessageRecords) { n.Edges.NodeMessages = append(n.Edges.NodeMessages, e) }); err != nil {
+			return nil, err
+		}
+	}
 	return nodes, nil
 }
 
@@ -429,6 +474,36 @@ func (snq *SopNodeQuery) loadSopStage(ctx context.Context, query *SopStageQuery,
 	}
 	return nil
 }
+func (snq *SopNodeQuery) loadNodeMessages(ctx context.Context, query *MessageRecordsQuery, nodes []*SopNode, init func(*SopNode), assign func(*SopNode, *MessageRecords)) error {
+	fks := make([]driver.Value, 0, len(nodes))
+	nodeids := make(map[uint64]*SopNode)
+	for i := range nodes {
+		fks = append(fks, nodes[i].ID)
+		nodeids[nodes[i].ID] = nodes[i]
+		if init != nil {
+			init(nodes[i])
+		}
+	}
+	if len(query.ctx.Fields) > 0 {
+		query.ctx.AppendFieldOnce(messagerecords.FieldSubSourceID)
+	}
+	query.Where(predicate.MessageRecords(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(sopnode.NodeMessagesColumn), fks...))
+	}))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		fk := n.SubSourceID
+		node, ok := nodeids[fk]
+		if !ok {
+			return fmt.Errorf(`unexpected referenced foreign-key "sub_source_id" returned %v for node %v`, fk, n.ID)
+		}
+		assign(node, n)
+	}
+	return nil
+}
 
 func (snq *SopNodeQuery) sqlCount(ctx context.Context) (int, error) {
 	_spec := snq.querySpec()

+ 173 - 10
ent/sopnode_update.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
@@ -191,14 +192,14 @@ func (snu *SopNodeUpdate) ClearActionMessage() *SopNodeUpdate {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (snu *SopNodeUpdate) SetActionLabel(i []int) *SopNodeUpdate {
-	snu.mutation.SetActionLabel(i)
+func (snu *SopNodeUpdate) SetActionLabel(u []uint64) *SopNodeUpdate {
+	snu.mutation.SetActionLabel(u)
 	return snu
 }
 
-// AppendActionLabel appends i to the "action_label" field.
-func (snu *SopNodeUpdate) AppendActionLabel(i []int) *SopNodeUpdate {
-	snu.mutation.AppendActionLabel(i)
+// AppendActionLabel appends u to the "action_label" field.
+func (snu *SopNodeUpdate) AppendActionLabel(u []uint64) *SopNodeUpdate {
+	snu.mutation.AppendActionLabel(u)
 	return snu
 }
 
@@ -219,6 +220,21 @@ func (snu *SopNodeUpdate) SetSopStage(s *SopStage) *SopNodeUpdate {
 	return snu.SetSopStageID(s.ID)
 }
 
+// AddNodeMessageIDs adds the "node_messages" edge to the MessageRecords entity by IDs.
+func (snu *SopNodeUpdate) AddNodeMessageIDs(ids ...uint64) *SopNodeUpdate {
+	snu.mutation.AddNodeMessageIDs(ids...)
+	return snu
+}
+
+// AddNodeMessages adds the "node_messages" edges to the MessageRecords entity.
+func (snu *SopNodeUpdate) AddNodeMessages(m ...*MessageRecords) *SopNodeUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return snu.AddNodeMessageIDs(ids...)
+}
+
 // Mutation returns the SopNodeMutation object of the builder.
 func (snu *SopNodeUpdate) Mutation() *SopNodeMutation {
 	return snu.mutation
@@ -230,6 +246,27 @@ func (snu *SopNodeUpdate) ClearSopStage() *SopNodeUpdate {
 	return snu
 }
 
+// ClearNodeMessages clears all "node_messages" edges to the MessageRecords entity.
+func (snu *SopNodeUpdate) ClearNodeMessages() *SopNodeUpdate {
+	snu.mutation.ClearNodeMessages()
+	return snu
+}
+
+// RemoveNodeMessageIDs removes the "node_messages" edge to MessageRecords entities by IDs.
+func (snu *SopNodeUpdate) RemoveNodeMessageIDs(ids ...uint64) *SopNodeUpdate {
+	snu.mutation.RemoveNodeMessageIDs(ids...)
+	return snu
+}
+
+// RemoveNodeMessages removes "node_messages" edges to MessageRecords entities.
+func (snu *SopNodeUpdate) RemoveNodeMessages(m ...*MessageRecords) *SopNodeUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return snu.RemoveNodeMessageIDs(ids...)
+}
+
 // Save executes the query and returns the number of nodes affected by the update operation.
 func (snu *SopNodeUpdate) Save(ctx context.Context) (int, error) {
 	if err := snu.defaults(); err != nil {
@@ -387,6 +424,51 @@ func (snu *SopNodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if snu.mutation.NodeMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := snu.mutation.RemovedNodeMessagesIDs(); len(nodes) > 0 && !snu.mutation.NodeMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := snu.mutation.NodeMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	if n, err = sqlgraph.UpdateNodes(ctx, snu.driver, _spec); err != nil {
 		if _, ok := err.(*sqlgraph.NotFoundError); ok {
 			err = &NotFoundError{sopnode.Label}
@@ -567,14 +649,14 @@ func (snuo *SopNodeUpdateOne) ClearActionMessage() *SopNodeUpdateOne {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (snuo *SopNodeUpdateOne) SetActionLabel(i []int) *SopNodeUpdateOne {
-	snuo.mutation.SetActionLabel(i)
+func (snuo *SopNodeUpdateOne) SetActionLabel(u []uint64) *SopNodeUpdateOne {
+	snuo.mutation.SetActionLabel(u)
 	return snuo
 }
 
-// AppendActionLabel appends i to the "action_label" field.
-func (snuo *SopNodeUpdateOne) AppendActionLabel(i []int) *SopNodeUpdateOne {
-	snuo.mutation.AppendActionLabel(i)
+// AppendActionLabel appends u to the "action_label" field.
+func (snuo *SopNodeUpdateOne) AppendActionLabel(u []uint64) *SopNodeUpdateOne {
+	snuo.mutation.AppendActionLabel(u)
 	return snuo
 }
 
@@ -595,6 +677,21 @@ func (snuo *SopNodeUpdateOne) SetSopStage(s *SopStage) *SopNodeUpdateOne {
 	return snuo.SetSopStageID(s.ID)
 }
 
+// AddNodeMessageIDs adds the "node_messages" edge to the MessageRecords entity by IDs.
+func (snuo *SopNodeUpdateOne) AddNodeMessageIDs(ids ...uint64) *SopNodeUpdateOne {
+	snuo.mutation.AddNodeMessageIDs(ids...)
+	return snuo
+}
+
+// AddNodeMessages adds the "node_messages" edges to the MessageRecords entity.
+func (snuo *SopNodeUpdateOne) AddNodeMessages(m ...*MessageRecords) *SopNodeUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return snuo.AddNodeMessageIDs(ids...)
+}
+
 // Mutation returns the SopNodeMutation object of the builder.
 func (snuo *SopNodeUpdateOne) Mutation() *SopNodeMutation {
 	return snuo.mutation
@@ -606,6 +703,27 @@ func (snuo *SopNodeUpdateOne) ClearSopStage() *SopNodeUpdateOne {
 	return snuo
 }
 
+// ClearNodeMessages clears all "node_messages" edges to the MessageRecords entity.
+func (snuo *SopNodeUpdateOne) ClearNodeMessages() *SopNodeUpdateOne {
+	snuo.mutation.ClearNodeMessages()
+	return snuo
+}
+
+// RemoveNodeMessageIDs removes the "node_messages" edge to MessageRecords entities by IDs.
+func (snuo *SopNodeUpdateOne) RemoveNodeMessageIDs(ids ...uint64) *SopNodeUpdateOne {
+	snuo.mutation.RemoveNodeMessageIDs(ids...)
+	return snuo
+}
+
+// RemoveNodeMessages removes "node_messages" edges to MessageRecords entities.
+func (snuo *SopNodeUpdateOne) RemoveNodeMessages(m ...*MessageRecords) *SopNodeUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return snuo.RemoveNodeMessageIDs(ids...)
+}
+
 // Where appends a list predicates to the SopNodeUpdate builder.
 func (snuo *SopNodeUpdateOne) Where(ps ...predicate.SopNode) *SopNodeUpdateOne {
 	snuo.mutation.Where(ps...)
@@ -793,6 +911,51 @@ func (snuo *SopNodeUpdateOne) sqlSave(ctx context.Context) (_node *SopNode, err
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if snuo.mutation.NodeMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := snuo.mutation.RemovedNodeMessagesIDs(); len(nodes) > 0 && !snuo.mutation.NodeMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := snuo.mutation.NodeMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopnode.NodeMessagesTable,
+			Columns: []string{sopnode.NodeMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	_node = &SopNode{config: snuo.config}
 	_spec.Assign = _node.assignValues
 	_spec.ScanValues = _node.scanValues

+ 18 - 2
ent/sopstage.go

@@ -41,7 +41,7 @@ type SopStage struct {
 	// 命中后发送的消息内容
 	ActionMessage []custom_types.Action `json:"action_message,omitempty"`
 	// 命中后需要打的标签
-	ActionLabel []int `json:"action_label,omitempty"`
+	ActionLabel []uint64 `json:"action_label,omitempty"`
 	// 阶段顺序
 	IndexSort int `json:"index_sort,omitempty"`
 	// Edges holds the relations/edges for other nodes in the graph.
@@ -56,9 +56,11 @@ type SopStageEdges struct {
 	SopTask *SopTask `json:"sop_task,omitempty"`
 	// StageNodes holds the value of the stage_nodes edge.
 	StageNodes []*SopNode `json:"stage_nodes,omitempty"`
+	// StageMessages holds the value of the stage_messages edge.
+	StageMessages []*MessageRecords `json:"stage_messages,omitempty"`
 	// loadedTypes holds the information for reporting if a
 	// type was loaded (or requested) in eager-loading or not.
-	loadedTypes [2]bool
+	loadedTypes [3]bool
 }
 
 // SopTaskOrErr returns the SopTask value or an error if the edge
@@ -81,6 +83,15 @@ func (e SopStageEdges) StageNodesOrErr() ([]*SopNode, error) {
 	return nil, &NotLoadedError{edge: "stage_nodes"}
 }
 
+// StageMessagesOrErr returns the StageMessages value or an error if the edge
+// was not loaded in eager-loading.
+func (e SopStageEdges) StageMessagesOrErr() ([]*MessageRecords, error) {
+	if e.loadedTypes[2] {
+		return e.StageMessages, nil
+	}
+	return nil, &NotLoadedError{edge: "stage_messages"}
+}
+
 // scanValues returns the types for scanning values from sql.Rows.
 func (*SopStage) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
@@ -216,6 +227,11 @@ func (ss *SopStage) QueryStageNodes() *SopNodeQuery {
 	return NewSopStageClient(ss.config).QueryStageNodes(ss)
 }
 
+// QueryStageMessages queries the "stage_messages" edge of the SopStage entity.
+func (ss *SopStage) QueryStageMessages() *MessageRecordsQuery {
+	return NewSopStageClient(ss.config).QueryStageMessages(ss)
+}
+
 // Update returns a builder for updating this SopStage.
 // Note that you need to call SopStage.Unwrap() before calling this method if this SopStage
 // was returned from a transaction, and the transaction was committed or rolled back.

+ 30 - 0
ent/sopstage/sopstage.go

@@ -43,6 +43,8 @@ const (
 	EdgeSopTask = "sop_task"
 	// EdgeStageNodes holds the string denoting the stage_nodes edge name in mutations.
 	EdgeStageNodes = "stage_nodes"
+	// EdgeStageMessages holds the string denoting the stage_messages edge name in mutations.
+	EdgeStageMessages = "stage_messages"
 	// Table holds the table name of the sopstage in the database.
 	Table = "sop_stage"
 	// SopTaskTable is the table that holds the sop_task relation/edge.
@@ -59,6 +61,13 @@ const (
 	StageNodesInverseTable = "sop_node"
 	// StageNodesColumn is the table column denoting the stage_nodes relation/edge.
 	StageNodesColumn = "stage_id"
+	// StageMessagesTable is the table that holds the stage_messages relation/edge.
+	StageMessagesTable = "message_records"
+	// StageMessagesInverseTable is the table name for the MessageRecords entity.
+	// It exists in this package in order to avoid circular dependency with the "messagerecords" package.
+	StageMessagesInverseTable = "message_records"
+	// StageMessagesColumn is the table column denoting the stage_messages relation/edge.
+	StageMessagesColumn = "source_id"
 )
 
 // Columns holds all SQL columns for sopstage fields.
@@ -187,6 +196,20 @@ func ByStageNodes(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
 		sqlgraph.OrderByNeighborTerms(s, newStageNodesStep(), append([]sql.OrderTerm{term}, terms...)...)
 	}
 }
+
+// ByStageMessagesCount orders the results by stage_messages count.
+func ByStageMessagesCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newStageMessagesStep(), opts...)
+	}
+}
+
+// ByStageMessages orders the results by stage_messages terms.
+func ByStageMessages(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newStageMessagesStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
 func newSopTaskStep() *sqlgraph.Step {
 	return sqlgraph.NewStep(
 		sqlgraph.From(Table, FieldID),
@@ -201,3 +224,10 @@ func newStageNodesStep() *sqlgraph.Step {
 		sqlgraph.Edge(sqlgraph.O2M, false, StageNodesTable, StageNodesColumn),
 	)
 }
+func newStageMessagesStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(StageMessagesInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, StageMessagesTable, StageMessagesColumn),
+	)
+}

+ 23 - 0
ent/sopstage/where.go

@@ -561,6 +561,29 @@ func HasStageNodesWith(preds ...predicate.SopNode) predicate.SopStage {
 	})
 }
 
+// HasStageMessages applies the HasEdge predicate on the "stage_messages" edge.
+func HasStageMessages() predicate.SopStage {
+	return predicate.SopStage(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, StageMessagesTable, StageMessagesColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasStageMessagesWith applies the HasEdge predicate on the "stage_messages" edge with a given conditions (other predicates).
+func HasStageMessagesWith(preds ...predicate.MessageRecords) predicate.SopStage {
+	return predicate.SopStage(func(s *sql.Selector) {
+		step := newStageMessagesStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
 // And groups predicates with the AND operator between them.
 func And(predicates ...predicate.SopStage) predicate.SopStage {
 	return predicate.SopStage(sql.AndPredicates(predicates...))

+ 37 - 5
ent/sopstage_create.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
@@ -142,8 +143,8 @@ func (ssc *SopStageCreate) SetActionMessage(ct []custom_types.Action) *SopStageC
 }
 
 // SetActionLabel sets the "action_label" field.
-func (ssc *SopStageCreate) SetActionLabel(i []int) *SopStageCreate {
-	ssc.mutation.SetActionLabel(i)
+func (ssc *SopStageCreate) SetActionLabel(u []uint64) *SopStageCreate {
+	ssc.mutation.SetActionLabel(u)
 	return ssc
 }
 
@@ -193,6 +194,21 @@ func (ssc *SopStageCreate) AddStageNodes(s ...*SopNode) *SopStageCreate {
 	return ssc.AddStageNodeIDs(ids...)
 }
 
+// AddStageMessageIDs adds the "stage_messages" edge to the MessageRecords entity by IDs.
+func (ssc *SopStageCreate) AddStageMessageIDs(ids ...uint64) *SopStageCreate {
+	ssc.mutation.AddStageMessageIDs(ids...)
+	return ssc
+}
+
+// AddStageMessages adds the "stage_messages" edges to the MessageRecords entity.
+func (ssc *SopStageCreate) AddStageMessages(m ...*MessageRecords) *SopStageCreate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return ssc.AddStageMessageIDs(ids...)
+}
+
 // Mutation returns the SopStageMutation object of the builder.
 func (ssc *SopStageCreate) Mutation() *SopStageMutation {
 	return ssc.mutation
@@ -403,6 +419,22 @@ func (ssc *SopStageCreate) createSpec() (*SopStage, *sqlgraph.CreateSpec) {
 		}
 		_spec.Edges = append(_spec.Edges, edge)
 	}
+	if nodes := ssc.mutation.StageMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
 	return _node, _spec
 }
 
@@ -600,7 +632,7 @@ func (u *SopStageUpsert) ClearActionMessage() *SopStageUpsert {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopStageUpsert) SetActionLabel(v []int) *SopStageUpsert {
+func (u *SopStageUpsert) SetActionLabel(v []uint64) *SopStageUpsert {
 	u.Set(sopstage.FieldActionLabel, v)
 	return u
 }
@@ -861,7 +893,7 @@ func (u *SopStageUpsertOne) ClearActionMessage() *SopStageUpsertOne {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopStageUpsertOne) SetActionLabel(v []int) *SopStageUpsertOne {
+func (u *SopStageUpsertOne) SetActionLabel(v []uint64) *SopStageUpsertOne {
 	return u.Update(func(s *SopStageUpsert) {
 		s.SetActionLabel(v)
 	})
@@ -1295,7 +1327,7 @@ func (u *SopStageUpsertBulk) ClearActionMessage() *SopStageUpsertBulk {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (u *SopStageUpsertBulk) SetActionLabel(v []int) *SopStageUpsertBulk {
+func (u *SopStageUpsertBulk) SetActionLabel(v []uint64) *SopStageUpsertBulk {
 	return u.Update(func(s *SopStageUpsert) {
 		s.SetActionLabel(v)
 	})

+ 88 - 14
ent/sopstage_query.go

@@ -7,6 +7,7 @@ import (
 	"database/sql/driver"
 	"fmt"
 	"math"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
@@ -20,12 +21,13 @@ import (
 // SopStageQuery is the builder for querying SopStage entities.
 type SopStageQuery struct {
 	config
-	ctx            *QueryContext
-	order          []sopstage.OrderOption
-	inters         []Interceptor
-	predicates     []predicate.SopStage
-	withSopTask    *SopTaskQuery
-	withStageNodes *SopNodeQuery
+	ctx               *QueryContext
+	order             []sopstage.OrderOption
+	inters            []Interceptor
+	predicates        []predicate.SopStage
+	withSopTask       *SopTaskQuery
+	withStageNodes    *SopNodeQuery
+	withStageMessages *MessageRecordsQuery
 	// intermediate query (i.e. traversal path).
 	sql  *sql.Selector
 	path func(context.Context) (*sql.Selector, error)
@@ -106,6 +108,28 @@ func (ssq *SopStageQuery) QueryStageNodes() *SopNodeQuery {
 	return query
 }
 
+// QueryStageMessages chains the current query on the "stage_messages" edge.
+func (ssq *SopStageQuery) QueryStageMessages() *MessageRecordsQuery {
+	query := (&MessageRecordsClient{config: ssq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := ssq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := ssq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(sopstage.Table, sopstage.FieldID, selector),
+			sqlgraph.To(messagerecords.Table, messagerecords.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, sopstage.StageMessagesTable, sopstage.StageMessagesColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(ssq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
 // First returns the first SopStage entity from the query.
 // Returns a *NotFoundError when no SopStage was found.
 func (ssq *SopStageQuery) First(ctx context.Context) (*SopStage, error) {
@@ -293,13 +317,14 @@ func (ssq *SopStageQuery) Clone() *SopStageQuery {
 		return nil
 	}
 	return &SopStageQuery{
-		config:         ssq.config,
-		ctx:            ssq.ctx.Clone(),
-		order:          append([]sopstage.OrderOption{}, ssq.order...),
-		inters:         append([]Interceptor{}, ssq.inters...),
-		predicates:     append([]predicate.SopStage{}, ssq.predicates...),
-		withSopTask:    ssq.withSopTask.Clone(),
-		withStageNodes: ssq.withStageNodes.Clone(),
+		config:            ssq.config,
+		ctx:               ssq.ctx.Clone(),
+		order:             append([]sopstage.OrderOption{}, ssq.order...),
+		inters:            append([]Interceptor{}, ssq.inters...),
+		predicates:        append([]predicate.SopStage{}, ssq.predicates...),
+		withSopTask:       ssq.withSopTask.Clone(),
+		withStageNodes:    ssq.withStageNodes.Clone(),
+		withStageMessages: ssq.withStageMessages.Clone(),
 		// clone intermediate query.
 		sql:  ssq.sql.Clone(),
 		path: ssq.path,
@@ -328,6 +353,17 @@ func (ssq *SopStageQuery) WithStageNodes(opts ...func(*SopNodeQuery)) *SopStageQ
 	return ssq
 }
 
+// WithStageMessages tells the query-builder to eager-load the nodes that are connected to
+// the "stage_messages" edge. The optional arguments are used to configure the query builder of the edge.
+func (ssq *SopStageQuery) WithStageMessages(opts ...func(*MessageRecordsQuery)) *SopStageQuery {
+	query := (&MessageRecordsClient{config: ssq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	ssq.withStageMessages = query
+	return ssq
+}
+
 // 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.
 //
@@ -406,9 +442,10 @@ func (ssq *SopStageQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*So
 	var (
 		nodes       = []*SopStage{}
 		_spec       = ssq.querySpec()
-		loadedTypes = [2]bool{
+		loadedTypes = [3]bool{
 			ssq.withSopTask != nil,
 			ssq.withStageNodes != nil,
+			ssq.withStageMessages != nil,
 		}
 	)
 	_spec.ScanValues = func(columns []string) ([]any, error) {
@@ -442,6 +479,13 @@ func (ssq *SopStageQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*So
 			return nil, err
 		}
 	}
+	if query := ssq.withStageMessages; query != nil {
+		if err := ssq.loadStageMessages(ctx, query, nodes,
+			func(n *SopStage) { n.Edges.StageMessages = []*MessageRecords{} },
+			func(n *SopStage, e *MessageRecords) { n.Edges.StageMessages = append(n.Edges.StageMessages, e) }); err != nil {
+			return nil, err
+		}
+	}
 	return nodes, nil
 }
 
@@ -504,6 +548,36 @@ func (ssq *SopStageQuery) loadStageNodes(ctx context.Context, query *SopNodeQuer
 	}
 	return nil
 }
+func (ssq *SopStageQuery) loadStageMessages(ctx context.Context, query *MessageRecordsQuery, nodes []*SopStage, init func(*SopStage), assign func(*SopStage, *MessageRecords)) error {
+	fks := make([]driver.Value, 0, len(nodes))
+	nodeids := make(map[uint64]*SopStage)
+	for i := range nodes {
+		fks = append(fks, nodes[i].ID)
+		nodeids[nodes[i].ID] = nodes[i]
+		if init != nil {
+			init(nodes[i])
+		}
+	}
+	if len(query.ctx.Fields) > 0 {
+		query.ctx.AppendFieldOnce(messagerecords.FieldSourceID)
+	}
+	query.Where(predicate.MessageRecords(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(sopstage.StageMessagesColumn), fks...))
+	}))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		fk := n.SourceID
+		node, ok := nodeids[fk]
+		if !ok {
+			return fmt.Errorf(`unexpected referenced foreign-key "source_id" returned %v for node %v`, fk, n.ID)
+		}
+		assign(node, n)
+	}
+	return nil
+}
 
 func (ssq *SopStageQuery) sqlCount(ctx context.Context) (int, error) {
 	_spec := ssq.querySpec()

+ 173 - 10
ent/sopstage_update.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
@@ -186,14 +187,14 @@ func (ssu *SopStageUpdate) ClearActionMessage() *SopStageUpdate {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (ssu *SopStageUpdate) SetActionLabel(i []int) *SopStageUpdate {
-	ssu.mutation.SetActionLabel(i)
+func (ssu *SopStageUpdate) SetActionLabel(u []uint64) *SopStageUpdate {
+	ssu.mutation.SetActionLabel(u)
 	return ssu
 }
 
-// AppendActionLabel appends i to the "action_label" field.
-func (ssu *SopStageUpdate) AppendActionLabel(i []int) *SopStageUpdate {
-	ssu.mutation.AppendActionLabel(i)
+// AppendActionLabel appends u to the "action_label" field.
+func (ssu *SopStageUpdate) AppendActionLabel(u []uint64) *SopStageUpdate {
+	ssu.mutation.AppendActionLabel(u)
 	return ssu
 }
 
@@ -256,6 +257,21 @@ func (ssu *SopStageUpdate) AddStageNodes(s ...*SopNode) *SopStageUpdate {
 	return ssu.AddStageNodeIDs(ids...)
 }
 
+// AddStageMessageIDs adds the "stage_messages" edge to the MessageRecords entity by IDs.
+func (ssu *SopStageUpdate) AddStageMessageIDs(ids ...uint64) *SopStageUpdate {
+	ssu.mutation.AddStageMessageIDs(ids...)
+	return ssu
+}
+
+// AddStageMessages adds the "stage_messages" edges to the MessageRecords entity.
+func (ssu *SopStageUpdate) AddStageMessages(m ...*MessageRecords) *SopStageUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return ssu.AddStageMessageIDs(ids...)
+}
+
 // Mutation returns the SopStageMutation object of the builder.
 func (ssu *SopStageUpdate) Mutation() *SopStageMutation {
 	return ssu.mutation
@@ -288,6 +304,27 @@ func (ssu *SopStageUpdate) RemoveStageNodes(s ...*SopNode) *SopStageUpdate {
 	return ssu.RemoveStageNodeIDs(ids...)
 }
 
+// ClearStageMessages clears all "stage_messages" edges to the MessageRecords entity.
+func (ssu *SopStageUpdate) ClearStageMessages() *SopStageUpdate {
+	ssu.mutation.ClearStageMessages()
+	return ssu
+}
+
+// RemoveStageMessageIDs removes the "stage_messages" edge to MessageRecords entities by IDs.
+func (ssu *SopStageUpdate) RemoveStageMessageIDs(ids ...uint64) *SopStageUpdate {
+	ssu.mutation.RemoveStageMessageIDs(ids...)
+	return ssu
+}
+
+// RemoveStageMessages removes "stage_messages" edges to MessageRecords entities.
+func (ssu *SopStageUpdate) RemoveStageMessages(m ...*MessageRecords) *SopStageUpdate {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return ssu.RemoveStageMessageIDs(ids...)
+}
+
 // Save executes the query and returns the number of nodes affected by the update operation.
 func (ssu *SopStageUpdate) Save(ctx context.Context) (int, error) {
 	if err := ssu.defaults(); err != nil {
@@ -496,6 +533,51 @@ func (ssu *SopStageUpdate) sqlSave(ctx context.Context) (n int, err error) {
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if ssu.mutation.StageMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := ssu.mutation.RemovedStageMessagesIDs(); len(nodes) > 0 && !ssu.mutation.StageMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := ssu.mutation.StageMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	if n, err = sqlgraph.UpdateNodes(ctx, ssu.driver, _spec); err != nil {
 		if _, ok := err.(*sqlgraph.NotFoundError); ok {
 			err = &NotFoundError{sopstage.Label}
@@ -670,14 +752,14 @@ func (ssuo *SopStageUpdateOne) ClearActionMessage() *SopStageUpdateOne {
 }
 
 // SetActionLabel sets the "action_label" field.
-func (ssuo *SopStageUpdateOne) SetActionLabel(i []int) *SopStageUpdateOne {
-	ssuo.mutation.SetActionLabel(i)
+func (ssuo *SopStageUpdateOne) SetActionLabel(u []uint64) *SopStageUpdateOne {
+	ssuo.mutation.SetActionLabel(u)
 	return ssuo
 }
 
-// AppendActionLabel appends i to the "action_label" field.
-func (ssuo *SopStageUpdateOne) AppendActionLabel(i []int) *SopStageUpdateOne {
-	ssuo.mutation.AppendActionLabel(i)
+// AppendActionLabel appends u to the "action_label" field.
+func (ssuo *SopStageUpdateOne) AppendActionLabel(u []uint64) *SopStageUpdateOne {
+	ssuo.mutation.AppendActionLabel(u)
 	return ssuo
 }
 
@@ -740,6 +822,21 @@ func (ssuo *SopStageUpdateOne) AddStageNodes(s ...*SopNode) *SopStageUpdateOne {
 	return ssuo.AddStageNodeIDs(ids...)
 }
 
+// AddStageMessageIDs adds the "stage_messages" edge to the MessageRecords entity by IDs.
+func (ssuo *SopStageUpdateOne) AddStageMessageIDs(ids ...uint64) *SopStageUpdateOne {
+	ssuo.mutation.AddStageMessageIDs(ids...)
+	return ssuo
+}
+
+// AddStageMessages adds the "stage_messages" edges to the MessageRecords entity.
+func (ssuo *SopStageUpdateOne) AddStageMessages(m ...*MessageRecords) *SopStageUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return ssuo.AddStageMessageIDs(ids...)
+}
+
 // Mutation returns the SopStageMutation object of the builder.
 func (ssuo *SopStageUpdateOne) Mutation() *SopStageMutation {
 	return ssuo.mutation
@@ -772,6 +869,27 @@ func (ssuo *SopStageUpdateOne) RemoveStageNodes(s ...*SopNode) *SopStageUpdateOn
 	return ssuo.RemoveStageNodeIDs(ids...)
 }
 
+// ClearStageMessages clears all "stage_messages" edges to the MessageRecords entity.
+func (ssuo *SopStageUpdateOne) ClearStageMessages() *SopStageUpdateOne {
+	ssuo.mutation.ClearStageMessages()
+	return ssuo
+}
+
+// RemoveStageMessageIDs removes the "stage_messages" edge to MessageRecords entities by IDs.
+func (ssuo *SopStageUpdateOne) RemoveStageMessageIDs(ids ...uint64) *SopStageUpdateOne {
+	ssuo.mutation.RemoveStageMessageIDs(ids...)
+	return ssuo
+}
+
+// RemoveStageMessages removes "stage_messages" edges to MessageRecords entities.
+func (ssuo *SopStageUpdateOne) RemoveStageMessages(m ...*MessageRecords) *SopStageUpdateOne {
+	ids := make([]uint64, len(m))
+	for i := range m {
+		ids[i] = m[i].ID
+	}
+	return ssuo.RemoveStageMessageIDs(ids...)
+}
+
 // Where appends a list predicates to the SopStageUpdate builder.
 func (ssuo *SopStageUpdateOne) Where(ps ...predicate.SopStage) *SopStageUpdateOne {
 	ssuo.mutation.Where(ps...)
@@ -1010,6 +1128,51 @@ func (ssuo *SopStageUpdateOne) sqlSave(ctx context.Context) (_node *SopStage, er
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if ssuo.mutation.StageMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := ssuo.mutation.RemovedStageMessagesIDs(); len(nodes) > 0 && !ssuo.mutation.StageMessagesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := ssuo.mutation.StageMessagesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   sopstage.StageMessagesTable,
+			Columns: []string{sopstage.StageMessagesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(messagerecords.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	_node = &SopStage{config: ssuo.config}
 	_spec.Assign = _node.assignValues
 	_spec.ScanValues = _node.scanValues

+ 5 - 0
internal/handler/routes.go

@@ -324,6 +324,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/sop_task/detail",
 					Handler: sop_task.GetSopTaskDetailHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_task/publish",
+					Handler: sop_task.PublishSopTaskHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

+ 44 - 0
internal/handler/sop_task/publish_sop_task_handler.go

@@ -0,0 +1,44 @@
+package sop_task
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/sop_task"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /sop_task/publish sop_task PublishSopTask
+//
+// Publish sop task | 发布 SopTask
+//
+// Publish sop task | 发布 SopTask
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func PublishSopTaskHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := sop_task.NewPublishSopTaskLogic(r.Context(), svcCtx)
+		resp, err := l.PublishSopTask(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 164 - 21
internal/logic/label_relationship/update_label_relationships_logic.go

@@ -3,7 +3,12 @@ package label_relationship
 import (
 	"context"
 	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/custom_types"
 	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/soptask"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -25,14 +30,8 @@ func NewUpdateLabelRelationshipsLogic(ctx context.Context, svcCtx *svc.ServiceCo
 }
 
 func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.LabelRelationshipsInfo) (resp *types.BaseMsgResp, err error) {
-	l.Logger.Info("Start processing UpdateLabelRelationships request", "request", req)
-	defer func() {
-		if err != nil {
-			l.Logger.Error("Error occurred in UpdateLabelRelationships", "error", err)
-		} else {
-			l.Logger.Info("Successfully processed UpdateLabelRelationships request")
-		}
-	}()
+	// 获取联系人信息
+	c, err := l.svcCtx.DB.Contact.Query().Where(contact.ID(*req.ContactId)).Only(l.ctx)
 	// 获取联系人当前已关联的标签
 	currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(*req.ContactId)).All(l.ctx)
 	if err != nil {
@@ -48,30 +47,65 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 	// 对比新旧标签ID,找出需要新增和移除的标签
 	addLabelIds, removeLabelIds := compareLabelIds(req.LabelIds, currentLabelIds)
 
-	// 删除需要移除的标签关系
-	for _, id := range removeLabelIds {
-		_, err := l.svcCtx.DB.LabelRelationship.
-			Delete().
-			Where(
-				labelrelationship.ContactID(*req.ContactId),
-				labelrelationship.LabelID(id),
-			).
-			Exec(l.ctx)
-		if err != nil {
-			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	// 如果 req.UpdateType 为空,或 req.UpdateType 的值为 “all” 时
+	if req.UpdateType == nil || *req.UpdateType == "all" {
+		// 删除需要移除的标签关系
+		for _, id := range removeLabelIds {
+			_, err := l.svcCtx.DB.LabelRelationship.
+				Delete().
+				Where(
+					labelrelationship.ContactID(*req.ContactId),
+					labelrelationship.LabelID(id),
+				).
+				Exec(l.ctx)
+			if err != nil {
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
 		}
 	}
 
 	// 创建需要新增的标签关系
 	for _, id := range addLabelIds {
-		_, err := l.svcCtx.DB.LabelRelationship.Create().
+		_, _ = l.svcCtx.DB.LabelRelationship.Create().
 			SetLabelID(id).
 			SetContactID(*req.ContactId).
-			SetStatus(*req.Status).
 			Save(l.ctx)
+		//if err != nil {
+		//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		//}
+	}
+
+	currentLabelIds = req.LabelIds
+
+	// 获取所有 status 为 3 且 bot_wxid_list 包含 c.wx_wxid 的 sop_task
+	sopTasks, err := l.svcCtx.DB.SopTask.Query().Where(soptask.Status(3)).All(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	var filteredSopTasks []*ent.SopTask
+	for _, task := range sopTasks {
+		for _, botWxid := range task.BotWxidList {
+			if botWxid == c.WxWxid {
+				filteredSopTasks = append(filteredSopTasks, task)
+				break
+			}
+		}
+	}
+
+	// 获取所有 filteredSopTasks 的 sop_stages
+	var sopStages []*ent.SopStage
+	for _, task := range filteredSopTasks {
+		stages, err := task.QueryTaskStages().All(l.ctx)
 		if err != nil {
 			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 		}
+		sopStages = append(sopStages, stages...)
+	}
+
+	err = l.AddLabelRelationships(sopStages, *c, currentLabelIds)
+	if err != nil {
+		return nil, err
 	}
 
 	return &types.BaseMsgResp{
@@ -80,6 +114,88 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 	}, nil
 }
 
+func (l *UpdateLabelRelationshipsLogic) AddLabelRelationships(sopStages []*ent.SopStage, contact ent.Contact, currentLabelIds []uint64) (err error) {
+
+	// 遍历 sop_stages,找出满足条件的 stage
+	for _, stage := range sopStages {
+		if stage.ConditionType == 1 && isLabelIdListMatchFilter(currentLabelIds, stage.ConditionOperator, stage.ConditionList) {
+			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
+			_, err = l.svcCtx.DB.MessageRecords.Query().
+				Where(
+					messagerecords.ContactWxid(contact.Wxid),
+					messagerecords.SourceType(3),
+					messagerecords.SourceID(stage.ID),
+					messagerecords.SubSourceID(0),
+				).
+				Only(l.ctx)
+			if err == nil {
+				continue
+			}
+			// 判断ActionMessage是否为空
+			sourceType := 3
+			if stage.ActionMessage != nil {
+				for _, message := range stage.ActionMessage {
+					_, _ = l.svcCtx.DB.MessageRecords.Create().
+						SetNotNilBotWxid(&contact.WxWxid).
+						SetNotNilContactID(&contact.ID).
+						SetNotNilContactType(&contact.Type).
+						SetNotNilContactWxid(&contact.Wxid).
+						SetNotNilContentType(&message.Type).
+						SetNotNilContent(&message.Content).
+						SetNotNilSourceType(&sourceType).
+						SetNotNilSourceID(&stage.ID).
+						Save(l.ctx)
+
+					//if err != nil {
+					//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+					//}
+				}
+			}
+			if stage.ActionLabel != nil {
+				// 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
+				var newLabelIds []uint64
+				// 创建一个映射,用于快速查找 currentLabelIds 中的元素
+				currentLabelIdSet := make(map[uint64]struct{})
+				for _, id := range currentLabelIds {
+					currentLabelIdSet[id] = struct{}{}
+				}
+
+				// 遍历 addLabelIds,找出不在 currentLabelIds 中的元素
+				for _, id := range stage.ActionLabel {
+					if _, exists := currentLabelIdSet[id]; !exists {
+						newLabelIds = append(newLabelIds, id)
+					}
+				}
+
+				if len(newLabelIds) == 0 {
+					return nil
+				}
+
+				// 创建需要新增的标签关系
+				for _, id := range newLabelIds {
+					_, err = l.svcCtx.DB.LabelRelationship.Create().
+						SetLabelID(id).
+						SetContactID(contact.ID).
+						Save(l.ctx)
+					//if err != nil {
+					//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+					//}
+				}
+
+				// 合并 currentLabelIds 和 newLabelIds
+				currentLabelIds = append(currentLabelIds, newLabelIds...)
+				// 递归调用 AddLabelRelationships
+				err = l.AddLabelRelationships(sopStages, contact, currentLabelIds)
+				if err != nil {
+					return err
+				}
+			}
+		}
+
+	}
+	return nil
+}
+
 // compareLabelIds compares the new label ids with the current ones and returns the ids to be added and removed
 func compareLabelIds(newLabelIds []uint64, currentLabelIds []uint64) (addLabelIds []uint64, removeLabelIds []uint64) {
 	newLabelIdSet := make(map[uint64]struct{}, len(newLabelIds))
@@ -101,3 +217,30 @@ func compareLabelIds(newLabelIds []uint64, currentLabelIds []uint64) (addLabelId
 
 	return
 }
+
+func isLabelIdListMatchFilter(labelIdList []uint64, conditionOperator int, conditionList []custom_types.Condition) bool {
+	labelIdSet := make(map[uint64]struct{})
+	for _, id := range labelIdList {
+		labelIdSet[id] = struct{}{}
+	}
+
+	for _, condition := range conditionList {
+		match := false
+		for _, id := range condition.LabelIdList {
+			if _, ok := labelIdSet[id]; ok {
+				match = true
+				break
+			}
+		}
+
+		if condition.Equal == 2 {
+			match = !match
+		}
+
+		if (conditionOperator == 1 && !match) || (conditionOperator == 2 && match) {
+			return match
+		}
+	}
+
+	return conditionOperator == 1
+}

+ 251 - 0
internal/logic/sop_task/publish_sop_task_logic.go

@@ -0,0 +1,251 @@
+package sop_task
+
+import (
+	"context"
+	"errors"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/custom_types"
+	"wechat-api/ent/labelrelationship"
+	"wechat-api/ent/messagerecords"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/soptask"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type PublishSopTaskLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewPublishSopTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PublishSopTaskLogic {
+	return &PublishSopTaskLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
+	// 根据 id 查询 sop_task
+	sopTask, err := l.svcCtx.DB.SopTask.Query().
+		Where(
+			soptask.ID(req.Id),
+			soptask.Status(3),
+		).
+		WithTaskStages().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 判断 sop_task 是否存在
+	if sopTask != nil {
+		// 查询任务的所有 sop_stages
+		sopStages, err := l.svcCtx.DB.SopStage.Query().All(l.ctx)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+
+		// 遍历 stage
+		for _, stage := range sopTask.Edges.TaskStages {
+			if stage.ConditionType == 1 {
+				// 构造查询条件
+				var predicates []predicate.Contact
+
+				for _, condition := range stage.ConditionList {
+					subPredicate := contact.HasContactRelationshipsWith(labelrelationship.LabelIDIn(condition.LabelIdList...))
+					if condition.Equal == 2 {
+						subPredicate = contact.Not(subPredicate)
+					}
+					predicates = append(predicates, subPredicate)
+				}
+
+				// 查询满足条件的联系人
+				var contacts []*ent.Contact
+				var err error
+				sourceType := 3
+				if stage.ConditionOperator == 1 {
+					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.And(predicates...)).All(l.ctx)
+				} else {
+					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.Or(predicates...)).All(l.ctx)
+				}
+
+				if err != nil {
+					return nil, err
+				}
+
+				// 遍历 contacts
+				for _, c := range contacts {
+					// 判断联系人所属微信是否包含在任务当中
+					if sopTask.BotWxidList == nil || (sopTask.BotWxidList != nil && valueInArray(c.WxWxid, sopTask.BotWxidList)) {
+						for _, message := range stage.ActionMessage {
+							_, _ = l.svcCtx.DB.MessageRecords.Create().
+								SetNotNilBotWxid(&c.WxWxid).
+								SetNotNilContactID(&c.ID).
+								SetNotNilContactType(&c.Type).
+								SetNotNilContactWxid(&c.Wxid).
+								SetNotNilContentType(&message.Type).
+								SetNotNilContent(&message.Content).
+								SetNotNilSourceType(&sourceType).
+								SetNotNilSourceID(&stage.ID).
+								Save(l.ctx)
+
+							//if err != nil {
+							//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+							//}
+						}
+
+						// 查询当前联系人的标签关系
+						currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(c.ID)).All(l.ctx)
+						if err != nil {
+							return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+						}
+
+						// 提取当前标签ID
+						var currentLabelIds []uint64
+						for _, relationship := range currentLabelRelationships {
+							currentLabelIds = append(currentLabelIds, relationship.LabelID)
+						}
+
+						if stage.ActionLabel != nil {
+							// 递归调用 AddLabelRelationships
+							err = l.AddLabelRelationships(sopStages, *c, currentLabelIds, stage.ActionLabel)
+							if err != nil {
+								return nil, err
+							}
+						}
+					}
+				}
+			}
+		}
+		return &types.BaseMsgResp{Msg: errormsg.Success}, nil
+	} else {
+		// 返回错误信息:任务不存在
+		return nil, errors.New(errormsg.TargetNotFound)
+	}
+}
+
+func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, addLabelIds []uint64) (err error) {
+	// 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
+	var newLabelIds []uint64
+	// 创建一个映射,用于快速查找 currentLabelIds 中的元素
+	currentLabelIdSet := make(map[uint64]struct{})
+	for _, id := range currentLabelIds {
+		currentLabelIdSet[id] = struct{}{}
+	}
+
+	// 遍历 addLabelIds,找出不在 currentLabelIds 中的元素
+	for _, id := range addLabelIds {
+		if _, exists := currentLabelIdSet[id]; !exists {
+			newLabelIds = append(newLabelIds, id)
+		}
+	}
+
+	if len(newLabelIds) == 0 {
+		return nil
+	}
+
+	// 创建需要新增的标签关系
+	for _, id := range newLabelIds {
+		_, err = l.svcCtx.DB.LabelRelationship.Create().
+			SetLabelID(id).
+			SetContactID(contact.ID).
+			Save(l.ctx)
+		if err != nil {
+			return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+		}
+	}
+
+	// 合并 currentLabelIds 和 newLabelIds
+	currentLabelIds = append(currentLabelIds, newLabelIds...)
+
+	// 遍历 sop_stages,找出满足条件的 stage
+	for _, stage := range sopStages {
+		if stage.ConditionType == 1 && isLabelIdListMatchFilter(currentLabelIds, stage.ConditionOperator, stage.ConditionList) {
+			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
+			_, err = l.svcCtx.DB.MessageRecords.Query().
+				Where(
+					messagerecords.ContactWxid(contact.Wxid),
+					messagerecords.SourceType(3),
+					messagerecords.SourceID(stage.ID),
+					messagerecords.SubSourceID(0),
+				).
+				Only(l.ctx)
+			if err == nil {
+				continue
+			}
+			// 判断ActionMessage是否为空
+			sourceType := 3
+			if stage.ActionMessage != nil {
+				for _, message := range stage.ActionMessage {
+					_, _ = l.svcCtx.DB.MessageRecords.Create().
+						SetNotNilBotWxid(&contact.WxWxid).
+						SetNotNilContactID(&contact.ID).
+						SetNotNilContactType(&contact.Type).
+						SetNotNilContactWxid(&contact.Wxid).
+						SetNotNilContentType(&message.Type).
+						SetNotNilContent(&message.Content).
+						SetNotNilSourceType(&sourceType).
+						SetNotNilSourceID(&stage.ID).
+						Save(l.ctx)
+
+					//if err != nil {
+					//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+					//}
+				}
+			}
+			if stage.ActionLabel != nil {
+				// 递归调用 AddLabelRelationships
+				err = l.AddLabelRelationships(sopStages, contact, currentLabelIds, stage.ActionLabel)
+				if err != nil {
+					return err
+				}
+			}
+		}
+
+	}
+	return nil
+}
+
+func valueInArray(val string, array []string) bool {
+	for _, item := range array {
+		if item == val {
+			return true
+		}
+	}
+	return false
+}
+
+func isLabelIdListMatchFilter(labelIdList []uint64, conditionOperator int, conditionList []custom_types.Condition) bool {
+	labelIdSet := make(map[uint64]struct{})
+	for _, id := range labelIdList {
+		labelIdSet[id] = struct{}{}
+	}
+
+	for _, condition := range conditionList {
+		match := false
+		for _, id := range condition.LabelIdList {
+			if _, ok := labelIdSet[id]; ok {
+				match = true
+				break
+			}
+		}
+
+		if condition.Equal == 2 {
+			match = !match
+		}
+
+		if (conditionOperator == 1 && !match) || (conditionOperator == 2 && match) {
+			return match
+		}
+	}
+
+	return conditionOperator == 1
+}

+ 7 - 7
internal/types/types.go

@@ -533,8 +533,8 @@ type LabelRelationshipInfo struct {
 // swagger:model LabelRelationshipsInfo
 type LabelRelationshipsInfo struct {
 	BaseIDInfo
-	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
-	Status *uint8 `json:"status,optional"`
+	// 更新类型:为空或“all”时表示全量更新,为 “add” 时表示仅追加
+	UpdateType *string `json:"updateType,optional"`
 	// 标签 ID
 	LabelIds []uint64 `json:"labelIds,optional"`
 	// 联系人 ID
@@ -726,7 +726,7 @@ type SopStageInfo struct {
 	// 命中后发送的消息内容
 	ActionMessage []Action `json:"actionMessage,optional"`
 	// 命中后需要打的标签
-	ActionLabel []int `json:"actionLabel,optional"`
+	ActionLabel []uint64 `json:"actionLabel,optional"`
 	// 阶段顺序
 	IndexSort *int `json:"indexSort,optional"`
 	// sop 任务信息
@@ -776,7 +776,7 @@ type SopNodeInfo struct {
 	// 命中后发送的消息内容
 	ActionMessage []Action `json:"actionMessage,optional"`
 	// 命中后需要打的标签
-	ActionLabel []int `json:"actionLabel,optional"`
+	ActionLabel []uint64 `json:"actionLabel,optional"`
 	// 阶段信息
 	StageInfo *SopStageInfo `json:"stageInfo,optional"`
 }
@@ -858,7 +858,7 @@ type MessageRecordsInfo struct {
 	// 机器人微信 id
 	BotWxid *string `json:"botWxid,optional"`
 	// 联系人 id
-	ContactId *int `json:"contactId,optional"`
+	ContactId *uint64 `json:"contactId,optional"`
 	// 类型:1好友,2群组,3企业微信联系人
 	ContactType *int `json:"contactType,optional"`
 	// 接收方微信 id
@@ -874,9 +874,9 @@ type MessageRecordsInfo struct {
 	// 源类型 1 点发 2 群发 3 SOP
 	SourceType *int `json:"sourceType,optional"`
 	// 源 ID
-	SourceId *int `json:"sourceId,optional"`
+	SourceId *uint64 `json:"sourceId,optional"`
 	// 次源 ID
-	SubSourceId *int `json:"subSourceId,optional"`
+	SubSourceId *uint64 `json:"subSourceId,optional"`
 }
 
 // The response data of message records list | MessageRecords列表数据

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác