浏览代码

增加智能表单接口

boweniac 2 周之前
父节点
当前提交
c2d59a8f7a
共有 53 个文件被更改,包括 9392 次插入242 次删除
  1. 2 1
      desc/all.api
  2. 65 0
      desc/wechat/contact_field_template.api
  3. 3 0
      desc/wechat/label_relationship.api
  4. 433 112
      ent/client.go
  5. 18 2
      ent/contact.go
  6. 30 0
      ent/contact/contact.go
  7. 23 0
      ent/contact/where.go
  8. 32 0
      ent/contact_create.go
  9. 75 1
      ent/contact_query.go
  10. 163 0
      ent/contact_update.go
  11. 206 0
      ent/contactfield.go
  12. 137 0
      ent/contactfield/contactfield.go
  13. 389 0
      ent/contactfield/where.go
  14. 922 0
      ent/contactfield_create.go
  15. 88 0
      ent/contactfield_delete.go
  16. 605 0
      ent/contactfield_query.go
  17. 566 0
      ent/contactfield_update.go
  18. 165 0
      ent/contactfieldtemplate.go
  19. 105 0
      ent/contactfieldtemplate/contactfieldtemplate.go
  20. 315 0
      ent/contactfieldtemplate/where.go
  21. 862 0
      ent/contactfieldtemplate_create.go
  22. 88 0
      ent/contactfieldtemplate_delete.go
  23. 526 0
      ent/contactfieldtemplate_query.go
  24. 444 0
      ent/contactfieldtemplate_update.go
  25. 13 0
      ent/custom_types/types.go
  26. 45 41
      ent/ent.go
  27. 24 0
      ent/hook/hook.go
  28. 60 0
      ent/intercept/intercept.go
  29. 50 0
      ent/migrate/schema.go
  30. 1677 44
      ent/mutation.go
  31. 164 0
      ent/pagination.go
  32. 6 0
      ent/predicate/predicate.go
  33. 60 0
      ent/runtime/runtime.go
  34. 1 0
      ent/schema/contact.go
  35. 59 0
      ent/schema/contact_field.go
  36. 50 0
      ent/schema/contact_field_template.go
  37. 264 0
      ent/set_not_nil.go
  38. 6 0
      ent/tx.go
  39. 4 0
      go.sum
  40. 44 0
      internal/handler/contact_field_template/create_contact_field_template_handler.go
  41. 44 0
      internal/handler/contact_field_template/delete_contact_field_template_handler.go
  42. 44 0
      internal/handler/contact_field_template/get_contact_field_template_by_id_handler.go
  43. 44 0
      internal/handler/contact_field_template/update_contact_field_template_handler.go
  44. 30 0
      internal/handler/routes.go
  45. 32 2
      internal/logic/contact/create_contact_logic.go
  46. 71 27
      internal/logic/contact/get_contact_by_id_logic.go
  47. 26 0
      internal/logic/contact/get_contact_list_logic.go
  48. 49 1
      internal/logic/contact/update_contact_logic.go
  49. 62 0
      internal/logic/contact_field_template/create_contact_field_template_logic.go
  50. 42 0
      internal/logic/contact_field_template/delete_contact_field_template_logic.go
  51. 66 0
      internal/logic/contact_field_template/get_contact_field_template_by_id_logic.go
  52. 50 0
      internal/logic/contact_field_template/update_contact_field_template_logic.go
  53. 43 11
      internal/types/types.go

+ 2 - 1
desc/all.api

@@ -45,4 +45,5 @@ import "./wechat/whatsapp.api"
 import "./wechat/whatsapp_channel.api"
 import "./wechat/fastgpt.api"
 import "./wechat/department.api"
-import "./wechat/api_key.api"
+import "./wechat/api_key.api"
+import "./wechat/contact_field_template.api"

+ 65 - 0
desc/wechat/contact_field_template.api

@@ -0,0 +1,65 @@
+import "../base.api"
+
+type (
+
+    ContactFieldTemplateOptions {
+        Label *string `json:"label,optional"`
+
+        Value    *string `json:"value,optional"`
+    }
+    ContactFieldTemplate {
+        Type  *string `json:"type,optional"`
+
+        Id    *string `json:"id,optional"`
+
+        Label *string `json:"label,optional"`
+
+        Options []ContactFieldTemplateOptions `json:"options,optional"`
+
+        Value    []string `json:"value,optional"`
+    }
+
+    ContactFieldTemplateInfo {
+        BaseIDInfo
+
+        // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+        Status  *uint8 `json:"status,optional"`
+
+        // 组织ID
+        OrganizationId *uint64 `json:"organizationId,optional"`
+
+        Template []ContactFieldTemplate `json:"template,optional"`
+    }
+
+    // Contact information response | Contact信息返回体
+    ContactFieldTemplateInfoResp {
+        BaseDataInfo
+
+        // Contact information | Contact数据
+        Data []ContactFieldTemplate `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: contact_field_template
+    middleware: Authority
+)
+
+service Wechat {
+    // Create contact_field_template information | 创建 ContactFieldTemplate
+    @handler createContactFieldTemplate
+    post /contact_field_template/create (ContactFieldTemplateInfo) returns (BaseMsgResp)
+
+    // Update contact_field_template information | 更新 ContactFieldTemplate
+    @handler updateContactFieldTemplate
+    post /contact_field_template/update (ContactFieldTemplateInfo) returns (BaseMsgResp)
+
+    // Delete contact_field_template information | 删除 ContactFieldTemplate 信息
+    @handler deleteContactFieldTemplate
+    post /contact_field_template/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get contact_field_template by ID | 通过ID获取 ContactFieldTemplate
+    @handler getContactFieldTemplateById
+    post /contact_field_template (IDReq) returns (ContactFieldTemplateInfoResp)
+}

+ 3 - 0
desc/wechat/label_relationship.api

@@ -1,4 +1,5 @@
 import "../base.api"
+import "./contact_field_template.api"
 
 type (
     // ContactLabelList | Contact标签列表
@@ -84,6 +85,8 @@ type (
 		Ctitle *string `json:"ctitle,optional"`
 		Cc *string `json:"cc,optional"`
 		Phone *string `json:"phone,optional"`
+
+		CustomFields []ContactFieldTemplate `json:"customFields,optional"`
     }
     // The response data of label information | Label信息
     LabelInfo {

+ 433 - 112
ent/client.go

@@ -21,6 +21,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/employee"
@@ -86,6 +88,10 @@ type Client struct {
 	ChatSession *ChatSessionClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
+	// ContactField is the client for interacting with the ContactField builders.
+	ContactField *ContactFieldClient
+	// ContactFieldTemplate is the client for interacting with the ContactFieldTemplate builders.
+	ContactFieldTemplate *ContactFieldTemplateClient
 	// CreditBalance is the client for interacting with the CreditBalance builders.
 	CreditBalance *CreditBalanceClient
 	// CreditUsage is the client for interacting with the CreditUsage builders.
@@ -169,6 +175,8 @@ func (c *Client) init() {
 	c.ChatRecords = NewChatRecordsClient(c.config)
 	c.ChatSession = NewChatSessionClient(c.config)
 	c.Contact = NewContactClient(c.config)
+	c.ContactField = NewContactFieldClient(c.config)
+	c.ContactFieldTemplate = NewContactFieldTemplateClient(c.config)
 	c.CreditBalance = NewCreditBalanceClient(c.config)
 	c.CreditUsage = NewCreditUsageClient(c.config)
 	c.Employee = NewEmployeeClient(c.config)
@@ -290,49 +298,51 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 	cfg := c.config
 	cfg.driver = tx
 	return &Tx{
-		ctx:                 ctx,
-		config:              cfg,
-		Agent:               NewAgentClient(cfg),
-		AgentBase:           NewAgentBaseClient(cfg),
-		AliyunAvatar:        NewAliyunAvatarClient(cfg),
-		AllocAgent:          NewAllocAgentClient(cfg),
-		ApiKey:              NewApiKeyClient(cfg),
-		BatchMsg:            NewBatchMsgClient(cfg),
-		Category:            NewCategoryClient(cfg),
-		ChatRecords:         NewChatRecordsClient(cfg),
-		ChatSession:         NewChatSessionClient(cfg),
-		Contact:             NewContactClient(cfg),
-		CreditBalance:       NewCreditBalanceClient(cfg),
-		CreditUsage:         NewCreditUsageClient(cfg),
-		Employee:            NewEmployeeClient(cfg),
-		EmployeeConfig:      NewEmployeeConfigClient(cfg),
-		Label:               NewLabelClient(cfg),
-		LabelRelationship:   NewLabelRelationshipClient(cfg),
-		LabelTagging:        NewLabelTaggingClient(cfg),
-		Message:             NewMessageClient(cfg),
-		MessageRecords:      NewMessageRecordsClient(cfg),
-		Msg:                 NewMsgClient(cfg),
-		PayRecharge:         NewPayRechargeClient(cfg),
-		Server:              NewServerClient(cfg),
-		SopNode:             NewSopNodeClient(cfg),
-		SopStage:            NewSopStageClient(cfg),
-		SopTask:             NewSopTaskClient(cfg),
-		Token:               NewTokenClient(cfg),
-		Tutorial:            NewTutorialClient(cfg),
-		UsageDetail:         NewUsageDetailClient(cfg),
-		UsageStatisticDay:   NewUsageStatisticDayClient(cfg),
-		UsageStatisticHour:  NewUsageStatisticHourClient(cfg),
-		UsageStatisticMonth: NewUsageStatisticMonthClient(cfg),
-		UsageTotal:          NewUsageTotalClient(cfg),
-		Whatsapp:            NewWhatsappClient(cfg),
-		WhatsappChannel:     NewWhatsappChannelClient(cfg),
-		WorkExperience:      NewWorkExperienceClient(cfg),
-		WpChatroom:          NewWpChatroomClient(cfg),
-		WpChatroomMember:    NewWpChatroomMemberClient(cfg),
-		Wx:                  NewWxClient(cfg),
-		WxCard:              NewWxCardClient(cfg),
-		WxCardUser:          NewWxCardUserClient(cfg),
-		WxCardVisit:         NewWxCardVisitClient(cfg),
+		ctx:                  ctx,
+		config:               cfg,
+		Agent:                NewAgentClient(cfg),
+		AgentBase:            NewAgentBaseClient(cfg),
+		AliyunAvatar:         NewAliyunAvatarClient(cfg),
+		AllocAgent:           NewAllocAgentClient(cfg),
+		ApiKey:               NewApiKeyClient(cfg),
+		BatchMsg:             NewBatchMsgClient(cfg),
+		Category:             NewCategoryClient(cfg),
+		ChatRecords:          NewChatRecordsClient(cfg),
+		ChatSession:          NewChatSessionClient(cfg),
+		Contact:              NewContactClient(cfg),
+		ContactField:         NewContactFieldClient(cfg),
+		ContactFieldTemplate: NewContactFieldTemplateClient(cfg),
+		CreditBalance:        NewCreditBalanceClient(cfg),
+		CreditUsage:          NewCreditUsageClient(cfg),
+		Employee:             NewEmployeeClient(cfg),
+		EmployeeConfig:       NewEmployeeConfigClient(cfg),
+		Label:                NewLabelClient(cfg),
+		LabelRelationship:    NewLabelRelationshipClient(cfg),
+		LabelTagging:         NewLabelTaggingClient(cfg),
+		Message:              NewMessageClient(cfg),
+		MessageRecords:       NewMessageRecordsClient(cfg),
+		Msg:                  NewMsgClient(cfg),
+		PayRecharge:          NewPayRechargeClient(cfg),
+		Server:               NewServerClient(cfg),
+		SopNode:              NewSopNodeClient(cfg),
+		SopStage:             NewSopStageClient(cfg),
+		SopTask:              NewSopTaskClient(cfg),
+		Token:                NewTokenClient(cfg),
+		Tutorial:             NewTutorialClient(cfg),
+		UsageDetail:          NewUsageDetailClient(cfg),
+		UsageStatisticDay:    NewUsageStatisticDayClient(cfg),
+		UsageStatisticHour:   NewUsageStatisticHourClient(cfg),
+		UsageStatisticMonth:  NewUsageStatisticMonthClient(cfg),
+		UsageTotal:           NewUsageTotalClient(cfg),
+		Whatsapp:             NewWhatsappClient(cfg),
+		WhatsappChannel:      NewWhatsappChannelClient(cfg),
+		WorkExperience:       NewWorkExperienceClient(cfg),
+		WpChatroom:           NewWpChatroomClient(cfg),
+		WpChatroomMember:     NewWpChatroomMemberClient(cfg),
+		Wx:                   NewWxClient(cfg),
+		WxCard:               NewWxCardClient(cfg),
+		WxCardUser:           NewWxCardUserClient(cfg),
+		WxCardVisit:          NewWxCardVisitClient(cfg),
 	}, nil
 }
 
@@ -350,49 +360,51 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 	cfg := c.config
 	cfg.driver = &txDriver{tx: tx, drv: c.driver}
 	return &Tx{
-		ctx:                 ctx,
-		config:              cfg,
-		Agent:               NewAgentClient(cfg),
-		AgentBase:           NewAgentBaseClient(cfg),
-		AliyunAvatar:        NewAliyunAvatarClient(cfg),
-		AllocAgent:          NewAllocAgentClient(cfg),
-		ApiKey:              NewApiKeyClient(cfg),
-		BatchMsg:            NewBatchMsgClient(cfg),
-		Category:            NewCategoryClient(cfg),
-		ChatRecords:         NewChatRecordsClient(cfg),
-		ChatSession:         NewChatSessionClient(cfg),
-		Contact:             NewContactClient(cfg),
-		CreditBalance:       NewCreditBalanceClient(cfg),
-		CreditUsage:         NewCreditUsageClient(cfg),
-		Employee:            NewEmployeeClient(cfg),
-		EmployeeConfig:      NewEmployeeConfigClient(cfg),
-		Label:               NewLabelClient(cfg),
-		LabelRelationship:   NewLabelRelationshipClient(cfg),
-		LabelTagging:        NewLabelTaggingClient(cfg),
-		Message:             NewMessageClient(cfg),
-		MessageRecords:      NewMessageRecordsClient(cfg),
-		Msg:                 NewMsgClient(cfg),
-		PayRecharge:         NewPayRechargeClient(cfg),
-		Server:              NewServerClient(cfg),
-		SopNode:             NewSopNodeClient(cfg),
-		SopStage:            NewSopStageClient(cfg),
-		SopTask:             NewSopTaskClient(cfg),
-		Token:               NewTokenClient(cfg),
-		Tutorial:            NewTutorialClient(cfg),
-		UsageDetail:         NewUsageDetailClient(cfg),
-		UsageStatisticDay:   NewUsageStatisticDayClient(cfg),
-		UsageStatisticHour:  NewUsageStatisticHourClient(cfg),
-		UsageStatisticMonth: NewUsageStatisticMonthClient(cfg),
-		UsageTotal:          NewUsageTotalClient(cfg),
-		Whatsapp:            NewWhatsappClient(cfg),
-		WhatsappChannel:     NewWhatsappChannelClient(cfg),
-		WorkExperience:      NewWorkExperienceClient(cfg),
-		WpChatroom:          NewWpChatroomClient(cfg),
-		WpChatroomMember:    NewWpChatroomMemberClient(cfg),
-		Wx:                  NewWxClient(cfg),
-		WxCard:              NewWxCardClient(cfg),
-		WxCardUser:          NewWxCardUserClient(cfg),
-		WxCardVisit:         NewWxCardVisitClient(cfg),
+		ctx:                  ctx,
+		config:               cfg,
+		Agent:                NewAgentClient(cfg),
+		AgentBase:            NewAgentBaseClient(cfg),
+		AliyunAvatar:         NewAliyunAvatarClient(cfg),
+		AllocAgent:           NewAllocAgentClient(cfg),
+		ApiKey:               NewApiKeyClient(cfg),
+		BatchMsg:             NewBatchMsgClient(cfg),
+		Category:             NewCategoryClient(cfg),
+		ChatRecords:          NewChatRecordsClient(cfg),
+		ChatSession:          NewChatSessionClient(cfg),
+		Contact:              NewContactClient(cfg),
+		ContactField:         NewContactFieldClient(cfg),
+		ContactFieldTemplate: NewContactFieldTemplateClient(cfg),
+		CreditBalance:        NewCreditBalanceClient(cfg),
+		CreditUsage:          NewCreditUsageClient(cfg),
+		Employee:             NewEmployeeClient(cfg),
+		EmployeeConfig:       NewEmployeeConfigClient(cfg),
+		Label:                NewLabelClient(cfg),
+		LabelRelationship:    NewLabelRelationshipClient(cfg),
+		LabelTagging:         NewLabelTaggingClient(cfg),
+		Message:              NewMessageClient(cfg),
+		MessageRecords:       NewMessageRecordsClient(cfg),
+		Msg:                  NewMsgClient(cfg),
+		PayRecharge:          NewPayRechargeClient(cfg),
+		Server:               NewServerClient(cfg),
+		SopNode:              NewSopNodeClient(cfg),
+		SopStage:             NewSopStageClient(cfg),
+		SopTask:              NewSopTaskClient(cfg),
+		Token:                NewTokenClient(cfg),
+		Tutorial:             NewTutorialClient(cfg),
+		UsageDetail:          NewUsageDetailClient(cfg),
+		UsageStatisticDay:    NewUsageStatisticDayClient(cfg),
+		UsageStatisticHour:   NewUsageStatisticHourClient(cfg),
+		UsageStatisticMonth:  NewUsageStatisticMonthClient(cfg),
+		UsageTotal:           NewUsageTotalClient(cfg),
+		Whatsapp:             NewWhatsappClient(cfg),
+		WhatsappChannel:      NewWhatsappChannelClient(cfg),
+		WorkExperience:       NewWorkExperienceClient(cfg),
+		WpChatroom:           NewWpChatroomClient(cfg),
+		WpChatroomMember:     NewWpChatroomMemberClient(cfg),
+		Wx:                   NewWxClient(cfg),
+		WxCard:               NewWxCardClient(cfg),
+		WxCardUser:           NewWxCardUserClient(cfg),
+		WxCardVisit:          NewWxCardVisitClient(cfg),
 	}, nil
 }
 
@@ -423,13 +435,14 @@ func (c *Client) Close() error {
 func (c *Client) Use(hooks ...Hook) {
 	for _, n := range []interface{ Use(...Hook) }{
 		c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent, c.ApiKey, c.BatchMsg,
-		c.Category, c.ChatRecords, c.ChatSession, c.Contact, c.CreditBalance,
-		c.CreditUsage, c.Employee, c.EmployeeConfig, c.Label, c.LabelRelationship,
-		c.LabelTagging, c.Message, c.MessageRecords, c.Msg, c.PayRecharge, c.Server,
-		c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial, c.UsageDetail,
-		c.UsageStatisticDay, c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal,
-		c.Whatsapp, c.WhatsappChannel, c.WorkExperience, c.WpChatroom,
-		c.WpChatroomMember, c.Wx, c.WxCard, c.WxCardUser, c.WxCardVisit,
+		c.Category, c.ChatRecords, c.ChatSession, c.Contact, c.ContactField,
+		c.ContactFieldTemplate, c.CreditBalance, c.CreditUsage, c.Employee,
+		c.EmployeeConfig, c.Label, c.LabelRelationship, c.LabelTagging, c.Message,
+		c.MessageRecords, c.Msg, c.PayRecharge, c.Server, c.SopNode, c.SopStage,
+		c.SopTask, c.Token, c.Tutorial, c.UsageDetail, c.UsageStatisticDay,
+		c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal, c.Whatsapp,
+		c.WhatsappChannel, c.WorkExperience, c.WpChatroom, c.WpChatroomMember, c.Wx,
+		c.WxCard, c.WxCardUser, c.WxCardVisit,
 	} {
 		n.Use(hooks...)
 	}
@@ -440,13 +453,14 @@ func (c *Client) Use(hooks ...Hook) {
 func (c *Client) Intercept(interceptors ...Interceptor) {
 	for _, n := range []interface{ Intercept(...Interceptor) }{
 		c.Agent, c.AgentBase, c.AliyunAvatar, c.AllocAgent, c.ApiKey, c.BatchMsg,
-		c.Category, c.ChatRecords, c.ChatSession, c.Contact, c.CreditBalance,
-		c.CreditUsage, c.Employee, c.EmployeeConfig, c.Label, c.LabelRelationship,
-		c.LabelTagging, c.Message, c.MessageRecords, c.Msg, c.PayRecharge, c.Server,
-		c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial, c.UsageDetail,
-		c.UsageStatisticDay, c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal,
-		c.Whatsapp, c.WhatsappChannel, c.WorkExperience, c.WpChatroom,
-		c.WpChatroomMember, c.Wx, c.WxCard, c.WxCardUser, c.WxCardVisit,
+		c.Category, c.ChatRecords, c.ChatSession, c.Contact, c.ContactField,
+		c.ContactFieldTemplate, c.CreditBalance, c.CreditUsage, c.Employee,
+		c.EmployeeConfig, c.Label, c.LabelRelationship, c.LabelTagging, c.Message,
+		c.MessageRecords, c.Msg, c.PayRecharge, c.Server, c.SopNode, c.SopStage,
+		c.SopTask, c.Token, c.Tutorial, c.UsageDetail, c.UsageStatisticDay,
+		c.UsageStatisticHour, c.UsageStatisticMonth, c.UsageTotal, c.Whatsapp,
+		c.WhatsappChannel, c.WorkExperience, c.WpChatroom, c.WpChatroomMember, c.Wx,
+		c.WxCard, c.WxCardUser, c.WxCardVisit,
 	} {
 		n.Intercept(interceptors...)
 	}
@@ -475,6 +489,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 		return c.ChatSession.mutate(ctx, m)
 	case *ContactMutation:
 		return c.Contact.mutate(ctx, m)
+	case *ContactFieldMutation:
+		return c.ContactField.mutate(ctx, m)
+	case *ContactFieldTemplateMutation:
+		return c.ContactFieldTemplate.mutate(ctx, m)
 	case *CreditBalanceMutation:
 		return c.CreditBalance.mutate(ctx, m)
 	case *CreditUsageMutation:
@@ -1975,6 +1993,22 @@ func (c *ContactClient) QueryContactRelationships(co *Contact) *LabelRelationshi
 	return query
 }
 
+// QueryContactFields queries the contact_fields edge of a Contact.
+func (c *ContactClient) QueryContactFields(co *Contact) *ContactFieldQuery {
+	query := (&ContactFieldClient{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(contactfield.Table, contactfield.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, contact.ContactFieldsTable, contact.ContactFieldsColumn),
+		)
+		fromV = sqlgraph.Neighbors(co.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
 // QueryContactMessages queries the contact_messages edge of a Contact.
 func (c *ContactClient) QueryContactMessages(co *Contact) *MessageRecordsQuery {
 	query := (&MessageRecordsClient{config: c.config}).Query()
@@ -2018,6 +2052,292 @@ func (c *ContactClient) mutate(ctx context.Context, m *ContactMutation) (Value,
 	}
 }
 
+// ContactFieldClient is a client for the ContactField schema.
+type ContactFieldClient struct {
+	config
+}
+
+// NewContactFieldClient returns a client for the ContactField from the given config.
+func NewContactFieldClient(c config) *ContactFieldClient {
+	return &ContactFieldClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `contactfield.Hooks(f(g(h())))`.
+func (c *ContactFieldClient) Use(hooks ...Hook) {
+	c.hooks.ContactField = append(c.hooks.ContactField, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `contactfield.Intercept(f(g(h())))`.
+func (c *ContactFieldClient) Intercept(interceptors ...Interceptor) {
+	c.inters.ContactField = append(c.inters.ContactField, interceptors...)
+}
+
+// Create returns a builder for creating a ContactField entity.
+func (c *ContactFieldClient) Create() *ContactFieldCreate {
+	mutation := newContactFieldMutation(c.config, OpCreate)
+	return &ContactFieldCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of ContactField entities.
+func (c *ContactFieldClient) CreateBulk(builders ...*ContactFieldCreate) *ContactFieldCreateBulk {
+	return &ContactFieldCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *ContactFieldClient) MapCreateBulk(slice any, setFunc func(*ContactFieldCreate, int)) *ContactFieldCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &ContactFieldCreateBulk{err: fmt.Errorf("calling to ContactFieldClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*ContactFieldCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &ContactFieldCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for ContactField.
+func (c *ContactFieldClient) Update() *ContactFieldUpdate {
+	mutation := newContactFieldMutation(c.config, OpUpdate)
+	return &ContactFieldUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *ContactFieldClient) UpdateOne(cf *ContactField) *ContactFieldUpdateOne {
+	mutation := newContactFieldMutation(c.config, OpUpdateOne, withContactField(cf))
+	return &ContactFieldUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *ContactFieldClient) UpdateOneID(id uint64) *ContactFieldUpdateOne {
+	mutation := newContactFieldMutation(c.config, OpUpdateOne, withContactFieldID(id))
+	return &ContactFieldUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for ContactField.
+func (c *ContactFieldClient) Delete() *ContactFieldDelete {
+	mutation := newContactFieldMutation(c.config, OpDelete)
+	return &ContactFieldDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *ContactFieldClient) DeleteOne(cf *ContactField) *ContactFieldDeleteOne {
+	return c.DeleteOneID(cf.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *ContactFieldClient) DeleteOneID(id uint64) *ContactFieldDeleteOne {
+	builder := c.Delete().Where(contactfield.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &ContactFieldDeleteOne{builder}
+}
+
+// Query returns a query builder for ContactField.
+func (c *ContactFieldClient) Query() *ContactFieldQuery {
+	return &ContactFieldQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeContactField},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a ContactField entity by its id.
+func (c *ContactFieldClient) Get(ctx context.Context, id uint64) (*ContactField, error) {
+	return c.Query().Where(contactfield.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *ContactFieldClient) GetX(ctx context.Context, id uint64) *ContactField {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// QueryFieldContact queries the field_contact edge of a ContactField.
+func (c *ContactFieldClient) QueryFieldContact(cf *ContactField) *ContactQuery {
+	query := (&ContactClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := cf.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(contactfield.Table, contactfield.FieldID, id),
+			sqlgraph.To(contact.Table, contact.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, contactfield.FieldContactTable, contactfield.FieldContactColumn),
+		)
+		fromV = sqlgraph.Neighbors(cf.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// Hooks returns the client hooks.
+func (c *ContactFieldClient) Hooks() []Hook {
+	hooks := c.hooks.ContactField
+	return append(hooks[:len(hooks):len(hooks)], contactfield.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *ContactFieldClient) Interceptors() []Interceptor {
+	inters := c.inters.ContactField
+	return append(inters[:len(inters):len(inters)], contactfield.Interceptors[:]...)
+}
+
+func (c *ContactFieldClient) mutate(ctx context.Context, m *ContactFieldMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&ContactFieldCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&ContactFieldUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&ContactFieldUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&ContactFieldDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown ContactField mutation op: %q", m.Op())
+	}
+}
+
+// ContactFieldTemplateClient is a client for the ContactFieldTemplate schema.
+type ContactFieldTemplateClient struct {
+	config
+}
+
+// NewContactFieldTemplateClient returns a client for the ContactFieldTemplate from the given config.
+func NewContactFieldTemplateClient(c config) *ContactFieldTemplateClient {
+	return &ContactFieldTemplateClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `contactfieldtemplate.Hooks(f(g(h())))`.
+func (c *ContactFieldTemplateClient) Use(hooks ...Hook) {
+	c.hooks.ContactFieldTemplate = append(c.hooks.ContactFieldTemplate, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `contactfieldtemplate.Intercept(f(g(h())))`.
+func (c *ContactFieldTemplateClient) Intercept(interceptors ...Interceptor) {
+	c.inters.ContactFieldTemplate = append(c.inters.ContactFieldTemplate, interceptors...)
+}
+
+// Create returns a builder for creating a ContactFieldTemplate entity.
+func (c *ContactFieldTemplateClient) Create() *ContactFieldTemplateCreate {
+	mutation := newContactFieldTemplateMutation(c.config, OpCreate)
+	return &ContactFieldTemplateCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of ContactFieldTemplate entities.
+func (c *ContactFieldTemplateClient) CreateBulk(builders ...*ContactFieldTemplateCreate) *ContactFieldTemplateCreateBulk {
+	return &ContactFieldTemplateCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *ContactFieldTemplateClient) MapCreateBulk(slice any, setFunc func(*ContactFieldTemplateCreate, int)) *ContactFieldTemplateCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &ContactFieldTemplateCreateBulk{err: fmt.Errorf("calling to ContactFieldTemplateClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*ContactFieldTemplateCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &ContactFieldTemplateCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for ContactFieldTemplate.
+func (c *ContactFieldTemplateClient) Update() *ContactFieldTemplateUpdate {
+	mutation := newContactFieldTemplateMutation(c.config, OpUpdate)
+	return &ContactFieldTemplateUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *ContactFieldTemplateClient) UpdateOne(cft *ContactFieldTemplate) *ContactFieldTemplateUpdateOne {
+	mutation := newContactFieldTemplateMutation(c.config, OpUpdateOne, withContactFieldTemplate(cft))
+	return &ContactFieldTemplateUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *ContactFieldTemplateClient) UpdateOneID(id uint64) *ContactFieldTemplateUpdateOne {
+	mutation := newContactFieldTemplateMutation(c.config, OpUpdateOne, withContactFieldTemplateID(id))
+	return &ContactFieldTemplateUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for ContactFieldTemplate.
+func (c *ContactFieldTemplateClient) Delete() *ContactFieldTemplateDelete {
+	mutation := newContactFieldTemplateMutation(c.config, OpDelete)
+	return &ContactFieldTemplateDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *ContactFieldTemplateClient) DeleteOne(cft *ContactFieldTemplate) *ContactFieldTemplateDeleteOne {
+	return c.DeleteOneID(cft.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *ContactFieldTemplateClient) DeleteOneID(id uint64) *ContactFieldTemplateDeleteOne {
+	builder := c.Delete().Where(contactfieldtemplate.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &ContactFieldTemplateDeleteOne{builder}
+}
+
+// Query returns a query builder for ContactFieldTemplate.
+func (c *ContactFieldTemplateClient) Query() *ContactFieldTemplateQuery {
+	return &ContactFieldTemplateQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeContactFieldTemplate},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a ContactFieldTemplate entity by its id.
+func (c *ContactFieldTemplateClient) Get(ctx context.Context, id uint64) (*ContactFieldTemplate, error) {
+	return c.Query().Where(contactfieldtemplate.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *ContactFieldTemplateClient) GetX(ctx context.Context, id uint64) *ContactFieldTemplate {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *ContactFieldTemplateClient) Hooks() []Hook {
+	hooks := c.hooks.ContactFieldTemplate
+	return append(hooks[:len(hooks):len(hooks)], contactfieldtemplate.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *ContactFieldTemplateClient) Interceptors() []Interceptor {
+	inters := c.inters.ContactFieldTemplate
+	return append(inters[:len(inters):len(inters)], contactfieldtemplate.Interceptors[:]...)
+}
+
+func (c *ContactFieldTemplateClient) mutate(ctx context.Context, m *ContactFieldTemplateMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&ContactFieldTemplateCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&ContactFieldTemplateUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&ContactFieldTemplateUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&ContactFieldTemplateDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown ContactFieldTemplate mutation op: %q", m.Op())
+	}
+}
+
 // CreditBalanceClient is a client for the CreditBalance schema.
 type CreditBalanceClient struct {
 	config
@@ -6527,21 +6847,22 @@ func (c *WxCardVisitClient) mutate(ctx context.Context, m *WxCardVisitMutation)
 type (
 	hooks struct {
 		Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey, BatchMsg, Category,
-		ChatRecords, ChatSession, Contact, CreditBalance, CreditUsage, Employee,
-		EmployeeConfig, Label, LabelRelationship, LabelTagging, Message,
-		MessageRecords, Msg, PayRecharge, Server, SopNode, SopStage, SopTask, Token,
-		Tutorial, UsageDetail, UsageStatisticDay, UsageStatisticHour,
-		UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel, WorkExperience,
-		WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser, WxCardVisit []ent.Hook
+		ChatRecords, ChatSession, Contact, ContactField, ContactFieldTemplate,
+		CreditBalance, CreditUsage, Employee, EmployeeConfig, Label, LabelRelationship,
+		LabelTagging, Message, MessageRecords, Msg, PayRecharge, Server, SopNode,
+		SopStage, SopTask, Token, Tutorial, UsageDetail, UsageStatisticDay,
+		UsageStatisticHour, UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel,
+		WorkExperience, WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser,
+		WxCardVisit []ent.Hook
 	}
 	inters struct {
 		Agent, AgentBase, AliyunAvatar, AllocAgent, ApiKey, BatchMsg, Category,
-		ChatRecords, ChatSession, Contact, CreditBalance, CreditUsage, Employee,
-		EmployeeConfig, Label, LabelRelationship, LabelTagging, Message,
-		MessageRecords, Msg, PayRecharge, Server, SopNode, SopStage, SopTask, Token,
-		Tutorial, UsageDetail, UsageStatisticDay, UsageStatisticHour,
-		UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel, WorkExperience,
-		WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser,
+		ChatRecords, ChatSession, Contact, ContactField, ContactFieldTemplate,
+		CreditBalance, CreditUsage, Employee, EmployeeConfig, Label, LabelRelationship,
+		LabelTagging, Message, MessageRecords, Msg, PayRecharge, Server, SopNode,
+		SopStage, SopTask, Token, Tutorial, UsageDetail, UsageStatisticDay,
+		UsageStatisticHour, UsageStatisticMonth, UsageTotal, Whatsapp, WhatsappChannel,
+		WorkExperience, WpChatroom, WpChatroomMember, Wx, WxCard, WxCardUser,
 		WxCardVisit []ent.Interceptor
 	}
 )

+ 18 - 2
ent/contact.go

@@ -87,11 +87,13 @@ type Contact struct {
 type ContactEdges struct {
 	// ContactRelationships holds the value of the contact_relationships edge.
 	ContactRelationships []*LabelRelationship `json:"contact_relationships,omitempty"`
+	// ContactFields holds the value of the contact_fields edge.
+	ContactFields []*ContactField `json:"contact_fields,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 [2]bool
+	loadedTypes [3]bool
 }
 
 // ContactRelationshipsOrErr returns the ContactRelationships value or an error if the edge
@@ -103,10 +105,19 @@ func (e ContactEdges) ContactRelationshipsOrErr() ([]*LabelRelationship, error)
 	return nil, &NotLoadedError{edge: "contact_relationships"}
 }
 
+// ContactFieldsOrErr returns the ContactFields value or an error if the edge
+// was not loaded in eager-loading.
+func (e ContactEdges) ContactFieldsOrErr() ([]*ContactField, error) {
+	if e.loadedTypes[1] {
+		return e.ContactFields, nil
+	}
+	return nil, &NotLoadedError{edge: "contact_fields"}
+}
+
 // 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] {
+	if e.loadedTypes[2] {
 		return e.ContactMessages, nil
 	}
 	return nil, &NotLoadedError{edge: "contact_messages"}
@@ -342,6 +353,11 @@ func (c *Contact) QueryContactRelationships() *LabelRelationshipQuery {
 	return NewContactClient(c.config).QueryContactRelationships(c)
 }
 
+// QueryContactFields queries the "contact_fields" edge of the Contact entity.
+func (c *Contact) QueryContactFields() *ContactFieldQuery {
+	return NewContactClient(c.config).QueryContactFields(c)
+}
+
 // QueryContactMessages queries the "contact_messages" edge of the Contact entity.
 func (c *Contact) QueryContactMessages() *MessageRecordsQuery {
 	return NewContactClient(c.config).QueryContactMessages(c)

+ 30 - 0
ent/contact/contact.go

@@ -77,6 +77,8 @@ const (
 	FieldPhone = "phone"
 	// EdgeContactRelationships holds the string denoting the contact_relationships edge name in mutations.
 	EdgeContactRelationships = "contact_relationships"
+	// EdgeContactFields holds the string denoting the contact_fields edge name in mutations.
+	EdgeContactFields = "contact_fields"
 	// 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.
@@ -88,6 +90,13 @@ const (
 	ContactRelationshipsInverseTable = "label_relationship"
 	// ContactRelationshipsColumn is the table column denoting the contact_relationships relation/edge.
 	ContactRelationshipsColumn = "contact_id"
+	// ContactFieldsTable is the table that holds the contact_fields relation/edge.
+	ContactFieldsTable = "contact_field"
+	// ContactFieldsInverseTable is the table name for the ContactField entity.
+	// It exists in this package in order to avoid circular dependency with the "contactfield" package.
+	ContactFieldsInverseTable = "contact_field"
+	// ContactFieldsColumn is the table column denoting the contact_fields relation/edge.
+	ContactFieldsColumn = "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.
@@ -384,6 +393,20 @@ func ByContactRelationships(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOpt
 	}
 }
 
+// ByContactFieldsCount orders the results by contact_fields count.
+func ByContactFieldsCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newContactFieldsStep(), opts...)
+	}
+}
+
+// ByContactFields orders the results by contact_fields terms.
+func ByContactFields(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newContactFieldsStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
+
 // ByContactMessagesCount orders the results by contact_messages count.
 func ByContactMessagesCount(opts ...sql.OrderTermOption) OrderOption {
 	return func(s *sql.Selector) {
@@ -404,6 +427,13 @@ func newContactRelationshipsStep() *sqlgraph.Step {
 		sqlgraph.Edge(sqlgraph.O2M, false, ContactRelationshipsTable, ContactRelationshipsColumn),
 	)
 }
+func newContactFieldsStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(ContactFieldsInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, ContactFieldsTable, ContactFieldsColumn),
+	)
+}
 func newContactMessagesStep() *sqlgraph.Step {
 	return sqlgraph.NewStep(
 		sqlgraph.From(Table, FieldID),

+ 23 - 0
ent/contact/where.go

@@ -1943,6 +1943,29 @@ func HasContactRelationshipsWith(preds ...predicate.LabelRelationship) predicate
 	})
 }
 
+// HasContactFields applies the HasEdge predicate on the "contact_fields" edge.
+func HasContactFields() predicate.Contact {
+	return predicate.Contact(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, ContactFieldsTable, ContactFieldsColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasContactFieldsWith applies the HasEdge predicate on the "contact_fields" edge with a given conditions (other predicates).
+func HasContactFieldsWith(preds ...predicate.ContactField) predicate.Contact {
+	return predicate.Contact(func(s *sql.Selector) {
+		step := newContactFieldsStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
 // HasContactMessages applies the HasEdge predicate on the "contact_messages" edge.
 func HasContactMessages() predicate.Contact {
 	return predicate.Contact(func(s *sql.Selector) {

+ 32 - 0
ent/contact_create.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/messagerecords"
 
@@ -465,6 +466,21 @@ func (cc *ContactCreate) AddContactRelationships(l ...*LabelRelationship) *Conta
 	return cc.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactFieldIDs adds the "contact_fields" edge to the ContactField entity by IDs.
+func (cc *ContactCreate) AddContactFieldIDs(ids ...uint64) *ContactCreate {
+	cc.mutation.AddContactFieldIDs(ids...)
+	return cc
+}
+
+// AddContactFields adds the "contact_fields" edges to the ContactField entity.
+func (cc *ContactCreate) AddContactFields(c ...*ContactField) *ContactCreate {
+	ids := make([]uint64, len(c))
+	for i := range c {
+		ids[i] = c[i].ID
+	}
+	return cc.AddContactFieldIDs(ids...)
+}
+
 // AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
 func (cc *ContactCreate) AddContactMessageIDs(ids ...uint64) *ContactCreate {
 	cc.mutation.AddContactMessageIDs(ids...)
@@ -891,6 +907,22 @@ func (cc *ContactCreate) createSpec() (*Contact, *sqlgraph.CreateSpec) {
 		}
 		_spec.Edges = append(_spec.Edges, edge)
 	}
+	if nodes := cc.mutation.ContactFieldsIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
 	if nodes := cc.mutation.ContactMessagesIDs(); len(nodes) > 0 {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,

+ 75 - 1
ent/contact_query.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"math"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
@@ -25,6 +26,7 @@ type ContactQuery struct {
 	inters                   []Interceptor
 	predicates               []predicate.Contact
 	withContactRelationships *LabelRelationshipQuery
+	withContactFields        *ContactFieldQuery
 	withContactMessages      *MessageRecordsQuery
 	// intermediate query (i.e. traversal path).
 	sql  *sql.Selector
@@ -84,6 +86,28 @@ func (cq *ContactQuery) QueryContactRelationships() *LabelRelationshipQuery {
 	return query
 }
 
+// QueryContactFields chains the current query on the "contact_fields" edge.
+func (cq *ContactQuery) QueryContactFields() *ContactFieldQuery {
+	query := (&ContactFieldClient{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(contactfield.Table, contactfield.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, contact.ContactFieldsTable, contact.ContactFieldsColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(cq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
 // QueryContactMessages chains the current query on the "contact_messages" edge.
 func (cq *ContactQuery) QueryContactMessages() *MessageRecordsQuery {
 	query := (&MessageRecordsClient{config: cq.config}).Query()
@@ -299,6 +323,7 @@ func (cq *ContactQuery) Clone() *ContactQuery {
 		inters:                   append([]Interceptor{}, cq.inters...),
 		predicates:               append([]predicate.Contact{}, cq.predicates...),
 		withContactRelationships: cq.withContactRelationships.Clone(),
+		withContactFields:        cq.withContactFields.Clone(),
 		withContactMessages:      cq.withContactMessages.Clone(),
 		// clone intermediate query.
 		sql:  cq.sql.Clone(),
@@ -317,6 +342,17 @@ func (cq *ContactQuery) WithContactRelationships(opts ...func(*LabelRelationship
 	return cq
 }
 
+// WithContactFields tells the query-builder to eager-load the nodes that are connected to
+// the "contact_fields" edge. The optional arguments are used to configure the query builder of the edge.
+func (cq *ContactQuery) WithContactFields(opts ...func(*ContactFieldQuery)) *ContactQuery {
+	query := (&ContactFieldClient{config: cq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	cq.withContactFields = query
+	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 {
@@ -406,8 +442,9 @@ func (cq *ContactQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Cont
 	var (
 		nodes       = []*Contact{}
 		_spec       = cq.querySpec()
-		loadedTypes = [2]bool{
+		loadedTypes = [3]bool{
 			cq.withContactRelationships != nil,
+			cq.withContactFields != nil,
 			cq.withContactMessages != nil,
 		}
 	)
@@ -438,6 +475,13 @@ func (cq *ContactQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Cont
 			return nil, err
 		}
 	}
+	if query := cq.withContactFields; query != nil {
+		if err := cq.loadContactFields(ctx, query, nodes,
+			func(n *Contact) { n.Edges.ContactFields = []*ContactField{} },
+			func(n *Contact, e *ContactField) { n.Edges.ContactFields = append(n.Edges.ContactFields, e) }); err != nil {
+			return nil, err
+		}
+	}
 	if query := cq.withContactMessages; query != nil {
 		if err := cq.loadContactMessages(ctx, query, nodes,
 			func(n *Contact) { n.Edges.ContactMessages = []*MessageRecords{} },
@@ -478,6 +522,36 @@ func (cq *ContactQuery) loadContactRelationships(ctx context.Context, query *Lab
 	}
 	return nil
 }
+func (cq *ContactQuery) loadContactFields(ctx context.Context, query *ContactFieldQuery, nodes []*Contact, init func(*Contact), assign func(*Contact, *ContactField)) 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(contactfield.FieldContactID)
+	}
+	query.Where(predicate.ContactField(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(contact.ContactFieldsColumn), 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) 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)

+ 163 - 0
ent/contact_update.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/messagerecords"
 	"wechat-api/ent/predicate"
@@ -523,6 +524,21 @@ func (cu *ContactUpdate) AddContactRelationships(l ...*LabelRelationship) *Conta
 	return cu.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactFieldIDs adds the "contact_fields" edge to the ContactField entity by IDs.
+func (cu *ContactUpdate) AddContactFieldIDs(ids ...uint64) *ContactUpdate {
+	cu.mutation.AddContactFieldIDs(ids...)
+	return cu
+}
+
+// AddContactFields adds the "contact_fields" edges to the ContactField entity.
+func (cu *ContactUpdate) AddContactFields(c ...*ContactField) *ContactUpdate {
+	ids := make([]uint64, len(c))
+	for i := range c {
+		ids[i] = c[i].ID
+	}
+	return cu.AddContactFieldIDs(ids...)
+}
+
 // AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
 func (cu *ContactUpdate) AddContactMessageIDs(ids ...uint64) *ContactUpdate {
 	cu.mutation.AddContactMessageIDs(ids...)
@@ -564,6 +580,27 @@ func (cu *ContactUpdate) RemoveContactRelationships(l ...*LabelRelationship) *Co
 	return cu.RemoveContactRelationshipIDs(ids...)
 }
 
+// ClearContactFields clears all "contact_fields" edges to the ContactField entity.
+func (cu *ContactUpdate) ClearContactFields() *ContactUpdate {
+	cu.mutation.ClearContactFields()
+	return cu
+}
+
+// RemoveContactFieldIDs removes the "contact_fields" edge to ContactField entities by IDs.
+func (cu *ContactUpdate) RemoveContactFieldIDs(ids ...uint64) *ContactUpdate {
+	cu.mutation.RemoveContactFieldIDs(ids...)
+	return cu
+}
+
+// RemoveContactFields removes "contact_fields" edges to ContactField entities.
+func (cu *ContactUpdate) RemoveContactFields(c ...*ContactField) *ContactUpdate {
+	ids := make([]uint64, len(c))
+	for i := range c {
+		ids[i] = c[i].ID
+	}
+	return cu.RemoveContactFieldIDs(ids...)
+}
+
 // ClearContactMessages clears all "contact_messages" edges to the MessageRecords entity.
 func (cu *ContactUpdate) ClearContactMessages() *ContactUpdate {
 	cu.mutation.ClearContactMessages()
@@ -804,6 +841,51 @@ func (cu *ContactUpdate) sqlSave(ctx context.Context) (n int, err error) {
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if cu.mutation.ContactFieldsCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cu.mutation.RemovedContactFieldsIDs(); len(nodes) > 0 && !cu.mutation.ContactFieldsCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.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.ContactFieldsIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	if cu.mutation.ContactMessagesCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,
@@ -1362,6 +1444,21 @@ func (cuo *ContactUpdateOne) AddContactRelationships(l ...*LabelRelationship) *C
 	return cuo.AddContactRelationshipIDs(ids...)
 }
 
+// AddContactFieldIDs adds the "contact_fields" edge to the ContactField entity by IDs.
+func (cuo *ContactUpdateOne) AddContactFieldIDs(ids ...uint64) *ContactUpdateOne {
+	cuo.mutation.AddContactFieldIDs(ids...)
+	return cuo
+}
+
+// AddContactFields adds the "contact_fields" edges to the ContactField entity.
+func (cuo *ContactUpdateOne) AddContactFields(c ...*ContactField) *ContactUpdateOne {
+	ids := make([]uint64, len(c))
+	for i := range c {
+		ids[i] = c[i].ID
+	}
+	return cuo.AddContactFieldIDs(ids...)
+}
+
 // AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by IDs.
 func (cuo *ContactUpdateOne) AddContactMessageIDs(ids ...uint64) *ContactUpdateOne {
 	cuo.mutation.AddContactMessageIDs(ids...)
@@ -1403,6 +1500,27 @@ func (cuo *ContactUpdateOne) RemoveContactRelationships(l ...*LabelRelationship)
 	return cuo.RemoveContactRelationshipIDs(ids...)
 }
 
+// ClearContactFields clears all "contact_fields" edges to the ContactField entity.
+func (cuo *ContactUpdateOne) ClearContactFields() *ContactUpdateOne {
+	cuo.mutation.ClearContactFields()
+	return cuo
+}
+
+// RemoveContactFieldIDs removes the "contact_fields" edge to ContactField entities by IDs.
+func (cuo *ContactUpdateOne) RemoveContactFieldIDs(ids ...uint64) *ContactUpdateOne {
+	cuo.mutation.RemoveContactFieldIDs(ids...)
+	return cuo
+}
+
+// RemoveContactFields removes "contact_fields" edges to ContactField entities.
+func (cuo *ContactUpdateOne) RemoveContactFields(c ...*ContactField) *ContactUpdateOne {
+	ids := make([]uint64, len(c))
+	for i := range c {
+		ids[i] = c[i].ID
+	}
+	return cuo.RemoveContactFieldIDs(ids...)
+}
+
 // ClearContactMessages clears all "contact_messages" edges to the MessageRecords entity.
 func (cuo *ContactUpdateOne) ClearContactMessages() *ContactUpdateOne {
 	cuo.mutation.ClearContactMessages()
@@ -1673,6 +1791,51 @@ func (cuo *ContactUpdateOne) sqlSave(ctx context.Context) (_node *Contact, err e
 		}
 		_spec.Edges.Add = append(_spec.Edges.Add, edge)
 	}
+	if cuo.mutation.ContactFieldsCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cuo.mutation.RemovedContactFieldsIDs(); len(nodes) > 0 && !cuo.mutation.ContactFieldsCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.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.ContactFieldsIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   contact.ContactFieldsTable,
+			Columns: []string{contact.ContactFieldsColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
 	if cuo.mutation.ContactMessagesCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,

+ 206 - 0
ent/contactfield.go

@@ -0,0 +1,206 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// ContactField is the model entity for the ContactField schema.
+type ContactField struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Status uint8 `json:"status,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// 联系人 ID
+	ContactID uint64 `json:"contact_id,omitempty"`
+	// 表单 id
+	FormID string `json:"form_id,omitempty"`
+	// 表单值
+	Value []string `json:"value,omitempty"`
+	// Edges holds the relations/edges for other nodes in the graph.
+	// The values are being populated by the ContactFieldQuery when eager-loading is set.
+	Edges        ContactFieldEdges `json:"edges"`
+	selectValues sql.SelectValues
+}
+
+// ContactFieldEdges holds the relations/edges for other nodes in the graph.
+type ContactFieldEdges struct {
+	// FieldContact holds the value of the field_contact edge.
+	FieldContact *Contact `json:"field_contact,omitempty"`
+	// loadedTypes holds the information for reporting if a
+	// type was loaded (or requested) in eager-loading or not.
+	loadedTypes [1]bool
+}
+
+// FieldContactOrErr returns the FieldContact value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e ContactFieldEdges) FieldContactOrErr() (*Contact, error) {
+	if e.FieldContact != nil {
+		return e.FieldContact, nil
+	} else if e.loadedTypes[0] {
+		return nil, &NotFoundError{label: contact.Label}
+	}
+	return nil, &NotLoadedError{edge: "field_contact"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*ContactField) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case contactfield.FieldValue:
+			values[i] = new([]byte)
+		case contactfield.FieldID, contactfield.FieldStatus, contactfield.FieldContactID:
+			values[i] = new(sql.NullInt64)
+		case contactfield.FieldFormID:
+			values[i] = new(sql.NullString)
+		case contactfield.FieldCreatedAt, contactfield.FieldUpdatedAt, contactfield.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the ContactField fields.
+func (cf *ContactField) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case contactfield.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			cf.ID = uint64(value.Int64)
+		case contactfield.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				cf.CreatedAt = value.Time
+			}
+		case contactfield.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				cf.UpdatedAt = value.Time
+			}
+		case contactfield.FieldStatus:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field status", values[i])
+			} else if value.Valid {
+				cf.Status = uint8(value.Int64)
+			}
+		case contactfield.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				cf.DeletedAt = value.Time
+			}
+		case contactfield.FieldContactID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field contact_id", values[i])
+			} else if value.Valid {
+				cf.ContactID = uint64(value.Int64)
+			}
+		case contactfield.FieldFormID:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field form_id", values[i])
+			} else if value.Valid {
+				cf.FormID = value.String
+			}
+		case contactfield.FieldValue:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field value", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &cf.Value); err != nil {
+					return fmt.Errorf("unmarshal field value: %w", err)
+				}
+			}
+		default:
+			cf.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// GetValue returns the ent.Value that was dynamically selected and assigned to the ContactField.
+// This includes values selected through modifiers, order, etc.
+func (cf *ContactField) GetValue(name string) (ent.Value, error) {
+	return cf.selectValues.Get(name)
+}
+
+// QueryFieldContact queries the "field_contact" edge of the ContactField entity.
+func (cf *ContactField) QueryFieldContact() *ContactQuery {
+	return NewContactFieldClient(cf.config).QueryFieldContact(cf)
+}
+
+// Update returns a builder for updating this ContactField.
+// Note that you need to call ContactField.Unwrap() before calling this method if this ContactField
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (cf *ContactField) Update() *ContactFieldUpdateOne {
+	return NewContactFieldClient(cf.config).UpdateOne(cf)
+}
+
+// Unwrap unwraps the ContactField entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (cf *ContactField) Unwrap() *ContactField {
+	_tx, ok := cf.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: ContactField is not a transactional entity")
+	}
+	cf.config.driver = _tx.drv
+	return cf
+}
+
+// String implements the fmt.Stringer.
+func (cf *ContactField) String() string {
+	var builder strings.Builder
+	builder.WriteString("ContactField(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", cf.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(cf.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(cf.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("status=")
+	builder.WriteString(fmt.Sprintf("%v", cf.Status))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(cf.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("contact_id=")
+	builder.WriteString(fmt.Sprintf("%v", cf.ContactID))
+	builder.WriteString(", ")
+	builder.WriteString("form_id=")
+	builder.WriteString(cf.FormID)
+	builder.WriteString(", ")
+	builder.WriteString("value=")
+	builder.WriteString(fmt.Sprintf("%v", cf.Value))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// ContactFields is a parsable slice of ContactField.
+type ContactFields []*ContactField

+ 137 - 0
ent/contactfield/contactfield.go

@@ -0,0 +1,137 @@
+// Code generated by ent, DO NOT EDIT.
+
+package contactfield
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+	// Label holds the string label denoting the contactfield type in the database.
+	Label = "contact_field"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldStatus holds the string denoting the status field in the database.
+	FieldStatus = "status"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldContactID holds the string denoting the contact_id field in the database.
+	FieldContactID = "contact_id"
+	// FieldFormID holds the string denoting the form_id field in the database.
+	FieldFormID = "form_id"
+	// FieldValue holds the string denoting the value field in the database.
+	FieldValue = "value"
+	// EdgeFieldContact holds the string denoting the field_contact edge name in mutations.
+	EdgeFieldContact = "field_contact"
+	// Table holds the table name of the contactfield in the database.
+	Table = "contact_field"
+	// FieldContactTable is the table that holds the field_contact relation/edge.
+	FieldContactTable = "contact_field"
+	// FieldContactInverseTable is the table name for the Contact entity.
+	// It exists in this package in order to avoid circular dependency with the "contact" package.
+	FieldContactInverseTable = "contact"
+	// FieldContactColumn is the table column denoting the field_contact relation/edge.
+	FieldContactColumn = "contact_id"
+)
+
+// Columns holds all SQL columns for contactfield fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldStatus,
+	FieldDeletedAt,
+	FieldContactID,
+	FieldFormID,
+	FieldValue,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultStatus holds the default value on creation for the "status" field.
+	DefaultStatus uint8
+	// DefaultContactID holds the default value on creation for the "contact_id" field.
+	DefaultContactID uint64
+)
+
+// OrderOption defines the ordering options for the ContactField queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByStatus orders the results by the status field.
+func ByStatus(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldStatus, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByContactID orders the results by the contact_id field.
+func ByContactID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldContactID, opts...).ToFunc()
+}
+
+// ByFormID orders the results by the form_id field.
+func ByFormID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldFormID, opts...).ToFunc()
+}
+
+// ByFieldContactField orders the results by field_contact field.
+func ByFieldContactField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newFieldContactStep(), sql.OrderByField(field, opts...))
+	}
+}
+func newFieldContactStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(FieldContactInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, FieldContactTable, FieldContactColumn),
+	)
+}

+ 389 - 0
ent/contactfield/where.go

@@ -0,0 +1,389 @@
+// Code generated by ent, DO NOT EDIT.
+
+package contactfield
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
+func Status(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldStatus, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// ContactID applies equality check predicate on the "contact_id" field. It's identical to ContactIDEQ.
+func ContactID(v uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldContactID, v))
+}
+
+// FormID applies equality check predicate on the "form_id" field. It's identical to FormIDEQ.
+func FormID(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldFormID, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// StatusEQ applies the EQ predicate on the "status" field.
+func StatusEQ(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldStatus, v))
+}
+
+// StatusNEQ applies the NEQ predicate on the "status" field.
+func StatusNEQ(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldStatus, v))
+}
+
+// StatusIn applies the In predicate on the "status" field.
+func StatusIn(vs ...uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldStatus, vs...))
+}
+
+// StatusNotIn applies the NotIn predicate on the "status" field.
+func StatusNotIn(vs ...uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldStatus, vs...))
+}
+
+// StatusGT applies the GT predicate on the "status" field.
+func StatusGT(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldStatus, v))
+}
+
+// StatusGTE applies the GTE predicate on the "status" field.
+func StatusGTE(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldStatus, v))
+}
+
+// StatusLT applies the LT predicate on the "status" field.
+func StatusLT(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldStatus, v))
+}
+
+// StatusLTE applies the LTE predicate on the "status" field.
+func StatusLTE(v uint8) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldStatus, v))
+}
+
+// StatusIsNil applies the IsNil predicate on the "status" field.
+func StatusIsNil() predicate.ContactField {
+	return predicate.ContactField(sql.FieldIsNull(FieldStatus))
+}
+
+// StatusNotNil applies the NotNil predicate on the "status" field.
+func StatusNotNil() predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotNull(FieldStatus))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.ContactField {
+	return predicate.ContactField(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// ContactIDEQ applies the EQ predicate on the "contact_id" field.
+func ContactIDEQ(v uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldContactID, v))
+}
+
+// ContactIDNEQ applies the NEQ predicate on the "contact_id" field.
+func ContactIDNEQ(v uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldContactID, v))
+}
+
+// ContactIDIn applies the In predicate on the "contact_id" field.
+func ContactIDIn(vs ...uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldContactID, vs...))
+}
+
+// ContactIDNotIn applies the NotIn predicate on the "contact_id" field.
+func ContactIDNotIn(vs ...uint64) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldContactID, vs...))
+}
+
+// FormIDEQ applies the EQ predicate on the "form_id" field.
+func FormIDEQ(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEQ(FieldFormID, v))
+}
+
+// FormIDNEQ applies the NEQ predicate on the "form_id" field.
+func FormIDNEQ(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNEQ(FieldFormID, v))
+}
+
+// FormIDIn applies the In predicate on the "form_id" field.
+func FormIDIn(vs ...string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldIn(FieldFormID, vs...))
+}
+
+// FormIDNotIn applies the NotIn predicate on the "form_id" field.
+func FormIDNotIn(vs ...string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldNotIn(FieldFormID, vs...))
+}
+
+// FormIDGT applies the GT predicate on the "form_id" field.
+func FormIDGT(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGT(FieldFormID, v))
+}
+
+// FormIDGTE applies the GTE predicate on the "form_id" field.
+func FormIDGTE(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldGTE(FieldFormID, v))
+}
+
+// FormIDLT applies the LT predicate on the "form_id" field.
+func FormIDLT(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLT(FieldFormID, v))
+}
+
+// FormIDLTE applies the LTE predicate on the "form_id" field.
+func FormIDLTE(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldLTE(FieldFormID, v))
+}
+
+// FormIDContains applies the Contains predicate on the "form_id" field.
+func FormIDContains(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldContains(FieldFormID, v))
+}
+
+// FormIDHasPrefix applies the HasPrefix predicate on the "form_id" field.
+func FormIDHasPrefix(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldHasPrefix(FieldFormID, v))
+}
+
+// FormIDHasSuffix applies the HasSuffix predicate on the "form_id" field.
+func FormIDHasSuffix(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldHasSuffix(FieldFormID, v))
+}
+
+// FormIDEqualFold applies the EqualFold predicate on the "form_id" field.
+func FormIDEqualFold(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldEqualFold(FieldFormID, v))
+}
+
+// FormIDContainsFold applies the ContainsFold predicate on the "form_id" field.
+func FormIDContainsFold(v string) predicate.ContactField {
+	return predicate.ContactField(sql.FieldContainsFold(FieldFormID, v))
+}
+
+// HasFieldContact applies the HasEdge predicate on the "field_contact" edge.
+func HasFieldContact() predicate.ContactField {
+	return predicate.ContactField(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, FieldContactTable, FieldContactColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasFieldContactWith applies the HasEdge predicate on the "field_contact" edge with a given conditions (other predicates).
+func HasFieldContactWith(preds ...predicate.Contact) predicate.ContactField {
+	return predicate.ContactField(func(s *sql.Selector) {
+		step := newFieldContactStep()
+		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.ContactField) predicate.ContactField {
+	return predicate.ContactField(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.ContactField) predicate.ContactField {
+	return predicate.ContactField(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.ContactField) predicate.ContactField {
+	return predicate.ContactField(sql.NotPredicates(p))
+}

+ 922 - 0
ent/contactfield_create.go

@@ -0,0 +1,922 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ContactFieldCreate is the builder for creating a ContactField entity.
+type ContactFieldCreate struct {
+	config
+	mutation *ContactFieldMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (cfc *ContactFieldCreate) SetCreatedAt(t time.Time) *ContactFieldCreate {
+	cfc.mutation.SetCreatedAt(t)
+	return cfc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (cfc *ContactFieldCreate) SetNillableCreatedAt(t *time.Time) *ContactFieldCreate {
+	if t != nil {
+		cfc.SetCreatedAt(*t)
+	}
+	return cfc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cfc *ContactFieldCreate) SetUpdatedAt(t time.Time) *ContactFieldCreate {
+	cfc.mutation.SetUpdatedAt(t)
+	return cfc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (cfc *ContactFieldCreate) SetNillableUpdatedAt(t *time.Time) *ContactFieldCreate {
+	if t != nil {
+		cfc.SetUpdatedAt(*t)
+	}
+	return cfc
+}
+
+// SetStatus sets the "status" field.
+func (cfc *ContactFieldCreate) SetStatus(u uint8) *ContactFieldCreate {
+	cfc.mutation.SetStatus(u)
+	return cfc
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cfc *ContactFieldCreate) SetNillableStatus(u *uint8) *ContactFieldCreate {
+	if u != nil {
+		cfc.SetStatus(*u)
+	}
+	return cfc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cfc *ContactFieldCreate) SetDeletedAt(t time.Time) *ContactFieldCreate {
+	cfc.mutation.SetDeletedAt(t)
+	return cfc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cfc *ContactFieldCreate) SetNillableDeletedAt(t *time.Time) *ContactFieldCreate {
+	if t != nil {
+		cfc.SetDeletedAt(*t)
+	}
+	return cfc
+}
+
+// SetContactID sets the "contact_id" field.
+func (cfc *ContactFieldCreate) SetContactID(u uint64) *ContactFieldCreate {
+	cfc.mutation.SetContactID(u)
+	return cfc
+}
+
+// SetNillableContactID sets the "contact_id" field if the given value is not nil.
+func (cfc *ContactFieldCreate) SetNillableContactID(u *uint64) *ContactFieldCreate {
+	if u != nil {
+		cfc.SetContactID(*u)
+	}
+	return cfc
+}
+
+// SetFormID sets the "form_id" field.
+func (cfc *ContactFieldCreate) SetFormID(s string) *ContactFieldCreate {
+	cfc.mutation.SetFormID(s)
+	return cfc
+}
+
+// SetValue sets the "value" field.
+func (cfc *ContactFieldCreate) SetValue(s []string) *ContactFieldCreate {
+	cfc.mutation.SetValue(s)
+	return cfc
+}
+
+// SetID sets the "id" field.
+func (cfc *ContactFieldCreate) SetID(u uint64) *ContactFieldCreate {
+	cfc.mutation.SetID(u)
+	return cfc
+}
+
+// SetFieldContactID sets the "field_contact" edge to the Contact entity by ID.
+func (cfc *ContactFieldCreate) SetFieldContactID(id uint64) *ContactFieldCreate {
+	cfc.mutation.SetFieldContactID(id)
+	return cfc
+}
+
+// SetFieldContact sets the "field_contact" edge to the Contact entity.
+func (cfc *ContactFieldCreate) SetFieldContact(c *Contact) *ContactFieldCreate {
+	return cfc.SetFieldContactID(c.ID)
+}
+
+// Mutation returns the ContactFieldMutation object of the builder.
+func (cfc *ContactFieldCreate) Mutation() *ContactFieldMutation {
+	return cfc.mutation
+}
+
+// Save creates the ContactField in the database.
+func (cfc *ContactFieldCreate) Save(ctx context.Context) (*ContactField, error) {
+	if err := cfc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, cfc.sqlSave, cfc.mutation, cfc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (cfc *ContactFieldCreate) SaveX(ctx context.Context) *ContactField {
+	v, err := cfc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (cfc *ContactFieldCreate) Exec(ctx context.Context) error {
+	_, err := cfc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cfc *ContactFieldCreate) ExecX(ctx context.Context) {
+	if err := cfc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cfc *ContactFieldCreate) defaults() error {
+	if _, ok := cfc.mutation.CreatedAt(); !ok {
+		if contactfield.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfield.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfield.DefaultCreatedAt()
+		cfc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := cfc.mutation.UpdatedAt(); !ok {
+		if contactfield.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfield.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfield.DefaultUpdatedAt()
+		cfc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := cfc.mutation.Status(); !ok {
+		v := contactfield.DefaultStatus
+		cfc.mutation.SetStatus(v)
+	}
+	if _, ok := cfc.mutation.ContactID(); !ok {
+		v := contactfield.DefaultContactID
+		cfc.mutation.SetContactID(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (cfc *ContactFieldCreate) check() error {
+	if _, ok := cfc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ContactField.created_at"`)}
+	}
+	if _, ok := cfc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ContactField.updated_at"`)}
+	}
+	if _, ok := cfc.mutation.ContactID(); !ok {
+		return &ValidationError{Name: "contact_id", err: errors.New(`ent: missing required field "ContactField.contact_id"`)}
+	}
+	if _, ok := cfc.mutation.FormID(); !ok {
+		return &ValidationError{Name: "form_id", err: errors.New(`ent: missing required field "ContactField.form_id"`)}
+	}
+	if _, ok := cfc.mutation.Value(); !ok {
+		return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "ContactField.value"`)}
+	}
+	if _, ok := cfc.mutation.FieldContactID(); !ok {
+		return &ValidationError{Name: "field_contact", err: errors.New(`ent: missing required edge "ContactField.field_contact"`)}
+	}
+	return nil
+}
+
+func (cfc *ContactFieldCreate) sqlSave(ctx context.Context) (*ContactField, error) {
+	if err := cfc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := cfc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, cfc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	cfc.mutation.id = &_node.ID
+	cfc.mutation.done = true
+	return _node, nil
+}
+
+func (cfc *ContactFieldCreate) createSpec() (*ContactField, *sqlgraph.CreateSpec) {
+	var (
+		_node = &ContactField{config: cfc.config}
+		_spec = sqlgraph.NewCreateSpec(contactfield.Table, sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = cfc.conflict
+	if id, ok := cfc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := cfc.mutation.CreatedAt(); ok {
+		_spec.SetField(contactfield.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := cfc.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfield.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := cfc.mutation.Status(); ok {
+		_spec.SetField(contactfield.FieldStatus, field.TypeUint8, value)
+		_node.Status = value
+	}
+	if value, ok := cfc.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfield.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := cfc.mutation.FormID(); ok {
+		_spec.SetField(contactfield.FieldFormID, field.TypeString, value)
+		_node.FormID = value
+	}
+	if value, ok := cfc.mutation.Value(); ok {
+		_spec.SetField(contactfield.FieldValue, field.TypeJSON, value)
+		_node.Value = value
+	}
+	if nodes := cfc.mutation.FieldContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   contactfield.FieldContactTable,
+			Columns: []string{contactfield.FieldContactColumn},
+			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
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ContactField.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ContactFieldUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (cfc *ContactFieldCreate) OnConflict(opts ...sql.ConflictOption) *ContactFieldUpsertOne {
+	cfc.conflict = opts
+	return &ContactFieldUpsertOne{
+		create: cfc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (cfc *ContactFieldCreate) OnConflictColumns(columns ...string) *ContactFieldUpsertOne {
+	cfc.conflict = append(cfc.conflict, sql.ConflictColumns(columns...))
+	return &ContactFieldUpsertOne{
+		create: cfc,
+	}
+}
+
+type (
+	// ContactFieldUpsertOne is the builder for "upsert"-ing
+	//  one ContactField node.
+	ContactFieldUpsertOne struct {
+		create *ContactFieldCreate
+	}
+
+	// ContactFieldUpsert is the "OnConflict" setter.
+	ContactFieldUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldUpsert) SetUpdatedAt(v time.Time) *ContactFieldUpsert {
+	u.Set(contactfield.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateUpdatedAt() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldUpdatedAt)
+	return u
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldUpsert) SetStatus(v uint8) *ContactFieldUpsert {
+	u.Set(contactfield.FieldStatus, v)
+	return u
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateStatus() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldStatus)
+	return u
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldUpsert) AddStatus(v uint8) *ContactFieldUpsert {
+	u.Add(contactfield.FieldStatus, v)
+	return u
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldUpsert) ClearStatus() *ContactFieldUpsert {
+	u.SetNull(contactfield.FieldStatus)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldUpsert) SetDeletedAt(v time.Time) *ContactFieldUpsert {
+	u.Set(contactfield.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateDeletedAt() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldUpsert) ClearDeletedAt() *ContactFieldUpsert {
+	u.SetNull(contactfield.FieldDeletedAt)
+	return u
+}
+
+// SetContactID sets the "contact_id" field.
+func (u *ContactFieldUpsert) SetContactID(v uint64) *ContactFieldUpsert {
+	u.Set(contactfield.FieldContactID, v)
+	return u
+}
+
+// UpdateContactID sets the "contact_id" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateContactID() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldContactID)
+	return u
+}
+
+// SetFormID sets the "form_id" field.
+func (u *ContactFieldUpsert) SetFormID(v string) *ContactFieldUpsert {
+	u.Set(contactfield.FieldFormID, v)
+	return u
+}
+
+// UpdateFormID sets the "form_id" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateFormID() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldFormID)
+	return u
+}
+
+// SetValue sets the "value" field.
+func (u *ContactFieldUpsert) SetValue(v []string) *ContactFieldUpsert {
+	u.Set(contactfield.FieldValue, v)
+	return u
+}
+
+// UpdateValue sets the "value" field to the value that was provided on create.
+func (u *ContactFieldUpsert) UpdateValue() *ContactFieldUpsert {
+	u.SetExcluded(contactfield.FieldValue)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(contactfield.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ContactFieldUpsertOne) UpdateNewValues() *ContactFieldUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(contactfield.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(contactfield.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *ContactFieldUpsertOne) Ignore() *ContactFieldUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ContactFieldUpsertOne) DoNothing() *ContactFieldUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ContactFieldCreate.OnConflict
+// documentation for more info.
+func (u *ContactFieldUpsertOne) Update(set func(*ContactFieldUpsert)) *ContactFieldUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ContactFieldUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldUpsertOne) SetUpdatedAt(v time.Time) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateUpdatedAt() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldUpsertOne) SetStatus(v uint8) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldUpsertOne) AddStatus(v uint8) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateStatus() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldUpsertOne) ClearStatus() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldUpsertOne) SetDeletedAt(v time.Time) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateDeletedAt() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldUpsertOne) ClearDeletedAt() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetContactID sets the "contact_id" field.
+func (u *ContactFieldUpsertOne) SetContactID(v uint64) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetContactID(v)
+	})
+}
+
+// UpdateContactID sets the "contact_id" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateContactID() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateContactID()
+	})
+}
+
+// SetFormID sets the "form_id" field.
+func (u *ContactFieldUpsertOne) SetFormID(v string) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetFormID(v)
+	})
+}
+
+// UpdateFormID sets the "form_id" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateFormID() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateFormID()
+	})
+}
+
+// SetValue sets the "value" field.
+func (u *ContactFieldUpsertOne) SetValue(v []string) *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetValue(v)
+	})
+}
+
+// UpdateValue sets the "value" field to the value that was provided on create.
+func (u *ContactFieldUpsertOne) UpdateValue() *ContactFieldUpsertOne {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateValue()
+	})
+}
+
+// Exec executes the query.
+func (u *ContactFieldUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ContactFieldCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ContactFieldUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *ContactFieldUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *ContactFieldUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// ContactFieldCreateBulk is the builder for creating many ContactField entities in bulk.
+type ContactFieldCreateBulk struct {
+	config
+	err      error
+	builders []*ContactFieldCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the ContactField entities in the database.
+func (cfcb *ContactFieldCreateBulk) Save(ctx context.Context) ([]*ContactField, error) {
+	if cfcb.err != nil {
+		return nil, cfcb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(cfcb.builders))
+	nodes := make([]*ContactField, len(cfcb.builders))
+	mutators := make([]Mutator, len(cfcb.builders))
+	for i := range cfcb.builders {
+		func(i int, root context.Context) {
+			builder := cfcb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*ContactFieldMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, cfcb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = cfcb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, cfcb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, cfcb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cfcb *ContactFieldCreateBulk) SaveX(ctx context.Context) []*ContactField {
+	v, err := cfcb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (cfcb *ContactFieldCreateBulk) Exec(ctx context.Context) error {
+	_, err := cfcb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cfcb *ContactFieldCreateBulk) ExecX(ctx context.Context) {
+	if err := cfcb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ContactField.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ContactFieldUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (cfcb *ContactFieldCreateBulk) OnConflict(opts ...sql.ConflictOption) *ContactFieldUpsertBulk {
+	cfcb.conflict = opts
+	return &ContactFieldUpsertBulk{
+		create: cfcb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (cfcb *ContactFieldCreateBulk) OnConflictColumns(columns ...string) *ContactFieldUpsertBulk {
+	cfcb.conflict = append(cfcb.conflict, sql.ConflictColumns(columns...))
+	return &ContactFieldUpsertBulk{
+		create: cfcb,
+	}
+}
+
+// ContactFieldUpsertBulk is the builder for "upsert"-ing
+// a bulk of ContactField nodes.
+type ContactFieldUpsertBulk struct {
+	create *ContactFieldCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(contactfield.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ContactFieldUpsertBulk) UpdateNewValues() *ContactFieldUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(contactfield.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(contactfield.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ContactField.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *ContactFieldUpsertBulk) Ignore() *ContactFieldUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ContactFieldUpsertBulk) DoNothing() *ContactFieldUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ContactFieldCreateBulk.OnConflict
+// documentation for more info.
+func (u *ContactFieldUpsertBulk) Update(set func(*ContactFieldUpsert)) *ContactFieldUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ContactFieldUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldUpsertBulk) SetUpdatedAt(v time.Time) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateUpdatedAt() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldUpsertBulk) SetStatus(v uint8) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldUpsertBulk) AddStatus(v uint8) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateStatus() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldUpsertBulk) ClearStatus() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldUpsertBulk) SetDeletedAt(v time.Time) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateDeletedAt() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldUpsertBulk) ClearDeletedAt() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetContactID sets the "contact_id" field.
+func (u *ContactFieldUpsertBulk) SetContactID(v uint64) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetContactID(v)
+	})
+}
+
+// UpdateContactID sets the "contact_id" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateContactID() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateContactID()
+	})
+}
+
+// SetFormID sets the "form_id" field.
+func (u *ContactFieldUpsertBulk) SetFormID(v string) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetFormID(v)
+	})
+}
+
+// UpdateFormID sets the "form_id" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateFormID() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateFormID()
+	})
+}
+
+// SetValue sets the "value" field.
+func (u *ContactFieldUpsertBulk) SetValue(v []string) *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.SetValue(v)
+	})
+}
+
+// UpdateValue sets the "value" field to the value that was provided on create.
+func (u *ContactFieldUpsertBulk) UpdateValue() *ContactFieldUpsertBulk {
+	return u.Update(func(s *ContactFieldUpsert) {
+		s.UpdateValue()
+	})
+}
+
+// Exec executes the query.
+func (u *ContactFieldUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ContactFieldCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ContactFieldCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ContactFieldUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/contactfield_delete.go

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

+ 605 - 0
ent/contactfield_query.go

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

+ 566 - 0
ent/contactfield_update.go

@@ -0,0 +1,566 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/dialect/sql/sqljson"
+	"entgo.io/ent/schema/field"
+)
+
+// ContactFieldUpdate is the builder for updating ContactField entities.
+type ContactFieldUpdate struct {
+	config
+	hooks    []Hook
+	mutation *ContactFieldMutation
+}
+
+// Where appends a list predicates to the ContactFieldUpdate builder.
+func (cfu *ContactFieldUpdate) Where(ps ...predicate.ContactField) *ContactFieldUpdate {
+	cfu.mutation.Where(ps...)
+	return cfu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cfu *ContactFieldUpdate) SetUpdatedAt(t time.Time) *ContactFieldUpdate {
+	cfu.mutation.SetUpdatedAt(t)
+	return cfu
+}
+
+// SetStatus sets the "status" field.
+func (cfu *ContactFieldUpdate) SetStatus(u uint8) *ContactFieldUpdate {
+	cfu.mutation.ResetStatus()
+	cfu.mutation.SetStatus(u)
+	return cfu
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cfu *ContactFieldUpdate) SetNillableStatus(u *uint8) *ContactFieldUpdate {
+	if u != nil {
+		cfu.SetStatus(*u)
+	}
+	return cfu
+}
+
+// AddStatus adds u to the "status" field.
+func (cfu *ContactFieldUpdate) AddStatus(u int8) *ContactFieldUpdate {
+	cfu.mutation.AddStatus(u)
+	return cfu
+}
+
+// ClearStatus clears the value of the "status" field.
+func (cfu *ContactFieldUpdate) ClearStatus() *ContactFieldUpdate {
+	cfu.mutation.ClearStatus()
+	return cfu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cfu *ContactFieldUpdate) SetDeletedAt(t time.Time) *ContactFieldUpdate {
+	cfu.mutation.SetDeletedAt(t)
+	return cfu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cfu *ContactFieldUpdate) SetNillableDeletedAt(t *time.Time) *ContactFieldUpdate {
+	if t != nil {
+		cfu.SetDeletedAt(*t)
+	}
+	return cfu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cfu *ContactFieldUpdate) ClearDeletedAt() *ContactFieldUpdate {
+	cfu.mutation.ClearDeletedAt()
+	return cfu
+}
+
+// SetContactID sets the "contact_id" field.
+func (cfu *ContactFieldUpdate) SetContactID(u uint64) *ContactFieldUpdate {
+	cfu.mutation.SetContactID(u)
+	return cfu
+}
+
+// SetNillableContactID sets the "contact_id" field if the given value is not nil.
+func (cfu *ContactFieldUpdate) SetNillableContactID(u *uint64) *ContactFieldUpdate {
+	if u != nil {
+		cfu.SetContactID(*u)
+	}
+	return cfu
+}
+
+// SetFormID sets the "form_id" field.
+func (cfu *ContactFieldUpdate) SetFormID(s string) *ContactFieldUpdate {
+	cfu.mutation.SetFormID(s)
+	return cfu
+}
+
+// SetNillableFormID sets the "form_id" field if the given value is not nil.
+func (cfu *ContactFieldUpdate) SetNillableFormID(s *string) *ContactFieldUpdate {
+	if s != nil {
+		cfu.SetFormID(*s)
+	}
+	return cfu
+}
+
+// SetValue sets the "value" field.
+func (cfu *ContactFieldUpdate) SetValue(s []string) *ContactFieldUpdate {
+	cfu.mutation.SetValue(s)
+	return cfu
+}
+
+// AppendValue appends s to the "value" field.
+func (cfu *ContactFieldUpdate) AppendValue(s []string) *ContactFieldUpdate {
+	cfu.mutation.AppendValue(s)
+	return cfu
+}
+
+// SetFieldContactID sets the "field_contact" edge to the Contact entity by ID.
+func (cfu *ContactFieldUpdate) SetFieldContactID(id uint64) *ContactFieldUpdate {
+	cfu.mutation.SetFieldContactID(id)
+	return cfu
+}
+
+// SetFieldContact sets the "field_contact" edge to the Contact entity.
+func (cfu *ContactFieldUpdate) SetFieldContact(c *Contact) *ContactFieldUpdate {
+	return cfu.SetFieldContactID(c.ID)
+}
+
+// Mutation returns the ContactFieldMutation object of the builder.
+func (cfu *ContactFieldUpdate) Mutation() *ContactFieldMutation {
+	return cfu.mutation
+}
+
+// ClearFieldContact clears the "field_contact" edge to the Contact entity.
+func (cfu *ContactFieldUpdate) ClearFieldContact() *ContactFieldUpdate {
+	cfu.mutation.ClearFieldContact()
+	return cfu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (cfu *ContactFieldUpdate) Save(ctx context.Context) (int, error) {
+	if err := cfu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, cfu.sqlSave, cfu.mutation, cfu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cfu *ContactFieldUpdate) SaveX(ctx context.Context) int {
+	affected, err := cfu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (cfu *ContactFieldUpdate) Exec(ctx context.Context) error {
+	_, err := cfu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cfu *ContactFieldUpdate) ExecX(ctx context.Context) {
+	if err := cfu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cfu *ContactFieldUpdate) defaults() error {
+	if _, ok := cfu.mutation.UpdatedAt(); !ok {
+		if contactfield.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfield.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfield.UpdateDefaultUpdatedAt()
+		cfu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (cfu *ContactFieldUpdate) check() error {
+	if _, ok := cfu.mutation.FieldContactID(); cfu.mutation.FieldContactCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "ContactField.field_contact"`)
+	}
+	return nil
+}
+
+func (cfu *ContactFieldUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := cfu.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(contactfield.Table, contactfield.Columns, sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64))
+	if ps := cfu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cfu.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfield.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cfu.mutation.Status(); ok {
+		_spec.SetField(contactfield.FieldStatus, field.TypeUint8, value)
+	}
+	if value, ok := cfu.mutation.AddedStatus(); ok {
+		_spec.AddField(contactfield.FieldStatus, field.TypeUint8, value)
+	}
+	if cfu.mutation.StatusCleared() {
+		_spec.ClearField(contactfield.FieldStatus, field.TypeUint8)
+	}
+	if value, ok := cfu.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfield.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cfu.mutation.DeletedAtCleared() {
+		_spec.ClearField(contactfield.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cfu.mutation.FormID(); ok {
+		_spec.SetField(contactfield.FieldFormID, field.TypeString, value)
+	}
+	if value, ok := cfu.mutation.Value(); ok {
+		_spec.SetField(contactfield.FieldValue, field.TypeJSON, value)
+	}
+	if value, ok := cfu.mutation.AppendedValue(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, contactfield.FieldValue, value)
+		})
+	}
+	if cfu.mutation.FieldContactCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   contactfield.FieldContactTable,
+			Columns: []string{contactfield.FieldContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cfu.mutation.FieldContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   contactfield.FieldContactTable,
+			Columns: []string{contactfield.FieldContactColumn},
+			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, cfu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{contactfield.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	cfu.mutation.done = true
+	return n, nil
+}
+
+// ContactFieldUpdateOne is the builder for updating a single ContactField entity.
+type ContactFieldUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *ContactFieldMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cfuo *ContactFieldUpdateOne) SetUpdatedAt(t time.Time) *ContactFieldUpdateOne {
+	cfuo.mutation.SetUpdatedAt(t)
+	return cfuo
+}
+
+// SetStatus sets the "status" field.
+func (cfuo *ContactFieldUpdateOne) SetStatus(u uint8) *ContactFieldUpdateOne {
+	cfuo.mutation.ResetStatus()
+	cfuo.mutation.SetStatus(u)
+	return cfuo
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cfuo *ContactFieldUpdateOne) SetNillableStatus(u *uint8) *ContactFieldUpdateOne {
+	if u != nil {
+		cfuo.SetStatus(*u)
+	}
+	return cfuo
+}
+
+// AddStatus adds u to the "status" field.
+func (cfuo *ContactFieldUpdateOne) AddStatus(u int8) *ContactFieldUpdateOne {
+	cfuo.mutation.AddStatus(u)
+	return cfuo
+}
+
+// ClearStatus clears the value of the "status" field.
+func (cfuo *ContactFieldUpdateOne) ClearStatus() *ContactFieldUpdateOne {
+	cfuo.mutation.ClearStatus()
+	return cfuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cfuo *ContactFieldUpdateOne) SetDeletedAt(t time.Time) *ContactFieldUpdateOne {
+	cfuo.mutation.SetDeletedAt(t)
+	return cfuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cfuo *ContactFieldUpdateOne) SetNillableDeletedAt(t *time.Time) *ContactFieldUpdateOne {
+	if t != nil {
+		cfuo.SetDeletedAt(*t)
+	}
+	return cfuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cfuo *ContactFieldUpdateOne) ClearDeletedAt() *ContactFieldUpdateOne {
+	cfuo.mutation.ClearDeletedAt()
+	return cfuo
+}
+
+// SetContactID sets the "contact_id" field.
+func (cfuo *ContactFieldUpdateOne) SetContactID(u uint64) *ContactFieldUpdateOne {
+	cfuo.mutation.SetContactID(u)
+	return cfuo
+}
+
+// SetNillableContactID sets the "contact_id" field if the given value is not nil.
+func (cfuo *ContactFieldUpdateOne) SetNillableContactID(u *uint64) *ContactFieldUpdateOne {
+	if u != nil {
+		cfuo.SetContactID(*u)
+	}
+	return cfuo
+}
+
+// SetFormID sets the "form_id" field.
+func (cfuo *ContactFieldUpdateOne) SetFormID(s string) *ContactFieldUpdateOne {
+	cfuo.mutation.SetFormID(s)
+	return cfuo
+}
+
+// SetNillableFormID sets the "form_id" field if the given value is not nil.
+func (cfuo *ContactFieldUpdateOne) SetNillableFormID(s *string) *ContactFieldUpdateOne {
+	if s != nil {
+		cfuo.SetFormID(*s)
+	}
+	return cfuo
+}
+
+// SetValue sets the "value" field.
+func (cfuo *ContactFieldUpdateOne) SetValue(s []string) *ContactFieldUpdateOne {
+	cfuo.mutation.SetValue(s)
+	return cfuo
+}
+
+// AppendValue appends s to the "value" field.
+func (cfuo *ContactFieldUpdateOne) AppendValue(s []string) *ContactFieldUpdateOne {
+	cfuo.mutation.AppendValue(s)
+	return cfuo
+}
+
+// SetFieldContactID sets the "field_contact" edge to the Contact entity by ID.
+func (cfuo *ContactFieldUpdateOne) SetFieldContactID(id uint64) *ContactFieldUpdateOne {
+	cfuo.mutation.SetFieldContactID(id)
+	return cfuo
+}
+
+// SetFieldContact sets the "field_contact" edge to the Contact entity.
+func (cfuo *ContactFieldUpdateOne) SetFieldContact(c *Contact) *ContactFieldUpdateOne {
+	return cfuo.SetFieldContactID(c.ID)
+}
+
+// Mutation returns the ContactFieldMutation object of the builder.
+func (cfuo *ContactFieldUpdateOne) Mutation() *ContactFieldMutation {
+	return cfuo.mutation
+}
+
+// ClearFieldContact clears the "field_contact" edge to the Contact entity.
+func (cfuo *ContactFieldUpdateOne) ClearFieldContact() *ContactFieldUpdateOne {
+	cfuo.mutation.ClearFieldContact()
+	return cfuo
+}
+
+// Where appends a list predicates to the ContactFieldUpdate builder.
+func (cfuo *ContactFieldUpdateOne) Where(ps ...predicate.ContactField) *ContactFieldUpdateOne {
+	cfuo.mutation.Where(ps...)
+	return cfuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (cfuo *ContactFieldUpdateOne) Select(field string, fields ...string) *ContactFieldUpdateOne {
+	cfuo.fields = append([]string{field}, fields...)
+	return cfuo
+}
+
+// Save executes the query and returns the updated ContactField entity.
+func (cfuo *ContactFieldUpdateOne) Save(ctx context.Context) (*ContactField, error) {
+	if err := cfuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, cfuo.sqlSave, cfuo.mutation, cfuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cfuo *ContactFieldUpdateOne) SaveX(ctx context.Context) *ContactField {
+	node, err := cfuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (cfuo *ContactFieldUpdateOne) Exec(ctx context.Context) error {
+	_, err := cfuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cfuo *ContactFieldUpdateOne) ExecX(ctx context.Context) {
+	if err := cfuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cfuo *ContactFieldUpdateOne) defaults() error {
+	if _, ok := cfuo.mutation.UpdatedAt(); !ok {
+		if contactfield.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfield.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfield.UpdateDefaultUpdatedAt()
+		cfuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (cfuo *ContactFieldUpdateOne) check() error {
+	if _, ok := cfuo.mutation.FieldContactID(); cfuo.mutation.FieldContactCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "ContactField.field_contact"`)
+	}
+	return nil
+}
+
+func (cfuo *ContactFieldUpdateOne) sqlSave(ctx context.Context) (_node *ContactField, err error) {
+	if err := cfuo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(contactfield.Table, contactfield.Columns, sqlgraph.NewFieldSpec(contactfield.FieldID, field.TypeUint64))
+	id, ok := cfuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ContactField.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := cfuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, contactfield.FieldID)
+		for _, f := range fields {
+			if !contactfield.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != contactfield.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := cfuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cfuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfield.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cfuo.mutation.Status(); ok {
+		_spec.SetField(contactfield.FieldStatus, field.TypeUint8, value)
+	}
+	if value, ok := cfuo.mutation.AddedStatus(); ok {
+		_spec.AddField(contactfield.FieldStatus, field.TypeUint8, value)
+	}
+	if cfuo.mutation.StatusCleared() {
+		_spec.ClearField(contactfield.FieldStatus, field.TypeUint8)
+	}
+	if value, ok := cfuo.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfield.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cfuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(contactfield.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cfuo.mutation.FormID(); ok {
+		_spec.SetField(contactfield.FieldFormID, field.TypeString, value)
+	}
+	if value, ok := cfuo.mutation.Value(); ok {
+		_spec.SetField(contactfield.FieldValue, field.TypeJSON, value)
+	}
+	if value, ok := cfuo.mutation.AppendedValue(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, contactfield.FieldValue, value)
+		})
+	}
+	if cfuo.mutation.FieldContactCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   contactfield.FieldContactTable,
+			Columns: []string{contactfield.FieldContactColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(contact.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := cfuo.mutation.FieldContactIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   contactfield.FieldContactTable,
+			Columns: []string{contactfield.FieldContactColumn},
+			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 = &ContactField{config: cfuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, cfuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{contactfield.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	cfuo.mutation.done = true
+	return _node, nil
+}

+ 165 - 0
ent/contactfieldtemplate.go

@@ -0,0 +1,165 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/ent/custom_types"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// ContactFieldTemplate is the model entity for the ContactFieldTemplate schema.
+type ContactFieldTemplate struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Status uint8 `json:"status,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// 机构 ID
+	OrganizationID uint64 `json:"organization_id,omitempty"`
+	// 模板
+	Template     []custom_types.ContactFieldTemplate `json:"template,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*ContactFieldTemplate) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case contactfieldtemplate.FieldTemplate:
+			values[i] = new([]byte)
+		case contactfieldtemplate.FieldID, contactfieldtemplate.FieldStatus, contactfieldtemplate.FieldOrganizationID:
+			values[i] = new(sql.NullInt64)
+		case contactfieldtemplate.FieldCreatedAt, contactfieldtemplate.FieldUpdatedAt, contactfieldtemplate.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the ContactFieldTemplate fields.
+func (cft *ContactFieldTemplate) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case contactfieldtemplate.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			cft.ID = uint64(value.Int64)
+		case contactfieldtemplate.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				cft.CreatedAt = value.Time
+			}
+		case contactfieldtemplate.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				cft.UpdatedAt = value.Time
+			}
+		case contactfieldtemplate.FieldStatus:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field status", values[i])
+			} else if value.Valid {
+				cft.Status = uint8(value.Int64)
+			}
+		case contactfieldtemplate.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				cft.DeletedAt = value.Time
+			}
+		case contactfieldtemplate.FieldOrganizationID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field organization_id", values[i])
+			} else if value.Valid {
+				cft.OrganizationID = uint64(value.Int64)
+			}
+		case contactfieldtemplate.FieldTemplate:
+			if value, ok := values[i].(*[]byte); !ok {
+				return fmt.Errorf("unexpected type %T for field template", values[i])
+			} else if value != nil && len(*value) > 0 {
+				if err := json.Unmarshal(*value, &cft.Template); err != nil {
+					return fmt.Errorf("unmarshal field template: %w", err)
+				}
+			}
+		default:
+			cft.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the ContactFieldTemplate.
+// This includes values selected through modifiers, order, etc.
+func (cft *ContactFieldTemplate) Value(name string) (ent.Value, error) {
+	return cft.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this ContactFieldTemplate.
+// Note that you need to call ContactFieldTemplate.Unwrap() before calling this method if this ContactFieldTemplate
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (cft *ContactFieldTemplate) Update() *ContactFieldTemplateUpdateOne {
+	return NewContactFieldTemplateClient(cft.config).UpdateOne(cft)
+}
+
+// Unwrap unwraps the ContactFieldTemplate entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (cft *ContactFieldTemplate) Unwrap() *ContactFieldTemplate {
+	_tx, ok := cft.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: ContactFieldTemplate is not a transactional entity")
+	}
+	cft.config.driver = _tx.drv
+	return cft
+}
+
+// String implements the fmt.Stringer.
+func (cft *ContactFieldTemplate) String() string {
+	var builder strings.Builder
+	builder.WriteString("ContactFieldTemplate(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", cft.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(cft.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(cft.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("status=")
+	builder.WriteString(fmt.Sprintf("%v", cft.Status))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(cft.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("organization_id=")
+	builder.WriteString(fmt.Sprintf("%v", cft.OrganizationID))
+	builder.WriteString(", ")
+	builder.WriteString("template=")
+	builder.WriteString(fmt.Sprintf("%v", cft.Template))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// ContactFieldTemplates is a parsable slice of ContactFieldTemplate.
+type ContactFieldTemplates []*ContactFieldTemplate

+ 105 - 0
ent/contactfieldtemplate/contactfieldtemplate.go

@@ -0,0 +1,105 @@
+// Code generated by ent, DO NOT EDIT.
+
+package contactfieldtemplate
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the contactfieldtemplate type in the database.
+	Label = "contact_field_template"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldStatus holds the string denoting the status field in the database.
+	FieldStatus = "status"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldOrganizationID holds the string denoting the organization_id field in the database.
+	FieldOrganizationID = "organization_id"
+	// FieldTemplate holds the string denoting the template field in the database.
+	FieldTemplate = "template"
+	// Table holds the table name of the contactfieldtemplate in the database.
+	Table = "contact_field_template"
+)
+
+// Columns holds all SQL columns for contactfieldtemplate fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldStatus,
+	FieldDeletedAt,
+	FieldOrganizationID,
+	FieldTemplate,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultStatus holds the default value on creation for the "status" field.
+	DefaultStatus uint8
+	// DefaultOrganizationID holds the default value on creation for the "organization_id" field.
+	DefaultOrganizationID uint64
+)
+
+// OrderOption defines the ordering options for the ContactFieldTemplate queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByStatus orders the results by the status field.
+func ByStatus(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldStatus, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByOrganizationID orders the results by the organization_id field.
+func ByOrganizationID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOrganizationID, opts...).ToFunc()
+}

+ 315 - 0
ent/contactfieldtemplate/where.go

@@ -0,0 +1,315 @@
+// Code generated by ent, DO NOT EDIT.
+
+package contactfieldtemplate
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// Status applies equality check predicate on the "status" field. It's identical to StatusEQ.
+func Status(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldStatus, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// OrganizationID applies equality check predicate on the "organization_id" field. It's identical to OrganizationIDEQ.
+func OrganizationID(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// StatusEQ applies the EQ predicate on the "status" field.
+func StatusEQ(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldStatus, v))
+}
+
+// StatusNEQ applies the NEQ predicate on the "status" field.
+func StatusNEQ(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldStatus, v))
+}
+
+// StatusIn applies the In predicate on the "status" field.
+func StatusIn(vs ...uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldStatus, vs...))
+}
+
+// StatusNotIn applies the NotIn predicate on the "status" field.
+func StatusNotIn(vs ...uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldStatus, vs...))
+}
+
+// StatusGT applies the GT predicate on the "status" field.
+func StatusGT(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldStatus, v))
+}
+
+// StatusGTE applies the GTE predicate on the "status" field.
+func StatusGTE(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldStatus, v))
+}
+
+// StatusLT applies the LT predicate on the "status" field.
+func StatusLT(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldStatus, v))
+}
+
+// StatusLTE applies the LTE predicate on the "status" field.
+func StatusLTE(v uint8) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldStatus, v))
+}
+
+// StatusIsNil applies the IsNil predicate on the "status" field.
+func StatusIsNil() predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIsNull(FieldStatus))
+}
+
+// StatusNotNil applies the NotNil predicate on the "status" field.
+func StatusNotNil() predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotNull(FieldStatus))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// OrganizationIDEQ applies the EQ predicate on the "organization_id" field.
+func OrganizationIDEQ(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDNEQ applies the NEQ predicate on the "organization_id" field.
+func OrganizationIDNEQ(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDIn applies the In predicate on the "organization_id" field.
+func OrganizationIDIn(vs ...uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDNotIn applies the NotIn predicate on the "organization_id" field.
+func OrganizationIDNotIn(vs ...uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldNotIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDGT applies the GT predicate on the "organization_id" field.
+func OrganizationIDGT(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGT(FieldOrganizationID, v))
+}
+
+// OrganizationIDGTE applies the GTE predicate on the "organization_id" field.
+func OrganizationIDGTE(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldGTE(FieldOrganizationID, v))
+}
+
+// OrganizationIDLT applies the LT predicate on the "organization_id" field.
+func OrganizationIDLT(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLT(FieldOrganizationID, v))
+}
+
+// OrganizationIDLTE applies the LTE predicate on the "organization_id" field.
+func OrganizationIDLTE(v uint64) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.FieldLTE(FieldOrganizationID, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.ContactFieldTemplate) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.ContactFieldTemplate) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.ContactFieldTemplate) predicate.ContactFieldTemplate {
+	return predicate.ContactFieldTemplate(sql.NotPredicates(p))
+}

+ 862 - 0
ent/contactfieldtemplate_create.go

@@ -0,0 +1,862 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/ent/custom_types"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ContactFieldTemplateCreate is the builder for creating a ContactFieldTemplate entity.
+type ContactFieldTemplateCreate struct {
+	config
+	mutation *ContactFieldTemplateMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (cftc *ContactFieldTemplateCreate) SetCreatedAt(t time.Time) *ContactFieldTemplateCreate {
+	cftc.mutation.SetCreatedAt(t)
+	return cftc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (cftc *ContactFieldTemplateCreate) SetNillableCreatedAt(t *time.Time) *ContactFieldTemplateCreate {
+	if t != nil {
+		cftc.SetCreatedAt(*t)
+	}
+	return cftc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cftc *ContactFieldTemplateCreate) SetUpdatedAt(t time.Time) *ContactFieldTemplateCreate {
+	cftc.mutation.SetUpdatedAt(t)
+	return cftc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (cftc *ContactFieldTemplateCreate) SetNillableUpdatedAt(t *time.Time) *ContactFieldTemplateCreate {
+	if t != nil {
+		cftc.SetUpdatedAt(*t)
+	}
+	return cftc
+}
+
+// SetStatus sets the "status" field.
+func (cftc *ContactFieldTemplateCreate) SetStatus(u uint8) *ContactFieldTemplateCreate {
+	cftc.mutation.SetStatus(u)
+	return cftc
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cftc *ContactFieldTemplateCreate) SetNillableStatus(u *uint8) *ContactFieldTemplateCreate {
+	if u != nil {
+		cftc.SetStatus(*u)
+	}
+	return cftc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cftc *ContactFieldTemplateCreate) SetDeletedAt(t time.Time) *ContactFieldTemplateCreate {
+	cftc.mutation.SetDeletedAt(t)
+	return cftc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cftc *ContactFieldTemplateCreate) SetNillableDeletedAt(t *time.Time) *ContactFieldTemplateCreate {
+	if t != nil {
+		cftc.SetDeletedAt(*t)
+	}
+	return cftc
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (cftc *ContactFieldTemplateCreate) SetOrganizationID(u uint64) *ContactFieldTemplateCreate {
+	cftc.mutation.SetOrganizationID(u)
+	return cftc
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (cftc *ContactFieldTemplateCreate) SetNillableOrganizationID(u *uint64) *ContactFieldTemplateCreate {
+	if u != nil {
+		cftc.SetOrganizationID(*u)
+	}
+	return cftc
+}
+
+// SetTemplate sets the "template" field.
+func (cftc *ContactFieldTemplateCreate) SetTemplate(ctft []custom_types.ContactFieldTemplate) *ContactFieldTemplateCreate {
+	cftc.mutation.SetTemplate(ctft)
+	return cftc
+}
+
+// SetID sets the "id" field.
+func (cftc *ContactFieldTemplateCreate) SetID(u uint64) *ContactFieldTemplateCreate {
+	cftc.mutation.SetID(u)
+	return cftc
+}
+
+// Mutation returns the ContactFieldTemplateMutation object of the builder.
+func (cftc *ContactFieldTemplateCreate) Mutation() *ContactFieldTemplateMutation {
+	return cftc.mutation
+}
+
+// Save creates the ContactFieldTemplate in the database.
+func (cftc *ContactFieldTemplateCreate) Save(ctx context.Context) (*ContactFieldTemplate, error) {
+	if err := cftc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, cftc.sqlSave, cftc.mutation, cftc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (cftc *ContactFieldTemplateCreate) SaveX(ctx context.Context) *ContactFieldTemplate {
+	v, err := cftc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (cftc *ContactFieldTemplateCreate) Exec(ctx context.Context) error {
+	_, err := cftc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cftc *ContactFieldTemplateCreate) ExecX(ctx context.Context) {
+	if err := cftc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cftc *ContactFieldTemplateCreate) defaults() error {
+	if _, ok := cftc.mutation.CreatedAt(); !ok {
+		if contactfieldtemplate.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfieldtemplate.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfieldtemplate.DefaultCreatedAt()
+		cftc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := cftc.mutation.UpdatedAt(); !ok {
+		if contactfieldtemplate.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfieldtemplate.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfieldtemplate.DefaultUpdatedAt()
+		cftc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := cftc.mutation.Status(); !ok {
+		v := contactfieldtemplate.DefaultStatus
+		cftc.mutation.SetStatus(v)
+	}
+	if _, ok := cftc.mutation.OrganizationID(); !ok {
+		v := contactfieldtemplate.DefaultOrganizationID
+		cftc.mutation.SetOrganizationID(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (cftc *ContactFieldTemplateCreate) check() error {
+	if _, ok := cftc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ContactFieldTemplate.created_at"`)}
+	}
+	if _, ok := cftc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ContactFieldTemplate.updated_at"`)}
+	}
+	if _, ok := cftc.mutation.OrganizationID(); !ok {
+		return &ValidationError{Name: "organization_id", err: errors.New(`ent: missing required field "ContactFieldTemplate.organization_id"`)}
+	}
+	if _, ok := cftc.mutation.Template(); !ok {
+		return &ValidationError{Name: "template", err: errors.New(`ent: missing required field "ContactFieldTemplate.template"`)}
+	}
+	return nil
+}
+
+func (cftc *ContactFieldTemplateCreate) sqlSave(ctx context.Context) (*ContactFieldTemplate, error) {
+	if err := cftc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := cftc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, cftc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	cftc.mutation.id = &_node.ID
+	cftc.mutation.done = true
+	return _node, nil
+}
+
+func (cftc *ContactFieldTemplateCreate) createSpec() (*ContactFieldTemplate, *sqlgraph.CreateSpec) {
+	var (
+		_node = &ContactFieldTemplate{config: cftc.config}
+		_spec = sqlgraph.NewCreateSpec(contactfieldtemplate.Table, sqlgraph.NewFieldSpec(contactfieldtemplate.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = cftc.conflict
+	if id, ok := cftc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := cftc.mutation.CreatedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := cftc.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := cftc.mutation.Status(); ok {
+		_spec.SetField(contactfieldtemplate.FieldStatus, field.TypeUint8, value)
+		_node.Status = value
+	}
+	if value, ok := cftc.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := cftc.mutation.OrganizationID(); ok {
+		_spec.SetField(contactfieldtemplate.FieldOrganizationID, field.TypeUint64, value)
+		_node.OrganizationID = value
+	}
+	if value, ok := cftc.mutation.Template(); ok {
+		_spec.SetField(contactfieldtemplate.FieldTemplate, field.TypeJSON, value)
+		_node.Template = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ContactFieldTemplate.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ContactFieldTemplateUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (cftc *ContactFieldTemplateCreate) OnConflict(opts ...sql.ConflictOption) *ContactFieldTemplateUpsertOne {
+	cftc.conflict = opts
+	return &ContactFieldTemplateUpsertOne{
+		create: cftc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (cftc *ContactFieldTemplateCreate) OnConflictColumns(columns ...string) *ContactFieldTemplateUpsertOne {
+	cftc.conflict = append(cftc.conflict, sql.ConflictColumns(columns...))
+	return &ContactFieldTemplateUpsertOne{
+		create: cftc,
+	}
+}
+
+type (
+	// ContactFieldTemplateUpsertOne is the builder for "upsert"-ing
+	//  one ContactFieldTemplate node.
+	ContactFieldTemplateUpsertOne struct {
+		create *ContactFieldTemplateCreate
+	}
+
+	// ContactFieldTemplateUpsert is the "OnConflict" setter.
+	ContactFieldTemplateUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldTemplateUpsert) SetUpdatedAt(v time.Time) *ContactFieldTemplateUpsert {
+	u.Set(contactfieldtemplate.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsert) UpdateUpdatedAt() *ContactFieldTemplateUpsert {
+	u.SetExcluded(contactfieldtemplate.FieldUpdatedAt)
+	return u
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldTemplateUpsert) SetStatus(v uint8) *ContactFieldTemplateUpsert {
+	u.Set(contactfieldtemplate.FieldStatus, v)
+	return u
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsert) UpdateStatus() *ContactFieldTemplateUpsert {
+	u.SetExcluded(contactfieldtemplate.FieldStatus)
+	return u
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldTemplateUpsert) AddStatus(v uint8) *ContactFieldTemplateUpsert {
+	u.Add(contactfieldtemplate.FieldStatus, v)
+	return u
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldTemplateUpsert) ClearStatus() *ContactFieldTemplateUpsert {
+	u.SetNull(contactfieldtemplate.FieldStatus)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldTemplateUpsert) SetDeletedAt(v time.Time) *ContactFieldTemplateUpsert {
+	u.Set(contactfieldtemplate.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsert) UpdateDeletedAt() *ContactFieldTemplateUpsert {
+	u.SetExcluded(contactfieldtemplate.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldTemplateUpsert) ClearDeletedAt() *ContactFieldTemplateUpsert {
+	u.SetNull(contactfieldtemplate.FieldDeletedAt)
+	return u
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *ContactFieldTemplateUpsert) SetOrganizationID(v uint64) *ContactFieldTemplateUpsert {
+	u.Set(contactfieldtemplate.FieldOrganizationID, v)
+	return u
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsert) UpdateOrganizationID() *ContactFieldTemplateUpsert {
+	u.SetExcluded(contactfieldtemplate.FieldOrganizationID)
+	return u
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *ContactFieldTemplateUpsert) AddOrganizationID(v uint64) *ContactFieldTemplateUpsert {
+	u.Add(contactfieldtemplate.FieldOrganizationID, v)
+	return u
+}
+
+// SetTemplate sets the "template" field.
+func (u *ContactFieldTemplateUpsert) SetTemplate(v []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpsert {
+	u.Set(contactfieldtemplate.FieldTemplate, v)
+	return u
+}
+
+// UpdateTemplate sets the "template" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsert) UpdateTemplate() *ContactFieldTemplateUpsert {
+	u.SetExcluded(contactfieldtemplate.FieldTemplate)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(contactfieldtemplate.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ContactFieldTemplateUpsertOne) UpdateNewValues() *ContactFieldTemplateUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(contactfieldtemplate.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(contactfieldtemplate.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *ContactFieldTemplateUpsertOne) Ignore() *ContactFieldTemplateUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ContactFieldTemplateUpsertOne) DoNothing() *ContactFieldTemplateUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ContactFieldTemplateCreate.OnConflict
+// documentation for more info.
+func (u *ContactFieldTemplateUpsertOne) Update(set func(*ContactFieldTemplateUpsert)) *ContactFieldTemplateUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ContactFieldTemplateUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldTemplateUpsertOne) SetUpdatedAt(v time.Time) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertOne) UpdateUpdatedAt() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldTemplateUpsertOne) SetStatus(v uint8) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldTemplateUpsertOne) AddStatus(v uint8) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertOne) UpdateStatus() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldTemplateUpsertOne) ClearStatus() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldTemplateUpsertOne) SetDeletedAt(v time.Time) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertOne) UpdateDeletedAt() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldTemplateUpsertOne) ClearDeletedAt() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *ContactFieldTemplateUpsertOne) SetOrganizationID(v uint64) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *ContactFieldTemplateUpsertOne) AddOrganizationID(v uint64) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertOne) UpdateOrganizationID() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// SetTemplate sets the "template" field.
+func (u *ContactFieldTemplateUpsertOne) SetTemplate(v []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetTemplate(v)
+	})
+}
+
+// UpdateTemplate sets the "template" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertOne) UpdateTemplate() *ContactFieldTemplateUpsertOne {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateTemplate()
+	})
+}
+
+// Exec executes the query.
+func (u *ContactFieldTemplateUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ContactFieldTemplateCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ContactFieldTemplateUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *ContactFieldTemplateUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *ContactFieldTemplateUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// ContactFieldTemplateCreateBulk is the builder for creating many ContactFieldTemplate entities in bulk.
+type ContactFieldTemplateCreateBulk struct {
+	config
+	err      error
+	builders []*ContactFieldTemplateCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the ContactFieldTemplate entities in the database.
+func (cftcb *ContactFieldTemplateCreateBulk) Save(ctx context.Context) ([]*ContactFieldTemplate, error) {
+	if cftcb.err != nil {
+		return nil, cftcb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(cftcb.builders))
+	nodes := make([]*ContactFieldTemplate, len(cftcb.builders))
+	mutators := make([]Mutator, len(cftcb.builders))
+	for i := range cftcb.builders {
+		func(i int, root context.Context) {
+			builder := cftcb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*ContactFieldTemplateMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, cftcb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = cftcb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, cftcb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, cftcb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cftcb *ContactFieldTemplateCreateBulk) SaveX(ctx context.Context) []*ContactFieldTemplate {
+	v, err := cftcb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (cftcb *ContactFieldTemplateCreateBulk) Exec(ctx context.Context) error {
+	_, err := cftcb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cftcb *ContactFieldTemplateCreateBulk) ExecX(ctx context.Context) {
+	if err := cftcb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ContactFieldTemplate.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ContactFieldTemplateUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (cftcb *ContactFieldTemplateCreateBulk) OnConflict(opts ...sql.ConflictOption) *ContactFieldTemplateUpsertBulk {
+	cftcb.conflict = opts
+	return &ContactFieldTemplateUpsertBulk{
+		create: cftcb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (cftcb *ContactFieldTemplateCreateBulk) OnConflictColumns(columns ...string) *ContactFieldTemplateUpsertBulk {
+	cftcb.conflict = append(cftcb.conflict, sql.ConflictColumns(columns...))
+	return &ContactFieldTemplateUpsertBulk{
+		create: cftcb,
+	}
+}
+
+// ContactFieldTemplateUpsertBulk is the builder for "upsert"-ing
+// a bulk of ContactFieldTemplate nodes.
+type ContactFieldTemplateUpsertBulk struct {
+	create *ContactFieldTemplateCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(contactfieldtemplate.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ContactFieldTemplateUpsertBulk) UpdateNewValues() *ContactFieldTemplateUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(contactfieldtemplate.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(contactfieldtemplate.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ContactFieldTemplate.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *ContactFieldTemplateUpsertBulk) Ignore() *ContactFieldTemplateUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ContactFieldTemplateUpsertBulk) DoNothing() *ContactFieldTemplateUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ContactFieldTemplateCreateBulk.OnConflict
+// documentation for more info.
+func (u *ContactFieldTemplateUpsertBulk) Update(set func(*ContactFieldTemplateUpsert)) *ContactFieldTemplateUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ContactFieldTemplateUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ContactFieldTemplateUpsertBulk) SetUpdatedAt(v time.Time) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertBulk) UpdateUpdatedAt() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetStatus sets the "status" field.
+func (u *ContactFieldTemplateUpsertBulk) SetStatus(v uint8) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetStatus(v)
+	})
+}
+
+// AddStatus adds v to the "status" field.
+func (u *ContactFieldTemplateUpsertBulk) AddStatus(v uint8) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.AddStatus(v)
+	})
+}
+
+// UpdateStatus sets the "status" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertBulk) UpdateStatus() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateStatus()
+	})
+}
+
+// ClearStatus clears the value of the "status" field.
+func (u *ContactFieldTemplateUpsertBulk) ClearStatus() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.ClearStatus()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ContactFieldTemplateUpsertBulk) SetDeletedAt(v time.Time) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertBulk) UpdateDeletedAt() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ContactFieldTemplateUpsertBulk) ClearDeletedAt() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *ContactFieldTemplateUpsertBulk) SetOrganizationID(v uint64) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *ContactFieldTemplateUpsertBulk) AddOrganizationID(v uint64) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertBulk) UpdateOrganizationID() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// SetTemplate sets the "template" field.
+func (u *ContactFieldTemplateUpsertBulk) SetTemplate(v []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.SetTemplate(v)
+	})
+}
+
+// UpdateTemplate sets the "template" field to the value that was provided on create.
+func (u *ContactFieldTemplateUpsertBulk) UpdateTemplate() *ContactFieldTemplateUpsertBulk {
+	return u.Update(func(s *ContactFieldTemplateUpsert) {
+		s.UpdateTemplate()
+	})
+}
+
+// Exec executes the query.
+func (u *ContactFieldTemplateUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ContactFieldTemplateCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ContactFieldTemplateCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ContactFieldTemplateUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/contactfieldtemplate_delete.go

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

+ 526 - 0
ent/contactfieldtemplate_query.go

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

+ 444 - 0
ent/contactfieldtemplate_update.go

@@ -0,0 +1,444 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/ent/custom_types"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/dialect/sql/sqljson"
+	"entgo.io/ent/schema/field"
+)
+
+// ContactFieldTemplateUpdate is the builder for updating ContactFieldTemplate entities.
+type ContactFieldTemplateUpdate struct {
+	config
+	hooks    []Hook
+	mutation *ContactFieldTemplateMutation
+}
+
+// Where appends a list predicates to the ContactFieldTemplateUpdate builder.
+func (cftu *ContactFieldTemplateUpdate) Where(ps ...predicate.ContactFieldTemplate) *ContactFieldTemplateUpdate {
+	cftu.mutation.Where(ps...)
+	return cftu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cftu *ContactFieldTemplateUpdate) SetUpdatedAt(t time.Time) *ContactFieldTemplateUpdate {
+	cftu.mutation.SetUpdatedAt(t)
+	return cftu
+}
+
+// SetStatus sets the "status" field.
+func (cftu *ContactFieldTemplateUpdate) SetStatus(u uint8) *ContactFieldTemplateUpdate {
+	cftu.mutation.ResetStatus()
+	cftu.mutation.SetStatus(u)
+	return cftu
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cftu *ContactFieldTemplateUpdate) SetNillableStatus(u *uint8) *ContactFieldTemplateUpdate {
+	if u != nil {
+		cftu.SetStatus(*u)
+	}
+	return cftu
+}
+
+// AddStatus adds u to the "status" field.
+func (cftu *ContactFieldTemplateUpdate) AddStatus(u int8) *ContactFieldTemplateUpdate {
+	cftu.mutation.AddStatus(u)
+	return cftu
+}
+
+// ClearStatus clears the value of the "status" field.
+func (cftu *ContactFieldTemplateUpdate) ClearStatus() *ContactFieldTemplateUpdate {
+	cftu.mutation.ClearStatus()
+	return cftu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cftu *ContactFieldTemplateUpdate) SetDeletedAt(t time.Time) *ContactFieldTemplateUpdate {
+	cftu.mutation.SetDeletedAt(t)
+	return cftu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cftu *ContactFieldTemplateUpdate) SetNillableDeletedAt(t *time.Time) *ContactFieldTemplateUpdate {
+	if t != nil {
+		cftu.SetDeletedAt(*t)
+	}
+	return cftu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cftu *ContactFieldTemplateUpdate) ClearDeletedAt() *ContactFieldTemplateUpdate {
+	cftu.mutation.ClearDeletedAt()
+	return cftu
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (cftu *ContactFieldTemplateUpdate) SetOrganizationID(u uint64) *ContactFieldTemplateUpdate {
+	cftu.mutation.ResetOrganizationID()
+	cftu.mutation.SetOrganizationID(u)
+	return cftu
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (cftu *ContactFieldTemplateUpdate) SetNillableOrganizationID(u *uint64) *ContactFieldTemplateUpdate {
+	if u != nil {
+		cftu.SetOrganizationID(*u)
+	}
+	return cftu
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (cftu *ContactFieldTemplateUpdate) AddOrganizationID(u int64) *ContactFieldTemplateUpdate {
+	cftu.mutation.AddOrganizationID(u)
+	return cftu
+}
+
+// SetTemplate sets the "template" field.
+func (cftu *ContactFieldTemplateUpdate) SetTemplate(ctft []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdate {
+	cftu.mutation.SetTemplate(ctft)
+	return cftu
+}
+
+// AppendTemplate appends ctft to the "template" field.
+func (cftu *ContactFieldTemplateUpdate) AppendTemplate(ctft []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdate {
+	cftu.mutation.AppendTemplate(ctft)
+	return cftu
+}
+
+// Mutation returns the ContactFieldTemplateMutation object of the builder.
+func (cftu *ContactFieldTemplateUpdate) Mutation() *ContactFieldTemplateMutation {
+	return cftu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (cftu *ContactFieldTemplateUpdate) Save(ctx context.Context) (int, error) {
+	if err := cftu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, cftu.sqlSave, cftu.mutation, cftu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cftu *ContactFieldTemplateUpdate) SaveX(ctx context.Context) int {
+	affected, err := cftu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (cftu *ContactFieldTemplateUpdate) Exec(ctx context.Context) error {
+	_, err := cftu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cftu *ContactFieldTemplateUpdate) ExecX(ctx context.Context) {
+	if err := cftu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cftu *ContactFieldTemplateUpdate) defaults() error {
+	if _, ok := cftu.mutation.UpdatedAt(); !ok {
+		if contactfieldtemplate.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfieldtemplate.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfieldtemplate.UpdateDefaultUpdatedAt()
+		cftu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (cftu *ContactFieldTemplateUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(contactfieldtemplate.Table, contactfieldtemplate.Columns, sqlgraph.NewFieldSpec(contactfieldtemplate.FieldID, field.TypeUint64))
+	if ps := cftu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cftu.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cftu.mutation.Status(); ok {
+		_spec.SetField(contactfieldtemplate.FieldStatus, field.TypeUint8, value)
+	}
+	if value, ok := cftu.mutation.AddedStatus(); ok {
+		_spec.AddField(contactfieldtemplate.FieldStatus, field.TypeUint8, value)
+	}
+	if cftu.mutation.StatusCleared() {
+		_spec.ClearField(contactfieldtemplate.FieldStatus, field.TypeUint8)
+	}
+	if value, ok := cftu.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cftu.mutation.DeletedAtCleared() {
+		_spec.ClearField(contactfieldtemplate.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cftu.mutation.OrganizationID(); ok {
+		_spec.SetField(contactfieldtemplate.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := cftu.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(contactfieldtemplate.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := cftu.mutation.Template(); ok {
+		_spec.SetField(contactfieldtemplate.FieldTemplate, field.TypeJSON, value)
+	}
+	if value, ok := cftu.mutation.AppendedTemplate(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, contactfieldtemplate.FieldTemplate, value)
+		})
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, cftu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{contactfieldtemplate.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	cftu.mutation.done = true
+	return n, nil
+}
+
+// ContactFieldTemplateUpdateOne is the builder for updating a single ContactFieldTemplate entity.
+type ContactFieldTemplateUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *ContactFieldTemplateMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cftuo *ContactFieldTemplateUpdateOne) SetUpdatedAt(t time.Time) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.SetUpdatedAt(t)
+	return cftuo
+}
+
+// SetStatus sets the "status" field.
+func (cftuo *ContactFieldTemplateUpdateOne) SetStatus(u uint8) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.ResetStatus()
+	cftuo.mutation.SetStatus(u)
+	return cftuo
+}
+
+// SetNillableStatus sets the "status" field if the given value is not nil.
+func (cftuo *ContactFieldTemplateUpdateOne) SetNillableStatus(u *uint8) *ContactFieldTemplateUpdateOne {
+	if u != nil {
+		cftuo.SetStatus(*u)
+	}
+	return cftuo
+}
+
+// AddStatus adds u to the "status" field.
+func (cftuo *ContactFieldTemplateUpdateOne) AddStatus(u int8) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.AddStatus(u)
+	return cftuo
+}
+
+// ClearStatus clears the value of the "status" field.
+func (cftuo *ContactFieldTemplateUpdateOne) ClearStatus() *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.ClearStatus()
+	return cftuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cftuo *ContactFieldTemplateUpdateOne) SetDeletedAt(t time.Time) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.SetDeletedAt(t)
+	return cftuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cftuo *ContactFieldTemplateUpdateOne) SetNillableDeletedAt(t *time.Time) *ContactFieldTemplateUpdateOne {
+	if t != nil {
+		cftuo.SetDeletedAt(*t)
+	}
+	return cftuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cftuo *ContactFieldTemplateUpdateOne) ClearDeletedAt() *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.ClearDeletedAt()
+	return cftuo
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (cftuo *ContactFieldTemplateUpdateOne) SetOrganizationID(u uint64) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.ResetOrganizationID()
+	cftuo.mutation.SetOrganizationID(u)
+	return cftuo
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (cftuo *ContactFieldTemplateUpdateOne) SetNillableOrganizationID(u *uint64) *ContactFieldTemplateUpdateOne {
+	if u != nil {
+		cftuo.SetOrganizationID(*u)
+	}
+	return cftuo
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (cftuo *ContactFieldTemplateUpdateOne) AddOrganizationID(u int64) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.AddOrganizationID(u)
+	return cftuo
+}
+
+// SetTemplate sets the "template" field.
+func (cftuo *ContactFieldTemplateUpdateOne) SetTemplate(ctft []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.SetTemplate(ctft)
+	return cftuo
+}
+
+// AppendTemplate appends ctft to the "template" field.
+func (cftuo *ContactFieldTemplateUpdateOne) AppendTemplate(ctft []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.AppendTemplate(ctft)
+	return cftuo
+}
+
+// Mutation returns the ContactFieldTemplateMutation object of the builder.
+func (cftuo *ContactFieldTemplateUpdateOne) Mutation() *ContactFieldTemplateMutation {
+	return cftuo.mutation
+}
+
+// Where appends a list predicates to the ContactFieldTemplateUpdate builder.
+func (cftuo *ContactFieldTemplateUpdateOne) Where(ps ...predicate.ContactFieldTemplate) *ContactFieldTemplateUpdateOne {
+	cftuo.mutation.Where(ps...)
+	return cftuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (cftuo *ContactFieldTemplateUpdateOne) Select(field string, fields ...string) *ContactFieldTemplateUpdateOne {
+	cftuo.fields = append([]string{field}, fields...)
+	return cftuo
+}
+
+// Save executes the query and returns the updated ContactFieldTemplate entity.
+func (cftuo *ContactFieldTemplateUpdateOne) Save(ctx context.Context) (*ContactFieldTemplate, error) {
+	if err := cftuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, cftuo.sqlSave, cftuo.mutation, cftuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cftuo *ContactFieldTemplateUpdateOne) SaveX(ctx context.Context) *ContactFieldTemplate {
+	node, err := cftuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (cftuo *ContactFieldTemplateUpdateOne) Exec(ctx context.Context) error {
+	_, err := cftuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cftuo *ContactFieldTemplateUpdateOne) ExecX(ctx context.Context) {
+	if err := cftuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cftuo *ContactFieldTemplateUpdateOne) defaults() error {
+	if _, ok := cftuo.mutation.UpdatedAt(); !ok {
+		if contactfieldtemplate.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized contactfieldtemplate.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := contactfieldtemplate.UpdateDefaultUpdatedAt()
+		cftuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (cftuo *ContactFieldTemplateUpdateOne) sqlSave(ctx context.Context) (_node *ContactFieldTemplate, err error) {
+	_spec := sqlgraph.NewUpdateSpec(contactfieldtemplate.Table, contactfieldtemplate.Columns, sqlgraph.NewFieldSpec(contactfieldtemplate.FieldID, field.TypeUint64))
+	id, ok := cftuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ContactFieldTemplate.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := cftuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, contactfieldtemplate.FieldID)
+		for _, f := range fields {
+			if !contactfieldtemplate.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != contactfieldtemplate.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := cftuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cftuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cftuo.mutation.Status(); ok {
+		_spec.SetField(contactfieldtemplate.FieldStatus, field.TypeUint8, value)
+	}
+	if value, ok := cftuo.mutation.AddedStatus(); ok {
+		_spec.AddField(contactfieldtemplate.FieldStatus, field.TypeUint8, value)
+	}
+	if cftuo.mutation.StatusCleared() {
+		_spec.ClearField(contactfieldtemplate.FieldStatus, field.TypeUint8)
+	}
+	if value, ok := cftuo.mutation.DeletedAt(); ok {
+		_spec.SetField(contactfieldtemplate.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cftuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(contactfieldtemplate.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cftuo.mutation.OrganizationID(); ok {
+		_spec.SetField(contactfieldtemplate.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := cftuo.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(contactfieldtemplate.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := cftuo.mutation.Template(); ok {
+		_spec.SetField(contactfieldtemplate.FieldTemplate, field.TypeJSON, value)
+	}
+	if value, ok := cftuo.mutation.AppendedTemplate(); ok {
+		_spec.AddModifier(func(u *sql.UpdateBuilder) {
+			sqljson.Append(u, contactfieldtemplate.FieldTemplate, value)
+		})
+	}
+	_node = &ContactFieldTemplate{config: cftuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, cftuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{contactfieldtemplate.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	cftuo.mutation.done = true
+	return _node, nil
+}

+ 13 - 0
ent/custom_types/types.go

@@ -29,3 +29,16 @@ type OriginalData struct {
 	Request  interface{} `json:"request"`
 	Response interface{} `json:"response"`
 }
+
+type ContactFieldTemplate struct {
+	Type    *string                       `json:"type,omitempty"`
+	Id      *string                       `json:"id,omitempty"`
+	Label   *string                       `json:"label,omitempty"`
+	Options []ContactFieldTemplateOptions `json:"options,omitempty"`
+	Value   []string                      `json:"value,omitempty"`
+}
+
+type ContactFieldTemplateOptions struct {
+	Label *string `json:"type,omitempty"`
+	Value *string `json:"value,omitempty"`
+}

+ 45 - 41
ent/ent.go

@@ -18,6 +18,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/employee"
@@ -113,47 +115,49 @@ var (
 func checkColumn(table, column string) error {
 	initCheck.Do(func() {
 		columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
-			agent.Table:               agent.ValidColumn,
-			agentbase.Table:           agentbase.ValidColumn,
-			aliyunavatar.Table:        aliyunavatar.ValidColumn,
-			allocagent.Table:          allocagent.ValidColumn,
-			apikey.Table:              apikey.ValidColumn,
-			batchmsg.Table:            batchmsg.ValidColumn,
-			category.Table:            category.ValidColumn,
-			chatrecords.Table:         chatrecords.ValidColumn,
-			chatsession.Table:         chatsession.ValidColumn,
-			contact.Table:             contact.ValidColumn,
-			creditbalance.Table:       creditbalance.ValidColumn,
-			creditusage.Table:         creditusage.ValidColumn,
-			employee.Table:            employee.ValidColumn,
-			employeeconfig.Table:      employeeconfig.ValidColumn,
-			label.Table:               label.ValidColumn,
-			labelrelationship.Table:   labelrelationship.ValidColumn,
-			labeltagging.Table:        labeltagging.ValidColumn,
-			message.Table:             message.ValidColumn,
-			messagerecords.Table:      messagerecords.ValidColumn,
-			msg.Table:                 msg.ValidColumn,
-			payrecharge.Table:         payrecharge.ValidColumn,
-			server.Table:              server.ValidColumn,
-			sopnode.Table:             sopnode.ValidColumn,
-			sopstage.Table:            sopstage.ValidColumn,
-			soptask.Table:             soptask.ValidColumn,
-			token.Table:               token.ValidColumn,
-			tutorial.Table:            tutorial.ValidColumn,
-			usagedetail.Table:         usagedetail.ValidColumn,
-			usagestatisticday.Table:   usagestatisticday.ValidColumn,
-			usagestatistichour.Table:  usagestatistichour.ValidColumn,
-			usagestatisticmonth.Table: usagestatisticmonth.ValidColumn,
-			usagetotal.Table:          usagetotal.ValidColumn,
-			whatsapp.Table:            whatsapp.ValidColumn,
-			whatsappchannel.Table:     whatsappchannel.ValidColumn,
-			workexperience.Table:      workexperience.ValidColumn,
-			wpchatroom.Table:          wpchatroom.ValidColumn,
-			wpchatroommember.Table:    wpchatroommember.ValidColumn,
-			wx.Table:                  wx.ValidColumn,
-			wxcard.Table:              wxcard.ValidColumn,
-			wxcarduser.Table:          wxcarduser.ValidColumn,
-			wxcardvisit.Table:         wxcardvisit.ValidColumn,
+			agent.Table:                agent.ValidColumn,
+			agentbase.Table:            agentbase.ValidColumn,
+			aliyunavatar.Table:         aliyunavatar.ValidColumn,
+			allocagent.Table:           allocagent.ValidColumn,
+			apikey.Table:               apikey.ValidColumn,
+			batchmsg.Table:             batchmsg.ValidColumn,
+			category.Table:             category.ValidColumn,
+			chatrecords.Table:          chatrecords.ValidColumn,
+			chatsession.Table:          chatsession.ValidColumn,
+			contact.Table:              contact.ValidColumn,
+			contactfield.Table:         contactfield.ValidColumn,
+			contactfieldtemplate.Table: contactfieldtemplate.ValidColumn,
+			creditbalance.Table:        creditbalance.ValidColumn,
+			creditusage.Table:          creditusage.ValidColumn,
+			employee.Table:             employee.ValidColumn,
+			employeeconfig.Table:       employeeconfig.ValidColumn,
+			label.Table:                label.ValidColumn,
+			labelrelationship.Table:    labelrelationship.ValidColumn,
+			labeltagging.Table:         labeltagging.ValidColumn,
+			message.Table:              message.ValidColumn,
+			messagerecords.Table:       messagerecords.ValidColumn,
+			msg.Table:                  msg.ValidColumn,
+			payrecharge.Table:          payrecharge.ValidColumn,
+			server.Table:               server.ValidColumn,
+			sopnode.Table:              sopnode.ValidColumn,
+			sopstage.Table:             sopstage.ValidColumn,
+			soptask.Table:              soptask.ValidColumn,
+			token.Table:                token.ValidColumn,
+			tutorial.Table:             tutorial.ValidColumn,
+			usagedetail.Table:          usagedetail.ValidColumn,
+			usagestatisticday.Table:    usagestatisticday.ValidColumn,
+			usagestatistichour.Table:   usagestatistichour.ValidColumn,
+			usagestatisticmonth.Table:  usagestatisticmonth.ValidColumn,
+			usagetotal.Table:           usagetotal.ValidColumn,
+			whatsapp.Table:             whatsapp.ValidColumn,
+			whatsappchannel.Table:      whatsappchannel.ValidColumn,
+			workexperience.Table:       workexperience.ValidColumn,
+			wpchatroom.Table:           wpchatroom.ValidColumn,
+			wpchatroommember.Table:     wpchatroommember.ValidColumn,
+			wx.Table:                   wx.ValidColumn,
+			wxcard.Table:               wxcard.ValidColumn,
+			wxcarduser.Table:           wxcarduser.ValidColumn,
+			wxcardvisit.Table:          wxcardvisit.ValidColumn,
 		})
 	})
 	return columnCheck(table, column)

+ 24 - 0
ent/hook/hook.go

@@ -128,6 +128,30 @@ func (f ContactFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, err
 	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ContactMutation", m)
 }
 
+// The ContactFieldFunc type is an adapter to allow the use of ordinary
+// function as ContactField mutator.
+type ContactFieldFunc func(context.Context, *ent.ContactFieldMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f ContactFieldFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.ContactFieldMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ContactFieldMutation", m)
+}
+
+// The ContactFieldTemplateFunc type is an adapter to allow the use of ordinary
+// function as ContactFieldTemplate mutator.
+type ContactFieldTemplateFunc func(context.Context, *ent.ContactFieldTemplateMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f ContactFieldTemplateFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.ContactFieldTemplateMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ContactFieldTemplateMutation", m)
+}
+
 // The CreditBalanceFunc type is an adapter to allow the use of ordinary
 // function as CreditBalance mutator.
 type CreditBalanceFunc func(context.Context, *ent.CreditBalanceMutation) (ent.Value, error)

+ 60 - 0
ent/intercept/intercept.go

@@ -16,6 +16,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/employee"
@@ -378,6 +380,60 @@ func (f TraverseContact) Traverse(ctx context.Context, q ent.Query) error {
 	return fmt.Errorf("unexpected query type %T. expect *ent.ContactQuery", q)
 }
 
+// The ContactFieldFunc type is an adapter to allow the use of ordinary function as a Querier.
+type ContactFieldFunc func(context.Context, *ent.ContactFieldQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f ContactFieldFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.ContactFieldQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.ContactFieldQuery", q)
+}
+
+// The TraverseContactField type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseContactField func(context.Context, *ent.ContactFieldQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseContactField) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseContactField) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.ContactFieldQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.ContactFieldQuery", q)
+}
+
+// The ContactFieldTemplateFunc type is an adapter to allow the use of ordinary function as a Querier.
+type ContactFieldTemplateFunc func(context.Context, *ent.ContactFieldTemplateQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f ContactFieldTemplateFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.ContactFieldTemplateQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.ContactFieldTemplateQuery", q)
+}
+
+// The TraverseContactFieldTemplate type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseContactFieldTemplate func(context.Context, *ent.ContactFieldTemplateQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseContactFieldTemplate) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseContactFieldTemplate) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.ContactFieldTemplateQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.ContactFieldTemplateQuery", q)
+}
+
 // The CreditBalanceFunc type is an adapter to allow the use of ordinary function as a Querier.
 type CreditBalanceFunc func(context.Context, *ent.CreditBalanceQuery) (ent.Value, error)
 
@@ -1238,6 +1294,10 @@ func NewQuery(q ent.Query) (Query, error) {
 		return &query[*ent.ChatSessionQuery, predicate.ChatSession, chatsession.OrderOption]{typ: ent.TypeChatSession, tq: q}, nil
 	case *ent.ContactQuery:
 		return &query[*ent.ContactQuery, predicate.Contact, contact.OrderOption]{typ: ent.TypeContact, tq: q}, nil
+	case *ent.ContactFieldQuery:
+		return &query[*ent.ContactFieldQuery, predicate.ContactField, contactfield.OrderOption]{typ: ent.TypeContactField, tq: q}, nil
+	case *ent.ContactFieldTemplateQuery:
+		return &query[*ent.ContactFieldTemplateQuery, predicate.ContactFieldTemplate, contactfieldtemplate.OrderOption]{typ: ent.TypeContactFieldTemplate, tq: q}, nil
 	case *ent.CreditBalanceQuery:
 		return &query[*ent.CreditBalanceQuery, predicate.CreditBalance, creditbalance.OrderOption]{typ: ent.TypeCreditBalance, tq: q}, nil
 	case *ent.CreditUsageQuery:

+ 50 - 0
ent/migrate/schema.go

@@ -335,6 +335,47 @@ var (
 			},
 		},
 	}
+	// ContactFieldColumns holds the columns for the "contact_field" table.
+	ContactFieldColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "form_id", Type: field.TypeString, Comment: "表单 id"},
+		{Name: "value", Type: field.TypeJSON, Comment: "表单值"},
+		{Name: "contact_id", Type: field.TypeUint64, Comment: "联系人 ID", Default: 1},
+	}
+	// ContactFieldTable holds the schema information for the "contact_field" table.
+	ContactFieldTable = &schema.Table{
+		Name:       "contact_field",
+		Columns:    ContactFieldColumns,
+		PrimaryKey: []*schema.Column{ContactFieldColumns[0]},
+		ForeignKeys: []*schema.ForeignKey{
+			{
+				Symbol:     "contact_field_contact_contact_fields",
+				Columns:    []*schema.Column{ContactFieldColumns[7]},
+				RefColumns: []*schema.Column{ContactColumns[0]},
+				OnDelete:   schema.NoAction,
+			},
+		},
+	}
+	// ContactFieldTemplateColumns holds the columns for the "contact_field_template" table.
+	ContactFieldTemplateColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "organization_id", Type: field.TypeUint64, Comment: "机构 ID", Default: 1},
+		{Name: "template", Type: field.TypeJSON, Comment: "模板"},
+	}
+	// ContactFieldTemplateTable holds the schema information for the "contact_field_template" table.
+	ContactFieldTemplateTable = &schema.Table{
+		Name:       "contact_field_template",
+		Columns:    ContactFieldTemplateColumns,
+		PrimaryKey: []*schema.Column{ContactFieldTemplateColumns[0]},
+	}
 	// CreditBalanceColumns holds the columns for the "credit_balance" table.
 	CreditBalanceColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -1424,6 +1465,8 @@ var (
 		ChatRecordsTable,
 		ChatSessionTable,
 		ContactTable,
+		ContactFieldTable,
+		ContactFieldTemplateTable,
 		CreditBalanceTable,
 		CreditUsageTable,
 		EmployeeTable,
@@ -1490,6 +1533,13 @@ func init() {
 	ContactTable.Annotation = &entsql.Annotation{
 		Table: "contact",
 	}
+	ContactFieldTable.ForeignKeys[0].RefTable = ContactTable
+	ContactFieldTable.Annotation = &entsql.Annotation{
+		Table: "contact_field",
+	}
+	ContactFieldTemplateTable.Annotation = &entsql.Annotation{
+		Table: "contact_field_template",
+	}
 	CreditBalanceTable.Annotation = &entsql.Annotation{
 		Table: "credit_balance",
 	}

+ 1677 - 44
ent/mutation.go

@@ -18,6 +18,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/custom_types"
@@ -65,47 +67,49 @@ const (
 	OpUpdateOne = ent.OpUpdateOne
 
 	// Node types.
-	TypeAgent               = "Agent"
-	TypeAgentBase           = "AgentBase"
-	TypeAliyunAvatar        = "AliyunAvatar"
-	TypeAllocAgent          = "AllocAgent"
-	TypeApiKey              = "ApiKey"
-	TypeBatchMsg            = "BatchMsg"
-	TypeCategory            = "Category"
-	TypeChatRecords         = "ChatRecords"
-	TypeChatSession         = "ChatSession"
-	TypeContact             = "Contact"
-	TypeCreditBalance       = "CreditBalance"
-	TypeCreditUsage         = "CreditUsage"
-	TypeEmployee            = "Employee"
-	TypeEmployeeConfig      = "EmployeeConfig"
-	TypeLabel               = "Label"
-	TypeLabelRelationship   = "LabelRelationship"
-	TypeLabelTagging        = "LabelTagging"
-	TypeMessage             = "Message"
-	TypeMessageRecords      = "MessageRecords"
-	TypeMsg                 = "Msg"
-	TypePayRecharge         = "PayRecharge"
-	TypeServer              = "Server"
-	TypeSopNode             = "SopNode"
-	TypeSopStage            = "SopStage"
-	TypeSopTask             = "SopTask"
-	TypeToken               = "Token"
-	TypeTutorial            = "Tutorial"
-	TypeUsageDetail         = "UsageDetail"
-	TypeUsageStatisticDay   = "UsageStatisticDay"
-	TypeUsageStatisticHour  = "UsageStatisticHour"
-	TypeUsageStatisticMonth = "UsageStatisticMonth"
-	TypeUsageTotal          = "UsageTotal"
-	TypeWhatsapp            = "Whatsapp"
-	TypeWhatsappChannel     = "WhatsappChannel"
-	TypeWorkExperience      = "WorkExperience"
-	TypeWpChatroom          = "WpChatroom"
-	TypeWpChatroomMember    = "WpChatroomMember"
-	TypeWx                  = "Wx"
-	TypeWxCard              = "WxCard"
-	TypeWxCardUser          = "WxCardUser"
-	TypeWxCardVisit         = "WxCardVisit"
+	TypeAgent                = "Agent"
+	TypeAgentBase            = "AgentBase"
+	TypeAliyunAvatar         = "AliyunAvatar"
+	TypeAllocAgent           = "AllocAgent"
+	TypeApiKey               = "ApiKey"
+	TypeBatchMsg             = "BatchMsg"
+	TypeCategory             = "Category"
+	TypeChatRecords          = "ChatRecords"
+	TypeChatSession          = "ChatSession"
+	TypeContact              = "Contact"
+	TypeContactField         = "ContactField"
+	TypeContactFieldTemplate = "ContactFieldTemplate"
+	TypeCreditBalance        = "CreditBalance"
+	TypeCreditUsage          = "CreditUsage"
+	TypeEmployee             = "Employee"
+	TypeEmployeeConfig       = "EmployeeConfig"
+	TypeLabel                = "Label"
+	TypeLabelRelationship    = "LabelRelationship"
+	TypeLabelTagging         = "LabelTagging"
+	TypeMessage              = "Message"
+	TypeMessageRecords       = "MessageRecords"
+	TypeMsg                  = "Msg"
+	TypePayRecharge          = "PayRecharge"
+	TypeServer               = "Server"
+	TypeSopNode              = "SopNode"
+	TypeSopStage             = "SopStage"
+	TypeSopTask              = "SopTask"
+	TypeToken                = "Token"
+	TypeTutorial             = "Tutorial"
+	TypeUsageDetail          = "UsageDetail"
+	TypeUsageStatisticDay    = "UsageStatisticDay"
+	TypeUsageStatisticHour   = "UsageStatisticHour"
+	TypeUsageStatisticMonth  = "UsageStatisticMonth"
+	TypeUsageTotal           = "UsageTotal"
+	TypeWhatsapp             = "Whatsapp"
+	TypeWhatsappChannel      = "WhatsappChannel"
+	TypeWorkExperience       = "WorkExperience"
+	TypeWpChatroom           = "WpChatroom"
+	TypeWpChatroomMember     = "WpChatroomMember"
+	TypeWx                   = "Wx"
+	TypeWxCard               = "WxCard"
+	TypeWxCardUser           = "WxCardUser"
+	TypeWxCardVisit          = "WxCardVisit"
 )
 
 // AgentMutation represents an operation that mutates the Agent nodes in the graph.
@@ -10110,6 +10114,9 @@ type ContactMutation struct {
 	contact_relationships        map[uint64]struct{}
 	removedcontact_relationships map[uint64]struct{}
 	clearedcontact_relationships bool
+	contact_fields               map[uint64]struct{}
+	removedcontact_fields        map[uint64]struct{}
+	clearedcontact_fields        bool
 	contact_messages             map[uint64]struct{}
 	removedcontact_messages      map[uint64]struct{}
 	clearedcontact_messages      bool
@@ -11571,6 +11578,60 @@ func (m *ContactMutation) ResetContactRelationships() {
 	m.removedcontact_relationships = nil
 }
 
+// AddContactFieldIDs adds the "contact_fields" edge to the ContactField entity by ids.
+func (m *ContactMutation) AddContactFieldIDs(ids ...uint64) {
+	if m.contact_fields == nil {
+		m.contact_fields = make(map[uint64]struct{})
+	}
+	for i := range ids {
+		m.contact_fields[ids[i]] = struct{}{}
+	}
+}
+
+// ClearContactFields clears the "contact_fields" edge to the ContactField entity.
+func (m *ContactMutation) ClearContactFields() {
+	m.clearedcontact_fields = true
+}
+
+// ContactFieldsCleared reports if the "contact_fields" edge to the ContactField entity was cleared.
+func (m *ContactMutation) ContactFieldsCleared() bool {
+	return m.clearedcontact_fields
+}
+
+// RemoveContactFieldIDs removes the "contact_fields" edge to the ContactField entity by IDs.
+func (m *ContactMutation) RemoveContactFieldIDs(ids ...uint64) {
+	if m.removedcontact_fields == nil {
+		m.removedcontact_fields = make(map[uint64]struct{})
+	}
+	for i := range ids {
+		delete(m.contact_fields, ids[i])
+		m.removedcontact_fields[ids[i]] = struct{}{}
+	}
+}
+
+// RemovedContactFields returns the removed IDs of the "contact_fields" edge to the ContactField entity.
+func (m *ContactMutation) RemovedContactFieldsIDs() (ids []uint64) {
+	for id := range m.removedcontact_fields {
+		ids = append(ids, id)
+	}
+	return
+}
+
+// ContactFieldsIDs returns the "contact_fields" edge IDs in the mutation.
+func (m *ContactMutation) ContactFieldsIDs() (ids []uint64) {
+	for id := range m.contact_fields {
+		ids = append(ids, id)
+	}
+	return
+}
+
+// ResetContactFields resets all changes to the "contact_fields" edge.
+func (m *ContactMutation) ResetContactFields() {
+	m.contact_fields = nil
+	m.clearedcontact_fields = false
+	m.removedcontact_fields = nil
+}
+
 // AddContactMessageIDs adds the "contact_messages" edge to the MessageRecords entity by ids.
 func (m *ContactMutation) AddContactMessageIDs(ids ...uint64) {
 	if m.contact_messages == nil {
@@ -12377,10 +12438,13 @@ func (m *ContactMutation) ResetField(name string) error {
 
 // AddedEdges returns all edge names that were set/added in this mutation.
 func (m *ContactMutation) AddedEdges() []string {
-	edges := make([]string, 0, 2)
+	edges := make([]string, 0, 3)
 	if m.contact_relationships != nil {
 		edges = append(edges, contact.EdgeContactRelationships)
 	}
+	if m.contact_fields != nil {
+		edges = append(edges, contact.EdgeContactFields)
+	}
 	if m.contact_messages != nil {
 		edges = append(edges, contact.EdgeContactMessages)
 	}
@@ -12397,6 +12461,12 @@ func (m *ContactMutation) AddedIDs(name string) []ent.Value {
 			ids = append(ids, id)
 		}
 		return ids
+	case contact.EdgeContactFields:
+		ids := make([]ent.Value, 0, len(m.contact_fields))
+		for id := range m.contact_fields {
+			ids = append(ids, id)
+		}
+		return ids
 	case contact.EdgeContactMessages:
 		ids := make([]ent.Value, 0, len(m.contact_messages))
 		for id := range m.contact_messages {
@@ -12409,10 +12479,13 @@ func (m *ContactMutation) AddedIDs(name string) []ent.Value {
 
 // RemovedEdges returns all edge names that were removed in this mutation.
 func (m *ContactMutation) RemovedEdges() []string {
-	edges := make([]string, 0, 2)
+	edges := make([]string, 0, 3)
 	if m.removedcontact_relationships != nil {
 		edges = append(edges, contact.EdgeContactRelationships)
 	}
+	if m.removedcontact_fields != nil {
+		edges = append(edges, contact.EdgeContactFields)
+	}
 	if m.removedcontact_messages != nil {
 		edges = append(edges, contact.EdgeContactMessages)
 	}
@@ -12429,6 +12502,12 @@ func (m *ContactMutation) RemovedIDs(name string) []ent.Value {
 			ids = append(ids, id)
 		}
 		return ids
+	case contact.EdgeContactFields:
+		ids := make([]ent.Value, 0, len(m.removedcontact_fields))
+		for id := range m.removedcontact_fields {
+			ids = append(ids, id)
+		}
+		return ids
 	case contact.EdgeContactMessages:
 		ids := make([]ent.Value, 0, len(m.removedcontact_messages))
 		for id := range m.removedcontact_messages {
@@ -12441,10 +12520,13 @@ func (m *ContactMutation) RemovedIDs(name string) []ent.Value {
 
 // ClearedEdges returns all edge names that were cleared in this mutation.
 func (m *ContactMutation) ClearedEdges() []string {
-	edges := make([]string, 0, 2)
+	edges := make([]string, 0, 3)
 	if m.clearedcontact_relationships {
 		edges = append(edges, contact.EdgeContactRelationships)
 	}
+	if m.clearedcontact_fields {
+		edges = append(edges, contact.EdgeContactFields)
+	}
 	if m.clearedcontact_messages {
 		edges = append(edges, contact.EdgeContactMessages)
 	}
@@ -12457,6 +12539,8 @@ func (m *ContactMutation) EdgeCleared(name string) bool {
 	switch name {
 	case contact.EdgeContactRelationships:
 		return m.clearedcontact_relationships
+	case contact.EdgeContactFields:
+		return m.clearedcontact_fields
 	case contact.EdgeContactMessages:
 		return m.clearedcontact_messages
 	}
@@ -12478,6 +12562,9 @@ func (m *ContactMutation) ResetEdge(name string) error {
 	case contact.EdgeContactRelationships:
 		m.ResetContactRelationships()
 		return nil
+	case contact.EdgeContactFields:
+		m.ResetContactFields()
+		return nil
 	case contact.EdgeContactMessages:
 		m.ResetContactMessages()
 		return nil
@@ -12485,6 +12572,1552 @@ func (m *ContactMutation) ResetEdge(name string) error {
 	return fmt.Errorf("unknown Contact edge %s", name)
 }
 
+// ContactFieldMutation represents an operation that mutates the ContactField nodes in the graph.
+type ContactFieldMutation struct {
+	config
+	op                   Op
+	typ                  string
+	id                   *uint64
+	created_at           *time.Time
+	updated_at           *time.Time
+	status               *uint8
+	addstatus            *int8
+	deleted_at           *time.Time
+	form_id              *string
+	value                *[]string
+	appendvalue          []string
+	clearedFields        map[string]struct{}
+	field_contact        *uint64
+	clearedfield_contact bool
+	done                 bool
+	oldValue             func(context.Context) (*ContactField, error)
+	predicates           []predicate.ContactField
+}
+
+var _ ent.Mutation = (*ContactFieldMutation)(nil)
+
+// contactfieldOption allows management of the mutation configuration using functional options.
+type contactfieldOption func(*ContactFieldMutation)
+
+// newContactFieldMutation creates new mutation for the ContactField entity.
+func newContactFieldMutation(c config, op Op, opts ...contactfieldOption) *ContactFieldMutation {
+	m := &ContactFieldMutation{
+		config:        c,
+		op:            op,
+		typ:           TypeContactField,
+		clearedFields: make(map[string]struct{}),
+	}
+	for _, opt := range opts {
+		opt(m)
+	}
+	return m
+}
+
+// withContactFieldID sets the ID field of the mutation.
+func withContactFieldID(id uint64) contactfieldOption {
+	return func(m *ContactFieldMutation) {
+		var (
+			err   error
+			once  sync.Once
+			value *ContactField
+		)
+		m.oldValue = func(ctx context.Context) (*ContactField, error) {
+			once.Do(func() {
+				if m.done {
+					err = errors.New("querying old values post mutation is not allowed")
+				} else {
+					value, err = m.Client().ContactField.Get(ctx, id)
+				}
+			})
+			return value, err
+		}
+		m.id = &id
+	}
+}
+
+// withContactField sets the old ContactField of the mutation.
+func withContactField(node *ContactField) contactfieldOption {
+	return func(m *ContactFieldMutation) {
+		m.oldValue = func(context.Context) (*ContactField, error) {
+			return node, nil
+		}
+		m.id = &node.ID
+	}
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m ContactFieldMutation) Client() *Client {
+	client := &Client{config: m.config}
+	client.init()
+	return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m ContactFieldMutation) Tx() (*Tx, error) {
+	if _, ok := m.driver.(*txDriver); !ok {
+		return nil, errors.New("ent: mutation is not running in a transaction")
+	}
+	tx := &Tx{config: m.config}
+	tx.init()
+	return tx, nil
+}
+
+// SetID sets the value of the id field. Note that this
+// operation is only accepted on creation of ContactField entities.
+func (m *ContactFieldMutation) SetID(id uint64) {
+	m.id = &id
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *ContactFieldMutation) ID() (id uint64, exists bool) {
+	if m.id == nil {
+		return
+	}
+	return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *ContactFieldMutation) IDs(ctx context.Context) ([]uint64, error) {
+	switch {
+	case m.op.Is(OpUpdateOne | OpDeleteOne):
+		id, exists := m.ID()
+		if exists {
+			return []uint64{id}, nil
+		}
+		fallthrough
+	case m.op.Is(OpUpdate | OpDelete):
+		return m.Client().ContactField.Query().Where(m.predicates...).IDs(ctx)
+	default:
+		return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+	}
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (m *ContactFieldMutation) SetCreatedAt(t time.Time) {
+	m.created_at = &t
+}
+
+// CreatedAt returns the value of the "created_at" field in the mutation.
+func (m *ContactFieldMutation) CreatedAt() (r time.Time, exists bool) {
+	v := m.created_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldCreatedAt returns the old "created_at" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldCreatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
+	}
+	return oldValue.CreatedAt, nil
+}
+
+// ResetCreatedAt resets all changes to the "created_at" field.
+func (m *ContactFieldMutation) ResetCreatedAt() {
+	m.created_at = nil
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (m *ContactFieldMutation) SetUpdatedAt(t time.Time) {
+	m.updated_at = &t
+}
+
+// UpdatedAt returns the value of the "updated_at" field in the mutation.
+func (m *ContactFieldMutation) UpdatedAt() (r time.Time, exists bool) {
+	v := m.updated_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldUpdatedAt returns the old "updated_at" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
+	}
+	return oldValue.UpdatedAt, nil
+}
+
+// ResetUpdatedAt resets all changes to the "updated_at" field.
+func (m *ContactFieldMutation) ResetUpdatedAt() {
+	m.updated_at = nil
+}
+
+// SetStatus sets the "status" field.
+func (m *ContactFieldMutation) SetStatus(u uint8) {
+	m.status = &u
+	m.addstatus = nil
+}
+
+// Status returns the value of the "status" field in the mutation.
+func (m *ContactFieldMutation) Status() (r uint8, exists bool) {
+	v := m.status
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldStatus returns the old "status" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldStatus(ctx context.Context) (v uint8, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldStatus is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldStatus requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldStatus: %w", err)
+	}
+	return oldValue.Status, nil
+}
+
+// AddStatus adds u to the "status" field.
+func (m *ContactFieldMutation) AddStatus(u int8) {
+	if m.addstatus != nil {
+		*m.addstatus += u
+	} else {
+		m.addstatus = &u
+	}
+}
+
+// AddedStatus returns the value that was added to the "status" field in this mutation.
+func (m *ContactFieldMutation) AddedStatus() (r int8, exists bool) {
+	v := m.addstatus
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ClearStatus clears the value of the "status" field.
+func (m *ContactFieldMutation) ClearStatus() {
+	m.status = nil
+	m.addstatus = nil
+	m.clearedFields[contactfield.FieldStatus] = struct{}{}
+}
+
+// StatusCleared returns if the "status" field was cleared in this mutation.
+func (m *ContactFieldMutation) StatusCleared() bool {
+	_, ok := m.clearedFields[contactfield.FieldStatus]
+	return ok
+}
+
+// ResetStatus resets all changes to the "status" field.
+func (m *ContactFieldMutation) ResetStatus() {
+	m.status = nil
+	m.addstatus = nil
+	delete(m.clearedFields, contactfield.FieldStatus)
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (m *ContactFieldMutation) SetDeletedAt(t time.Time) {
+	m.deleted_at = &t
+}
+
+// DeletedAt returns the value of the "deleted_at" field in the mutation.
+func (m *ContactFieldMutation) DeletedAt() (r time.Time, exists bool) {
+	v := m.deleted_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldDeletedAt returns the old "deleted_at" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldDeletedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err)
+	}
+	return oldValue.DeletedAt, nil
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (m *ContactFieldMutation) ClearDeletedAt() {
+	m.deleted_at = nil
+	m.clearedFields[contactfield.FieldDeletedAt] = struct{}{}
+}
+
+// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation.
+func (m *ContactFieldMutation) DeletedAtCleared() bool {
+	_, ok := m.clearedFields[contactfield.FieldDeletedAt]
+	return ok
+}
+
+// ResetDeletedAt resets all changes to the "deleted_at" field.
+func (m *ContactFieldMutation) ResetDeletedAt() {
+	m.deleted_at = nil
+	delete(m.clearedFields, contactfield.FieldDeletedAt)
+}
+
+// SetContactID sets the "contact_id" field.
+func (m *ContactFieldMutation) SetContactID(u uint64) {
+	m.field_contact = &u
+}
+
+// ContactID returns the value of the "contact_id" field in the mutation.
+func (m *ContactFieldMutation) ContactID() (r uint64, exists bool) {
+	v := m.field_contact
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldContactID returns the old "contact_id" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldContactID(ctx context.Context) (v uint64, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldContactID is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldContactID requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldContactID: %w", err)
+	}
+	return oldValue.ContactID, nil
+}
+
+// ResetContactID resets all changes to the "contact_id" field.
+func (m *ContactFieldMutation) ResetContactID() {
+	m.field_contact = nil
+}
+
+// SetFormID sets the "form_id" field.
+func (m *ContactFieldMutation) SetFormID(s string) {
+	m.form_id = &s
+}
+
+// FormID returns the value of the "form_id" field in the mutation.
+func (m *ContactFieldMutation) FormID() (r string, exists bool) {
+	v := m.form_id
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldFormID returns the old "form_id" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldFormID(ctx context.Context) (v string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldFormID is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldFormID requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldFormID: %w", err)
+	}
+	return oldValue.FormID, nil
+}
+
+// ResetFormID resets all changes to the "form_id" field.
+func (m *ContactFieldMutation) ResetFormID() {
+	m.form_id = nil
+}
+
+// SetValue sets the "value" field.
+func (m *ContactFieldMutation) SetValue(s []string) {
+	m.value = &s
+	m.appendvalue = nil
+}
+
+// Value returns the value of the "value" field in the mutation.
+func (m *ContactFieldMutation) Value() (r []string, exists bool) {
+	v := m.value
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldValue returns the old "value" field's value of the ContactField entity.
+// If the ContactField object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldMutation) OldValue(ctx context.Context) (v []string, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldValue is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldValue requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldValue: %w", err)
+	}
+	return oldValue.Value, nil
+}
+
+// AppendValue adds s to the "value" field.
+func (m *ContactFieldMutation) AppendValue(s []string) {
+	m.appendvalue = append(m.appendvalue, s...)
+}
+
+// AppendedValue returns the list of values that were appended to the "value" field in this mutation.
+func (m *ContactFieldMutation) AppendedValue() ([]string, bool) {
+	if len(m.appendvalue) == 0 {
+		return nil, false
+	}
+	return m.appendvalue, true
+}
+
+// ResetValue resets all changes to the "value" field.
+func (m *ContactFieldMutation) ResetValue() {
+	m.value = nil
+	m.appendvalue = nil
+}
+
+// SetFieldContactID sets the "field_contact" edge to the Contact entity by id.
+func (m *ContactFieldMutation) SetFieldContactID(id uint64) {
+	m.field_contact = &id
+}
+
+// ClearFieldContact clears the "field_contact" edge to the Contact entity.
+func (m *ContactFieldMutation) ClearFieldContact() {
+	m.clearedfield_contact = true
+	m.clearedFields[contactfield.FieldContactID] = struct{}{}
+}
+
+// FieldContactCleared reports if the "field_contact" edge to the Contact entity was cleared.
+func (m *ContactFieldMutation) FieldContactCleared() bool {
+	return m.clearedfield_contact
+}
+
+// FieldContactID returns the "field_contact" edge ID in the mutation.
+func (m *ContactFieldMutation) FieldContactID() (id uint64, exists bool) {
+	if m.field_contact != nil {
+		return *m.field_contact, true
+	}
+	return
+}
+
+// FieldContactIDs returns the "field_contact" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// FieldContactID instead. It exists only for internal usage by the builders.
+func (m *ContactFieldMutation) FieldContactIDs() (ids []uint64) {
+	if id := m.field_contact; id != nil {
+		ids = append(ids, *id)
+	}
+	return
+}
+
+// ResetFieldContact resets all changes to the "field_contact" edge.
+func (m *ContactFieldMutation) ResetFieldContact() {
+	m.field_contact = nil
+	m.clearedfield_contact = false
+}
+
+// Where appends a list predicates to the ContactFieldMutation builder.
+func (m *ContactFieldMutation) Where(ps ...predicate.ContactField) {
+	m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the ContactFieldMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *ContactFieldMutation) WhereP(ps ...func(*sql.Selector)) {
+	p := make([]predicate.ContactField, len(ps))
+	for i := range ps {
+		p[i] = ps[i]
+	}
+	m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *ContactFieldMutation) Op() Op {
+	return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *ContactFieldMutation) SetOp(op Op) {
+	m.op = op
+}
+
+// Type returns the node type of this mutation (ContactField).
+func (m *ContactFieldMutation) Type() string {
+	return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *ContactFieldMutation) Fields() []string {
+	fields := make([]string, 0, 7)
+	if m.created_at != nil {
+		fields = append(fields, contactfield.FieldCreatedAt)
+	}
+	if m.updated_at != nil {
+		fields = append(fields, contactfield.FieldUpdatedAt)
+	}
+	if m.status != nil {
+		fields = append(fields, contactfield.FieldStatus)
+	}
+	if m.deleted_at != nil {
+		fields = append(fields, contactfield.FieldDeletedAt)
+	}
+	if m.field_contact != nil {
+		fields = append(fields, contactfield.FieldContactID)
+	}
+	if m.form_id != nil {
+		fields = append(fields, contactfield.FieldFormID)
+	}
+	if m.value != nil {
+		fields = append(fields, contactfield.FieldValue)
+	}
+	return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *ContactFieldMutation) Field(name string) (ent.Value, bool) {
+	switch name {
+	case contactfield.FieldCreatedAt:
+		return m.CreatedAt()
+	case contactfield.FieldUpdatedAt:
+		return m.UpdatedAt()
+	case contactfield.FieldStatus:
+		return m.Status()
+	case contactfield.FieldDeletedAt:
+		return m.DeletedAt()
+	case contactfield.FieldContactID:
+		return m.ContactID()
+	case contactfield.FieldFormID:
+		return m.FormID()
+	case contactfield.FieldValue:
+		return m.Value()
+	}
+	return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *ContactFieldMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+	switch name {
+	case contactfield.FieldCreatedAt:
+		return m.OldCreatedAt(ctx)
+	case contactfield.FieldUpdatedAt:
+		return m.OldUpdatedAt(ctx)
+	case contactfield.FieldStatus:
+		return m.OldStatus(ctx)
+	case contactfield.FieldDeletedAt:
+		return m.OldDeletedAt(ctx)
+	case contactfield.FieldContactID:
+		return m.OldContactID(ctx)
+	case contactfield.FieldFormID:
+		return m.OldFormID(ctx)
+	case contactfield.FieldValue:
+		return m.OldValue(ctx)
+	}
+	return nil, fmt.Errorf("unknown ContactField field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *ContactFieldMutation) SetField(name string, value ent.Value) error {
+	switch name {
+	case contactfield.FieldCreatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetCreatedAt(v)
+		return nil
+	case contactfield.FieldUpdatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetUpdatedAt(v)
+		return nil
+	case contactfield.FieldStatus:
+		v, ok := value.(uint8)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetStatus(v)
+		return nil
+	case contactfield.FieldDeletedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetDeletedAt(v)
+		return nil
+	case contactfield.FieldContactID:
+		v, ok := value.(uint64)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetContactID(v)
+		return nil
+	case contactfield.FieldFormID:
+		v, ok := value.(string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetFormID(v)
+		return nil
+	case contactfield.FieldValue:
+		v, ok := value.([]string)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetValue(v)
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *ContactFieldMutation) AddedFields() []string {
+	var fields []string
+	if m.addstatus != nil {
+		fields = append(fields, contactfield.FieldStatus)
+	}
+	return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *ContactFieldMutation) AddedField(name string) (ent.Value, bool) {
+	switch name {
+	case contactfield.FieldStatus:
+		return m.AddedStatus()
+	}
+	return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *ContactFieldMutation) AddField(name string, value ent.Value) error {
+	switch name {
+	case contactfield.FieldStatus:
+		v, ok := value.(int8)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddStatus(v)
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *ContactFieldMutation) ClearedFields() []string {
+	var fields []string
+	if m.FieldCleared(contactfield.FieldStatus) {
+		fields = append(fields, contactfield.FieldStatus)
+	}
+	if m.FieldCleared(contactfield.FieldDeletedAt) {
+		fields = append(fields, contactfield.FieldDeletedAt)
+	}
+	return fields
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *ContactFieldMutation) FieldCleared(name string) bool {
+	_, ok := m.clearedFields[name]
+	return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *ContactFieldMutation) ClearField(name string) error {
+	switch name {
+	case contactfield.FieldStatus:
+		m.ClearStatus()
+		return nil
+	case contactfield.FieldDeletedAt:
+		m.ClearDeletedAt()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *ContactFieldMutation) ResetField(name string) error {
+	switch name {
+	case contactfield.FieldCreatedAt:
+		m.ResetCreatedAt()
+		return nil
+	case contactfield.FieldUpdatedAt:
+		m.ResetUpdatedAt()
+		return nil
+	case contactfield.FieldStatus:
+		m.ResetStatus()
+		return nil
+	case contactfield.FieldDeletedAt:
+		m.ResetDeletedAt()
+		return nil
+	case contactfield.FieldContactID:
+		m.ResetContactID()
+		return nil
+	case contactfield.FieldFormID:
+		m.ResetFormID()
+		return nil
+	case contactfield.FieldValue:
+		m.ResetValue()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *ContactFieldMutation) AddedEdges() []string {
+	edges := make([]string, 0, 1)
+	if m.field_contact != nil {
+		edges = append(edges, contactfield.EdgeFieldContact)
+	}
+	return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *ContactFieldMutation) AddedIDs(name string) []ent.Value {
+	switch name {
+	case contactfield.EdgeFieldContact:
+		if id := m.field_contact; id != nil {
+			return []ent.Value{*id}
+		}
+	}
+	return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *ContactFieldMutation) RemovedEdges() []string {
+	edges := make([]string, 0, 1)
+	return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *ContactFieldMutation) RemovedIDs(name string) []ent.Value {
+	return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *ContactFieldMutation) ClearedEdges() []string {
+	edges := make([]string, 0, 1)
+	if m.clearedfield_contact {
+		edges = append(edges, contactfield.EdgeFieldContact)
+	}
+	return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *ContactFieldMutation) EdgeCleared(name string) bool {
+	switch name {
+	case contactfield.EdgeFieldContact:
+		return m.clearedfield_contact
+	}
+	return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *ContactFieldMutation) ClearEdge(name string) error {
+	switch name {
+	case contactfield.EdgeFieldContact:
+		m.ClearFieldContact()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *ContactFieldMutation) ResetEdge(name string) error {
+	switch name {
+	case contactfield.EdgeFieldContact:
+		m.ResetFieldContact()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactField edge %s", name)
+}
+
+// ContactFieldTemplateMutation represents an operation that mutates the ContactFieldTemplate nodes in the graph.
+type ContactFieldTemplateMutation struct {
+	config
+	op                 Op
+	typ                string
+	id                 *uint64
+	created_at         *time.Time
+	updated_at         *time.Time
+	status             *uint8
+	addstatus          *int8
+	deleted_at         *time.Time
+	organization_id    *uint64
+	addorganization_id *int64
+	template           *[]custom_types.ContactFieldTemplate
+	appendtemplate     []custom_types.ContactFieldTemplate
+	clearedFields      map[string]struct{}
+	done               bool
+	oldValue           func(context.Context) (*ContactFieldTemplate, error)
+	predicates         []predicate.ContactFieldTemplate
+}
+
+var _ ent.Mutation = (*ContactFieldTemplateMutation)(nil)
+
+// contactfieldtemplateOption allows management of the mutation configuration using functional options.
+type contactfieldtemplateOption func(*ContactFieldTemplateMutation)
+
+// newContactFieldTemplateMutation creates new mutation for the ContactFieldTemplate entity.
+func newContactFieldTemplateMutation(c config, op Op, opts ...contactfieldtemplateOption) *ContactFieldTemplateMutation {
+	m := &ContactFieldTemplateMutation{
+		config:        c,
+		op:            op,
+		typ:           TypeContactFieldTemplate,
+		clearedFields: make(map[string]struct{}),
+	}
+	for _, opt := range opts {
+		opt(m)
+	}
+	return m
+}
+
+// withContactFieldTemplateID sets the ID field of the mutation.
+func withContactFieldTemplateID(id uint64) contactfieldtemplateOption {
+	return func(m *ContactFieldTemplateMutation) {
+		var (
+			err   error
+			once  sync.Once
+			value *ContactFieldTemplate
+		)
+		m.oldValue = func(ctx context.Context) (*ContactFieldTemplate, error) {
+			once.Do(func() {
+				if m.done {
+					err = errors.New("querying old values post mutation is not allowed")
+				} else {
+					value, err = m.Client().ContactFieldTemplate.Get(ctx, id)
+				}
+			})
+			return value, err
+		}
+		m.id = &id
+	}
+}
+
+// withContactFieldTemplate sets the old ContactFieldTemplate of the mutation.
+func withContactFieldTemplate(node *ContactFieldTemplate) contactfieldtemplateOption {
+	return func(m *ContactFieldTemplateMutation) {
+		m.oldValue = func(context.Context) (*ContactFieldTemplate, error) {
+			return node, nil
+		}
+		m.id = &node.ID
+	}
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m ContactFieldTemplateMutation) Client() *Client {
+	client := &Client{config: m.config}
+	client.init()
+	return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m ContactFieldTemplateMutation) Tx() (*Tx, error) {
+	if _, ok := m.driver.(*txDriver); !ok {
+		return nil, errors.New("ent: mutation is not running in a transaction")
+	}
+	tx := &Tx{config: m.config}
+	tx.init()
+	return tx, nil
+}
+
+// SetID sets the value of the id field. Note that this
+// operation is only accepted on creation of ContactFieldTemplate entities.
+func (m *ContactFieldTemplateMutation) SetID(id uint64) {
+	m.id = &id
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *ContactFieldTemplateMutation) ID() (id uint64, exists bool) {
+	if m.id == nil {
+		return
+	}
+	return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *ContactFieldTemplateMutation) IDs(ctx context.Context) ([]uint64, error) {
+	switch {
+	case m.op.Is(OpUpdateOne | OpDeleteOne):
+		id, exists := m.ID()
+		if exists {
+			return []uint64{id}, nil
+		}
+		fallthrough
+	case m.op.Is(OpUpdate | OpDelete):
+		return m.Client().ContactFieldTemplate.Query().Where(m.predicates...).IDs(ctx)
+	default:
+		return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+	}
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (m *ContactFieldTemplateMutation) SetCreatedAt(t time.Time) {
+	m.created_at = &t
+}
+
+// CreatedAt returns the value of the "created_at" field in the mutation.
+func (m *ContactFieldTemplateMutation) CreatedAt() (r time.Time, exists bool) {
+	v := m.created_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldCreatedAt returns the old "created_at" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldCreatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
+	}
+	return oldValue.CreatedAt, nil
+}
+
+// ResetCreatedAt resets all changes to the "created_at" field.
+func (m *ContactFieldTemplateMutation) ResetCreatedAt() {
+	m.created_at = nil
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (m *ContactFieldTemplateMutation) SetUpdatedAt(t time.Time) {
+	m.updated_at = &t
+}
+
+// UpdatedAt returns the value of the "updated_at" field in the mutation.
+func (m *ContactFieldTemplateMutation) UpdatedAt() (r time.Time, exists bool) {
+	v := m.updated_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldUpdatedAt returns the old "updated_at" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
+	}
+	return oldValue.UpdatedAt, nil
+}
+
+// ResetUpdatedAt resets all changes to the "updated_at" field.
+func (m *ContactFieldTemplateMutation) ResetUpdatedAt() {
+	m.updated_at = nil
+}
+
+// SetStatus sets the "status" field.
+func (m *ContactFieldTemplateMutation) SetStatus(u uint8) {
+	m.status = &u
+	m.addstatus = nil
+}
+
+// Status returns the value of the "status" field in the mutation.
+func (m *ContactFieldTemplateMutation) Status() (r uint8, exists bool) {
+	v := m.status
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldStatus returns the old "status" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldStatus(ctx context.Context) (v uint8, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldStatus is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldStatus requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldStatus: %w", err)
+	}
+	return oldValue.Status, nil
+}
+
+// AddStatus adds u to the "status" field.
+func (m *ContactFieldTemplateMutation) AddStatus(u int8) {
+	if m.addstatus != nil {
+		*m.addstatus += u
+	} else {
+		m.addstatus = &u
+	}
+}
+
+// AddedStatus returns the value that was added to the "status" field in this mutation.
+func (m *ContactFieldTemplateMutation) AddedStatus() (r int8, exists bool) {
+	v := m.addstatus
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ClearStatus clears the value of the "status" field.
+func (m *ContactFieldTemplateMutation) ClearStatus() {
+	m.status = nil
+	m.addstatus = nil
+	m.clearedFields[contactfieldtemplate.FieldStatus] = struct{}{}
+}
+
+// StatusCleared returns if the "status" field was cleared in this mutation.
+func (m *ContactFieldTemplateMutation) StatusCleared() bool {
+	_, ok := m.clearedFields[contactfieldtemplate.FieldStatus]
+	return ok
+}
+
+// ResetStatus resets all changes to the "status" field.
+func (m *ContactFieldTemplateMutation) ResetStatus() {
+	m.status = nil
+	m.addstatus = nil
+	delete(m.clearedFields, contactfieldtemplate.FieldStatus)
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (m *ContactFieldTemplateMutation) SetDeletedAt(t time.Time) {
+	m.deleted_at = &t
+}
+
+// DeletedAt returns the value of the "deleted_at" field in the mutation.
+func (m *ContactFieldTemplateMutation) DeletedAt() (r time.Time, exists bool) {
+	v := m.deleted_at
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldDeletedAt returns the old "deleted_at" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldDeletedAt requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err)
+	}
+	return oldValue.DeletedAt, nil
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (m *ContactFieldTemplateMutation) ClearDeletedAt() {
+	m.deleted_at = nil
+	m.clearedFields[contactfieldtemplate.FieldDeletedAt] = struct{}{}
+}
+
+// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation.
+func (m *ContactFieldTemplateMutation) DeletedAtCleared() bool {
+	_, ok := m.clearedFields[contactfieldtemplate.FieldDeletedAt]
+	return ok
+}
+
+// ResetDeletedAt resets all changes to the "deleted_at" field.
+func (m *ContactFieldTemplateMutation) ResetDeletedAt() {
+	m.deleted_at = nil
+	delete(m.clearedFields, contactfieldtemplate.FieldDeletedAt)
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (m *ContactFieldTemplateMutation) SetOrganizationID(u uint64) {
+	m.organization_id = &u
+	m.addorganization_id = nil
+}
+
+// OrganizationID returns the value of the "organization_id" field in the mutation.
+func (m *ContactFieldTemplateMutation) OrganizationID() (r uint64, exists bool) {
+	v := m.organization_id
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldOrganizationID returns the old "organization_id" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldOrganizationID(ctx context.Context) (v uint64, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldOrganizationID is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldOrganizationID requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldOrganizationID: %w", err)
+	}
+	return oldValue.OrganizationID, nil
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (m *ContactFieldTemplateMutation) AddOrganizationID(u int64) {
+	if m.addorganization_id != nil {
+		*m.addorganization_id += u
+	} else {
+		m.addorganization_id = &u
+	}
+}
+
+// AddedOrganizationID returns the value that was added to the "organization_id" field in this mutation.
+func (m *ContactFieldTemplateMutation) AddedOrganizationID() (r int64, exists bool) {
+	v := m.addorganization_id
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ResetOrganizationID resets all changes to the "organization_id" field.
+func (m *ContactFieldTemplateMutation) ResetOrganizationID() {
+	m.organization_id = nil
+	m.addorganization_id = nil
+}
+
+// SetTemplate sets the "template" field.
+func (m *ContactFieldTemplateMutation) SetTemplate(ctft []custom_types.ContactFieldTemplate) {
+	m.template = &ctft
+	m.appendtemplate = nil
+}
+
+// Template returns the value of the "template" field in the mutation.
+func (m *ContactFieldTemplateMutation) Template() (r []custom_types.ContactFieldTemplate, exists bool) {
+	v := m.template
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldTemplate returns the old "template" field's value of the ContactFieldTemplate entity.
+// If the ContactFieldTemplate object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *ContactFieldTemplateMutation) OldTemplate(ctx context.Context) (v []custom_types.ContactFieldTemplate, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldTemplate is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldTemplate requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldTemplate: %w", err)
+	}
+	return oldValue.Template, nil
+}
+
+// AppendTemplate adds ctft to the "template" field.
+func (m *ContactFieldTemplateMutation) AppendTemplate(ctft []custom_types.ContactFieldTemplate) {
+	m.appendtemplate = append(m.appendtemplate, ctft...)
+}
+
+// AppendedTemplate returns the list of values that were appended to the "template" field in this mutation.
+func (m *ContactFieldTemplateMutation) AppendedTemplate() ([]custom_types.ContactFieldTemplate, bool) {
+	if len(m.appendtemplate) == 0 {
+		return nil, false
+	}
+	return m.appendtemplate, true
+}
+
+// ResetTemplate resets all changes to the "template" field.
+func (m *ContactFieldTemplateMutation) ResetTemplate() {
+	m.template = nil
+	m.appendtemplate = nil
+}
+
+// Where appends a list predicates to the ContactFieldTemplateMutation builder.
+func (m *ContactFieldTemplateMutation) Where(ps ...predicate.ContactFieldTemplate) {
+	m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the ContactFieldTemplateMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *ContactFieldTemplateMutation) WhereP(ps ...func(*sql.Selector)) {
+	p := make([]predicate.ContactFieldTemplate, len(ps))
+	for i := range ps {
+		p[i] = ps[i]
+	}
+	m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *ContactFieldTemplateMutation) Op() Op {
+	return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *ContactFieldTemplateMutation) SetOp(op Op) {
+	m.op = op
+}
+
+// Type returns the node type of this mutation (ContactFieldTemplate).
+func (m *ContactFieldTemplateMutation) Type() string {
+	return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *ContactFieldTemplateMutation) Fields() []string {
+	fields := make([]string, 0, 6)
+	if m.created_at != nil {
+		fields = append(fields, contactfieldtemplate.FieldCreatedAt)
+	}
+	if m.updated_at != nil {
+		fields = append(fields, contactfieldtemplate.FieldUpdatedAt)
+	}
+	if m.status != nil {
+		fields = append(fields, contactfieldtemplate.FieldStatus)
+	}
+	if m.deleted_at != nil {
+		fields = append(fields, contactfieldtemplate.FieldDeletedAt)
+	}
+	if m.organization_id != nil {
+		fields = append(fields, contactfieldtemplate.FieldOrganizationID)
+	}
+	if m.template != nil {
+		fields = append(fields, contactfieldtemplate.FieldTemplate)
+	}
+	return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *ContactFieldTemplateMutation) Field(name string) (ent.Value, bool) {
+	switch name {
+	case contactfieldtemplate.FieldCreatedAt:
+		return m.CreatedAt()
+	case contactfieldtemplate.FieldUpdatedAt:
+		return m.UpdatedAt()
+	case contactfieldtemplate.FieldStatus:
+		return m.Status()
+	case contactfieldtemplate.FieldDeletedAt:
+		return m.DeletedAt()
+	case contactfieldtemplate.FieldOrganizationID:
+		return m.OrganizationID()
+	case contactfieldtemplate.FieldTemplate:
+		return m.Template()
+	}
+	return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *ContactFieldTemplateMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+	switch name {
+	case contactfieldtemplate.FieldCreatedAt:
+		return m.OldCreatedAt(ctx)
+	case contactfieldtemplate.FieldUpdatedAt:
+		return m.OldUpdatedAt(ctx)
+	case contactfieldtemplate.FieldStatus:
+		return m.OldStatus(ctx)
+	case contactfieldtemplate.FieldDeletedAt:
+		return m.OldDeletedAt(ctx)
+	case contactfieldtemplate.FieldOrganizationID:
+		return m.OldOrganizationID(ctx)
+	case contactfieldtemplate.FieldTemplate:
+		return m.OldTemplate(ctx)
+	}
+	return nil, fmt.Errorf("unknown ContactFieldTemplate field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *ContactFieldTemplateMutation) SetField(name string, value ent.Value) error {
+	switch name {
+	case contactfieldtemplate.FieldCreatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetCreatedAt(v)
+		return nil
+	case contactfieldtemplate.FieldUpdatedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetUpdatedAt(v)
+		return nil
+	case contactfieldtemplate.FieldStatus:
+		v, ok := value.(uint8)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetStatus(v)
+		return nil
+	case contactfieldtemplate.FieldDeletedAt:
+		v, ok := value.(time.Time)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetDeletedAt(v)
+		return nil
+	case contactfieldtemplate.FieldOrganizationID:
+		v, ok := value.(uint64)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetOrganizationID(v)
+		return nil
+	case contactfieldtemplate.FieldTemplate:
+		v, ok := value.([]custom_types.ContactFieldTemplate)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetTemplate(v)
+		return nil
+	}
+	return fmt.Errorf("unknown ContactFieldTemplate field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *ContactFieldTemplateMutation) AddedFields() []string {
+	var fields []string
+	if m.addstatus != nil {
+		fields = append(fields, contactfieldtemplate.FieldStatus)
+	}
+	if m.addorganization_id != nil {
+		fields = append(fields, contactfieldtemplate.FieldOrganizationID)
+	}
+	return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *ContactFieldTemplateMutation) AddedField(name string) (ent.Value, bool) {
+	switch name {
+	case contactfieldtemplate.FieldStatus:
+		return m.AddedStatus()
+	case contactfieldtemplate.FieldOrganizationID:
+		return m.AddedOrganizationID()
+	}
+	return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *ContactFieldTemplateMutation) AddField(name string, value ent.Value) error {
+	switch name {
+	case contactfieldtemplate.FieldStatus:
+		v, ok := value.(int8)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddStatus(v)
+		return nil
+	case contactfieldtemplate.FieldOrganizationID:
+		v, ok := value.(int64)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddOrganizationID(v)
+		return nil
+	}
+	return fmt.Errorf("unknown ContactFieldTemplate numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *ContactFieldTemplateMutation) ClearedFields() []string {
+	var fields []string
+	if m.FieldCleared(contactfieldtemplate.FieldStatus) {
+		fields = append(fields, contactfieldtemplate.FieldStatus)
+	}
+	if m.FieldCleared(contactfieldtemplate.FieldDeletedAt) {
+		fields = append(fields, contactfieldtemplate.FieldDeletedAt)
+	}
+	return fields
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *ContactFieldTemplateMutation) FieldCleared(name string) bool {
+	_, ok := m.clearedFields[name]
+	return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *ContactFieldTemplateMutation) ClearField(name string) error {
+	switch name {
+	case contactfieldtemplate.FieldStatus:
+		m.ClearStatus()
+		return nil
+	case contactfieldtemplate.FieldDeletedAt:
+		m.ClearDeletedAt()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactFieldTemplate nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *ContactFieldTemplateMutation) ResetField(name string) error {
+	switch name {
+	case contactfieldtemplate.FieldCreatedAt:
+		m.ResetCreatedAt()
+		return nil
+	case contactfieldtemplate.FieldUpdatedAt:
+		m.ResetUpdatedAt()
+		return nil
+	case contactfieldtemplate.FieldStatus:
+		m.ResetStatus()
+		return nil
+	case contactfieldtemplate.FieldDeletedAt:
+		m.ResetDeletedAt()
+		return nil
+	case contactfieldtemplate.FieldOrganizationID:
+		m.ResetOrganizationID()
+		return nil
+	case contactfieldtemplate.FieldTemplate:
+		m.ResetTemplate()
+		return nil
+	}
+	return fmt.Errorf("unknown ContactFieldTemplate field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *ContactFieldTemplateMutation) AddedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *ContactFieldTemplateMutation) AddedIDs(name string) []ent.Value {
+	return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *ContactFieldTemplateMutation) RemovedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *ContactFieldTemplateMutation) RemovedIDs(name string) []ent.Value {
+	return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *ContactFieldTemplateMutation) ClearedEdges() []string {
+	edges := make([]string, 0, 0)
+	return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *ContactFieldTemplateMutation) EdgeCleared(name string) bool {
+	return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *ContactFieldTemplateMutation) ClearEdge(name string) error {
+	return fmt.Errorf("unknown ContactFieldTemplate unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *ContactFieldTemplateMutation) ResetEdge(name string) error {
+	return fmt.Errorf("unknown ContactFieldTemplate edge %s", name)
+}
+
 // CreditBalanceMutation represents an operation that mutates the CreditBalance nodes in the graph.
 type CreditBalanceMutation struct {
 	config

+ 164 - 0
ent/pagination.go

@@ -15,6 +15,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/employee"
@@ -904,6 +906,168 @@ func (c *ContactQuery) Page(
 	return ret, nil
 }
 
+type ContactFieldPager struct {
+	Order  contactfield.OrderOption
+	Filter func(*ContactFieldQuery) (*ContactFieldQuery, error)
+}
+
+// ContactFieldPaginateOption enables pagination customization.
+type ContactFieldPaginateOption func(*ContactFieldPager)
+
+// DefaultContactFieldOrder is the default ordering of ContactField.
+var DefaultContactFieldOrder = Desc(contactfield.FieldID)
+
+func newContactFieldPager(opts []ContactFieldPaginateOption) (*ContactFieldPager, error) {
+	pager := &ContactFieldPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultContactFieldOrder
+	}
+	return pager, nil
+}
+
+func (p *ContactFieldPager) ApplyFilter(query *ContactFieldQuery) (*ContactFieldQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// ContactFieldPageList is ContactField PageList result.
+type ContactFieldPageList struct {
+	List        []*ContactField `json:"list"`
+	PageDetails *PageDetails    `json:"pageDetails"`
+}
+
+func (cf *ContactFieldQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...ContactFieldPaginateOption,
+) (*ContactFieldPageList, error) {
+
+	pager, err := newContactFieldPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if cf, err = pager.ApplyFilter(cf); err != nil {
+		return nil, err
+	}
+
+	ret := &ContactFieldPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := cf.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		cf = cf.Order(pager.Order)
+	} else {
+		cf = cf.Order(DefaultContactFieldOrder)
+	}
+
+	cf = cf.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := cf.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
+type ContactFieldTemplatePager struct {
+	Order  contactfieldtemplate.OrderOption
+	Filter func(*ContactFieldTemplateQuery) (*ContactFieldTemplateQuery, error)
+}
+
+// ContactFieldTemplatePaginateOption enables pagination customization.
+type ContactFieldTemplatePaginateOption func(*ContactFieldTemplatePager)
+
+// DefaultContactFieldTemplateOrder is the default ordering of ContactFieldTemplate.
+var DefaultContactFieldTemplateOrder = Desc(contactfieldtemplate.FieldID)
+
+func newContactFieldTemplatePager(opts []ContactFieldTemplatePaginateOption) (*ContactFieldTemplatePager, error) {
+	pager := &ContactFieldTemplatePager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultContactFieldTemplateOrder
+	}
+	return pager, nil
+}
+
+func (p *ContactFieldTemplatePager) ApplyFilter(query *ContactFieldTemplateQuery) (*ContactFieldTemplateQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// ContactFieldTemplatePageList is ContactFieldTemplate PageList result.
+type ContactFieldTemplatePageList struct {
+	List        []*ContactFieldTemplate `json:"list"`
+	PageDetails *PageDetails            `json:"pageDetails"`
+}
+
+func (cft *ContactFieldTemplateQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...ContactFieldTemplatePaginateOption,
+) (*ContactFieldTemplatePageList, error) {
+
+	pager, err := newContactFieldTemplatePager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if cft, err = pager.ApplyFilter(cft); err != nil {
+		return nil, err
+	}
+
+	ret := &ContactFieldTemplatePageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := cft.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		cft = cft.Order(pager.Order)
+	} else {
+		cft = cft.Order(DefaultContactFieldTemplateOrder)
+	}
+
+	cft = cft.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := cft.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type CreditBalancePager struct {
 	Order  creditbalance.OrderOption
 	Filter func(*CreditBalanceQuery) (*CreditBalanceQuery, error)

+ 6 - 0
ent/predicate/predicate.go

@@ -36,6 +36,12 @@ type ChatSession func(*sql.Selector)
 // Contact is the predicate function for contact builders.
 type Contact func(*sql.Selector)
 
+// ContactField is the predicate function for contactfield builders.
+type ContactField func(*sql.Selector)
+
+// ContactFieldTemplate is the predicate function for contactfieldtemplate builders.
+type ContactFieldTemplate func(*sql.Selector)
+
 // CreditBalance is the predicate function for creditbalance builders.
 type CreditBalance func(*sql.Selector)
 

+ 60 - 0
ent/runtime/runtime.go

@@ -14,6 +14,8 @@ import (
 	"wechat-api/ent/chatrecords"
 	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/creditbalance"
 	"wechat-api/ent/creditusage"
 	"wechat-api/ent/employee"
@@ -507,6 +509,64 @@ func init() {
 	contactDescPhone := contactFields[25].Descriptor()
 	// contact.DefaultPhone holds the default value on creation for the phone field.
 	contact.DefaultPhone = contactDescPhone.Default.(string)
+	contactfieldMixin := schema.ContactField{}.Mixin()
+	contactfieldMixinHooks2 := contactfieldMixin[2].Hooks()
+	contactfield.Hooks[0] = contactfieldMixinHooks2[0]
+	contactfieldMixinInters2 := contactfieldMixin[2].Interceptors()
+	contactfield.Interceptors[0] = contactfieldMixinInters2[0]
+	contactfieldMixinFields0 := contactfieldMixin[0].Fields()
+	_ = contactfieldMixinFields0
+	contactfieldMixinFields1 := contactfieldMixin[1].Fields()
+	_ = contactfieldMixinFields1
+	contactfieldFields := schema.ContactField{}.Fields()
+	_ = contactfieldFields
+	// contactfieldDescCreatedAt is the schema descriptor for created_at field.
+	contactfieldDescCreatedAt := contactfieldMixinFields0[1].Descriptor()
+	// contactfield.DefaultCreatedAt holds the default value on creation for the created_at field.
+	contactfield.DefaultCreatedAt = contactfieldDescCreatedAt.Default.(func() time.Time)
+	// contactfieldDescUpdatedAt is the schema descriptor for updated_at field.
+	contactfieldDescUpdatedAt := contactfieldMixinFields0[2].Descriptor()
+	// contactfield.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	contactfield.DefaultUpdatedAt = contactfieldDescUpdatedAt.Default.(func() time.Time)
+	// contactfield.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	contactfield.UpdateDefaultUpdatedAt = contactfieldDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// contactfieldDescStatus is the schema descriptor for status field.
+	contactfieldDescStatus := contactfieldMixinFields1[0].Descriptor()
+	// contactfield.DefaultStatus holds the default value on creation for the status field.
+	contactfield.DefaultStatus = contactfieldDescStatus.Default.(uint8)
+	// contactfieldDescContactID is the schema descriptor for contact_id field.
+	contactfieldDescContactID := contactfieldFields[0].Descriptor()
+	// contactfield.DefaultContactID holds the default value on creation for the contact_id field.
+	contactfield.DefaultContactID = contactfieldDescContactID.Default.(uint64)
+	contactfieldtemplateMixin := schema.ContactFieldTemplate{}.Mixin()
+	contactfieldtemplateMixinHooks2 := contactfieldtemplateMixin[2].Hooks()
+	contactfieldtemplate.Hooks[0] = contactfieldtemplateMixinHooks2[0]
+	contactfieldtemplateMixinInters2 := contactfieldtemplateMixin[2].Interceptors()
+	contactfieldtemplate.Interceptors[0] = contactfieldtemplateMixinInters2[0]
+	contactfieldtemplateMixinFields0 := contactfieldtemplateMixin[0].Fields()
+	_ = contactfieldtemplateMixinFields0
+	contactfieldtemplateMixinFields1 := contactfieldtemplateMixin[1].Fields()
+	_ = contactfieldtemplateMixinFields1
+	contactfieldtemplateFields := schema.ContactFieldTemplate{}.Fields()
+	_ = contactfieldtemplateFields
+	// contactfieldtemplateDescCreatedAt is the schema descriptor for created_at field.
+	contactfieldtemplateDescCreatedAt := contactfieldtemplateMixinFields0[1].Descriptor()
+	// contactfieldtemplate.DefaultCreatedAt holds the default value on creation for the created_at field.
+	contactfieldtemplate.DefaultCreatedAt = contactfieldtemplateDescCreatedAt.Default.(func() time.Time)
+	// contactfieldtemplateDescUpdatedAt is the schema descriptor for updated_at field.
+	contactfieldtemplateDescUpdatedAt := contactfieldtemplateMixinFields0[2].Descriptor()
+	// contactfieldtemplate.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	contactfieldtemplate.DefaultUpdatedAt = contactfieldtemplateDescUpdatedAt.Default.(func() time.Time)
+	// contactfieldtemplate.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	contactfieldtemplate.UpdateDefaultUpdatedAt = contactfieldtemplateDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// contactfieldtemplateDescStatus is the schema descriptor for status field.
+	contactfieldtemplateDescStatus := contactfieldtemplateMixinFields1[0].Descriptor()
+	// contactfieldtemplate.DefaultStatus holds the default value on creation for the status field.
+	contactfieldtemplate.DefaultStatus = contactfieldtemplateDescStatus.Default.(uint8)
+	// contactfieldtemplateDescOrganizationID is the schema descriptor for organization_id field.
+	contactfieldtemplateDescOrganizationID := contactfieldtemplateFields[0].Descriptor()
+	// contactfieldtemplate.DefaultOrganizationID holds the default value on creation for the organization_id field.
+	contactfieldtemplate.DefaultOrganizationID = contactfieldtemplateDescOrganizationID.Default.(uint64)
 	creditbalanceMixin := schema.CreditBalance{}.Mixin()
 	creditbalanceMixinHooks1 := creditbalanceMixin[1].Hooks()
 	creditbalance.Hooks[0] = creditbalanceMixinHooks1[0]

+ 1 - 0
ent/schema/contact.go

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

+ 59 - 0
ent/schema/contact_field.go

@@ -0,0 +1,59 @@
+package schema
+
+import (
+	"entgo.io/ent/schema/edge"
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type ContactField struct {
+	ent.Schema
+}
+
+func (ContactField) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("contact_id").Default(1).
+			Comment("联系人 ID").
+			Annotations(entsql.WithComments(true)),
+		field.String("form_id").
+			Annotations(entsql.WithComments(true)).
+			Comment("表单 id"),
+		field.JSON("value", []string{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("表单值"),
+	}
+}
+
+func (ContactField) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		mixins.StatusMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (ContactField) Indexes() []ent.Index {
+	return []ent.Index{}
+}
+
+func (ContactField) Edges() []ent.Edge {
+	return []ent.Edge{
+		edge.From("field_contact", Contact.Type).
+			Ref("contact_fields").
+			Unique().
+			Field("contact_id").
+			Required(),
+	}
+}
+
+func (ContactField) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "contact_field"},
+	}
+}

+ 50 - 0
ent/schema/contact_field_template.go

@@ -0,0 +1,50 @@
+package schema
+
+import (
+	"wechat-api/ent/custom_types"
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type ContactFieldTemplate struct {
+	ent.Schema
+}
+
+func (ContactFieldTemplate) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("organization_id").Default(1).
+			Comment("机构 ID").
+			Annotations(entsql.WithComments(true)),
+		field.JSON("template", []custom_types.ContactFieldTemplate{}).
+			Annotations(entsql.WithComments(true)).
+			Comment("模板"),
+	}
+}
+
+func (ContactFieldTemplate) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		mixins.StatusMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (ContactFieldTemplate) Indexes() []ent.Index {
+	return []ent.Index{}
+}
+
+func (ContactFieldTemplate) Edges() []ent.Edge {
+	return []ent.Edge{}
+}
+
+func (ContactFieldTemplate) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "contact_field_template"},
+	}
+}

+ 264 - 0
ent/set_not_nil.go

@@ -2792,6 +2792,270 @@ func (c *ContactCreate) SetNotNilPhone(value *string) *ContactCreate {
 }
 
 // set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilUpdatedAt(value *time.Time) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetUpdatedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilUpdatedAt(value *time.Time) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetUpdatedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilUpdatedAt(value *time.Time) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetUpdatedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilStatus(value *uint8) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetStatus(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilStatus(value *uint8) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetStatus(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilStatus(value *uint8) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetStatus(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilDeletedAt(value *time.Time) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetDeletedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilDeletedAt(value *time.Time) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetDeletedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilDeletedAt(value *time.Time) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetDeletedAt(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilContactID(value *uint64) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetContactID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilContactID(value *uint64) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetContactID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilContactID(value *uint64) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetContactID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilFormID(value *string) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetFormID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilFormID(value *string) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetFormID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilFormID(value *string) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetFormID(*value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdate) SetNotNilValue(value []string) *ContactFieldUpdate {
+	if value != nil {
+		return cf.SetValue(value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldUpdateOne) SetNotNilValue(value []string) *ContactFieldUpdateOne {
+	if value != nil {
+		return cf.SetValue(value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cf *ContactFieldCreate) SetNotNilValue(value []string) *ContactFieldCreate {
+	if value != nil {
+		return cf.SetValue(value)
+	}
+	return cf
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdate) SetNotNilUpdatedAt(value *time.Time) *ContactFieldTemplateUpdate {
+	if value != nil {
+		return cft.SetUpdatedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdateOne) SetNotNilUpdatedAt(value *time.Time) *ContactFieldTemplateUpdateOne {
+	if value != nil {
+		return cft.SetUpdatedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateCreate) SetNotNilUpdatedAt(value *time.Time) *ContactFieldTemplateCreate {
+	if value != nil {
+		return cft.SetUpdatedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdate) SetNotNilStatus(value *uint8) *ContactFieldTemplateUpdate {
+	if value != nil {
+		return cft.SetStatus(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdateOne) SetNotNilStatus(value *uint8) *ContactFieldTemplateUpdateOne {
+	if value != nil {
+		return cft.SetStatus(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateCreate) SetNotNilStatus(value *uint8) *ContactFieldTemplateCreate {
+	if value != nil {
+		return cft.SetStatus(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdate) SetNotNilDeletedAt(value *time.Time) *ContactFieldTemplateUpdate {
+	if value != nil {
+		return cft.SetDeletedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdateOne) SetNotNilDeletedAt(value *time.Time) *ContactFieldTemplateUpdateOne {
+	if value != nil {
+		return cft.SetDeletedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateCreate) SetNotNilDeletedAt(value *time.Time) *ContactFieldTemplateCreate {
+	if value != nil {
+		return cft.SetDeletedAt(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdate) SetNotNilOrganizationID(value *uint64) *ContactFieldTemplateUpdate {
+	if value != nil {
+		return cft.SetOrganizationID(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdateOne) SetNotNilOrganizationID(value *uint64) *ContactFieldTemplateUpdateOne {
+	if value != nil {
+		return cft.SetOrganizationID(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateCreate) SetNotNilOrganizationID(value *uint64) *ContactFieldTemplateCreate {
+	if value != nil {
+		return cft.SetOrganizationID(*value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdate) SetNotNilTemplate(value []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdate {
+	if value != nil {
+		return cft.SetTemplate(value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateUpdateOne) SetNotNilTemplate(value []custom_types.ContactFieldTemplate) *ContactFieldTemplateUpdateOne {
+	if value != nil {
+		return cft.SetTemplate(value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
+func (cft *ContactFieldTemplateCreate) SetNotNilTemplate(value []custom_types.ContactFieldTemplate) *ContactFieldTemplateCreate {
+	if value != nil {
+		return cft.SetTemplate(value)
+	}
+	return cft
+}
+
+// set field if value's pointer is not nil.
 func (cb *CreditBalanceUpdate) SetNotNilUpdatedAt(value *time.Time) *CreditBalanceUpdate {
 	if value != nil {
 		return cb.SetUpdatedAt(*value)

+ 6 - 0
ent/tx.go

@@ -34,6 +34,10 @@ type Tx struct {
 	ChatSession *ChatSessionClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
+	// ContactField is the client for interacting with the ContactField builders.
+	ContactField *ContactFieldClient
+	// ContactFieldTemplate is the client for interacting with the ContactFieldTemplate builders.
+	ContactFieldTemplate *ContactFieldTemplateClient
 	// CreditBalance is the client for interacting with the CreditBalance builders.
 	CreditBalance *CreditBalanceClient
 	// CreditUsage is the client for interacting with the CreditUsage builders.
@@ -237,6 +241,8 @@ func (tx *Tx) init() {
 	tx.ChatRecords = NewChatRecordsClient(tx.config)
 	tx.ChatSession = NewChatSessionClient(tx.config)
 	tx.Contact = NewContactClient(tx.config)
+	tx.ContactField = NewContactFieldClient(tx.config)
+	tx.ContactFieldTemplate = NewContactFieldTemplateClient(tx.config)
 	tx.CreditBalance = NewCreditBalanceClient(tx.config)
 	tx.CreditUsage = NewCreditUsageClient(tx.config)
 	tx.Employee = NewEmployeeClient(tx.config)

+ 4 - 0
go.sum

@@ -472,6 +472,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
@@ -510,6 +511,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
@@ -611,6 +613,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
 github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
 github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

+ 44 - 0
internal/handler/contact_field_template/create_contact_field_template_handler.go

@@ -0,0 +1,44 @@
+package contact_field_template
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/contact_field_template"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /contact_field_template/create contact_field_template CreateContactFieldTemplate
+//
+// Create contact_field_template information | 创建 ContactFieldTemplate
+//
+// Create contact_field_template information | 创建 ContactFieldTemplate
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: ContactFieldTemplateInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func CreateContactFieldTemplateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.ContactFieldTemplateInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := contact_field_template.NewCreateContactFieldTemplateLogic(r.Context(), svcCtx)
+		resp, err := l.CreateContactFieldTemplate(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/contact_field_template/delete_contact_field_template_handler.go

@@ -0,0 +1,44 @@
+package contact_field_template
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/contact_field_template"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /contact_field_template/delete contact_field_template DeleteContactFieldTemplate
+//
+// Delete contact_field_template information | 删除 ContactFieldTemplate 信息
+//
+// Delete contact_field_template information | 删除 ContactFieldTemplate 信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteContactFieldTemplateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDsReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := contact_field_template.NewDeleteContactFieldTemplateLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteContactFieldTemplate(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/contact_field_template/get_contact_field_template_by_id_handler.go

@@ -0,0 +1,44 @@
+package contact_field_template
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/contact_field_template"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /contact_field_template contact_field_template GetContactFieldTemplateById
+//
+// Get contact_field_template by ID | 通过ID获取 ContactFieldTemplate
+//
+// Get contact_field_template by ID | 通过ID获取 ContactFieldTemplate
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: ContactFieldTemplateInfoResp
+
+func GetContactFieldTemplateByIdHandler(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 := contact_field_template.NewGetContactFieldTemplateByIdLogic(r.Context(), svcCtx)
+		resp, err := l.GetContactFieldTemplateById(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/contact_field_template/update_contact_field_template_handler.go

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

+ 30 - 0
internal/handler/routes.go

@@ -29,6 +29,7 @@ import (
 	chatrecords "wechat-api/internal/handler/chatrecords"
 	chatsession "wechat-api/internal/handler/chatsession"
 	contact "wechat-api/internal/handler/contact"
+	contact_field_template "wechat-api/internal/handler/contact_field_template"
 	credit_balance "wechat-api/internal/handler/credit_balance"
 	credit_usage "wechat-api/internal/handler/credit_usage"
 	dashboard "wechat-api/internal/handler/dashboard"
@@ -292,6 +293,35 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/contact_field_template/create",
+					Handler: contact_field_template.CreateContactFieldTemplateHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/contact_field_template/update",
+					Handler: contact_field_template.UpdateContactFieldTemplateHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/contact_field_template/delete",
+					Handler: contact_field_template.DeleteContactFieldTemplateHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/contact_field_template",
+					Handler: contact_field_template.GetContactFieldTemplateByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
 		[]rest.Route{
 			{
 				Method:  http.MethodPost,

+ 32 - 2
internal/logic/contact/create_contact_logic.go

@@ -2,7 +2,7 @@ package contact
 
 import (
 	"context"
-
+	"wechat-api/ent"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -27,8 +27,12 @@ func NewCreateContactLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cre
 }
 
 func (l *CreateContactLogic) CreateContact(req *types.ContactInfo) (*types.BaseMsgResp, error) {
+	tx, err := l.svcCtx.DB.Tx(l.ctx)
+	if err != nil {
+		return nil, err
+	}
 	organizationId := l.ctx.Value("organizationId").(uint64)
-	_, err := l.svcCtx.DB.Contact.Create().
+	contact, err := tx.Contact.Create().
 		SetNotNilStatus(req.Status).
 		SetNotNilWxWxid(req.WxWxid).
 		SetNotNilType(req.Type).
@@ -59,8 +63,34 @@ func (l *CreateContactLogic) CreateContact(req *types.ContactInfo) (*types.BaseM
 		Save(l.ctx)
 
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	err = CreateContactFields(l.ctx, tx, contact.ID, req.CustomFields)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	_ = tx.Commit()
 	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
 }
+
+func CreateContactFields(ctx context.Context, tx *ent.Tx, contact_id uint64, fields []types.ContactFieldTemplate) error {
+	for _, field := range fields {
+		//f, err := tx.ContactField.Query().Where(contactfield.ContactID(contact_id), contactfield.FormID(*field.Id)).First(l.ctx)
+		if field.Label != nil && len(field.Value) > 0 {
+			_, err := tx.ContactField.Create().
+				SetContactID(contact_id).
+				SetFormID(*field.Id).
+				SetValue(field.Value).
+				Save(ctx)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}

+ 71 - 27
internal/logic/contact/get_contact_by_id_logic.go

@@ -2,7 +2,10 @@ package contact
 
 import (
 	"context"
+	"wechat-api/ent"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/ent/custom_types"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -33,12 +36,33 @@ func (l *GetContactByIdLogic) GetContactById(req *types.IDReq) (*types.ContactIn
 		Where(
 			contact.IDEQ(req.Id),                   // Filter by ID
 			contact.OrganizationID(organizationId), // Additional filter by organizationId
-		).
+		).WithContactFields(func(query *ent.ContactFieldQuery) {
+		query.WithFieldContact()
+	}).
 		Only(l.ctx)
 	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	var custom_field []types.ContactFieldTemplate
+	field_template, _ := l.svcCtx.DB.ContactFieldTemplate.Query().
+		Where(
+			contactfieldtemplate.OrganizationID(organizationId), // Additional filter by organizationId
+		).
+		Only(l.ctx)
+	if field_template != nil && len(field_template.Template) > 0 {
+		field_set := make(map[string][]string)
+		fields := data.Edges.ContactFields
+		for _, field := range fields {
+			field_set[field.FormID] = field.Value
+		}
+		for _, template := range field_template.Template {
+			template.Value = field_set[*template.Id]
+
+			custom_field = append(custom_field, ConvertCustomToInternal(template))
+		}
+	}
+
 	return &types.ContactInfoResp{
 		BaseDataInfo: types.BaseDataInfo{
 			Code: 0,
@@ -50,32 +74,52 @@ func (l *GetContactByIdLogic) GetContactById(req *types.IDReq) (*types.ContactIn
 				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
 				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
 			},
-			Status:     &data.Status,
-			WxWxid:     &data.WxWxid,
-			Type:       &data.Type,
-			Wxid:       &data.Wxid,
-			Account:    &data.Account,
-			Nickname:   &data.Nickname,
-			Markname:   &data.Markname,
-			Headimg:    &data.Headimg,
-			Sex:        &data.Sex,
-			Starrole:   &data.Starrole,
-			Dontseeit:  &data.Dontseeit,
-			Dontseeme:  &data.Dontseeme,
-			Lag:        &data.Lag,
-			Gid:        &data.Gid,
-			Gname:      &data.Gname,
-			V3:         &data.V3,
-			Ctype:      &data.Ctype,
-			Cname:      &data.Cname,
-			Cage:       &data.Cage,
-			Carea:      &data.Carea,
-			Cc:         &data.Cc,
-			Phone:      &data.Phone,
-			Cbirthday:  &data.Cbirthday,
-			Cbirtharea: &data.Cbirtharea,
-			CidcardNo:  &data.CidcardNo,
-			Ctitle:     &data.Ctitle,
+			Status:       &data.Status,
+			WxWxid:       &data.WxWxid,
+			Type:         &data.Type,
+			Wxid:         &data.Wxid,
+			Account:      &data.Account,
+			Nickname:     &data.Nickname,
+			Markname:     &data.Markname,
+			Headimg:      &data.Headimg,
+			Sex:          &data.Sex,
+			Starrole:     &data.Starrole,
+			Dontseeit:    &data.Dontseeit,
+			Dontseeme:    &data.Dontseeme,
+			Lag:          &data.Lag,
+			Gid:          &data.Gid,
+			Gname:        &data.Gname,
+			V3:           &data.V3,
+			Ctype:        &data.Ctype,
+			Cname:        &data.Cname,
+			Cage:         &data.Cage,
+			Carea:        &data.Carea,
+			Cc:           &data.Cc,
+			Phone:        &data.Phone,
+			Cbirthday:    &data.Cbirthday,
+			Cbirtharea:   &data.Cbirtharea,
+			CidcardNo:    &data.CidcardNo,
+			Ctitle:       &data.Ctitle,
+			CustomFields: custom_field,
 		},
 	}, nil
 }
+
+func ConvertCustomToInternal(src custom_types.ContactFieldTemplate) types.ContactFieldTemplate {
+	var result types.ContactFieldTemplate
+	var options []types.ContactFieldTemplateOptions
+	for _, o := range src.Options {
+		options = append(options, types.ContactFieldTemplateOptions{
+			Label: o.Label,
+			Value: o.Value,
+		})
+	}
+	result = types.ContactFieldTemplate{
+		Type:    src.Type,
+		Id:      src.Id,
+		Label:   src.Label,
+		Options: options,
+		Value:   src.Value,
+	}
+	return result
+}

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

@@ -3,6 +3,7 @@ package contact
 import (
 	"context"
 	"wechat-api/ent"
+	"wechat-api/ent/contactfieldtemplate"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/wx"
@@ -89,6 +90,8 @@ func (l *GetContactListLogic) GetContactList(req *types.ContactListReq) (*types.
 
 	data, err := l.svcCtx.DB.Contact.Query().Where(predicates...).WithContactRelationships(func(query *ent.LabelRelationshipQuery) {
 		query.WithLabels()
+	}).WithContactFields(func(query *ent.ContactFieldQuery) {
+		query.WithFieldContact()
 	}).Page(l.ctx, req.Page, req.PageSize)
 
 	if err != nil {
@@ -117,7 +120,28 @@ func (l *GetContactListLogic) GetContactList(req *types.ContactListReq) (*types.
 		}
 	}
 
+	field_template, _ := l.svcCtx.DB.ContactFieldTemplate.Query().
+		Where(
+			contactfieldtemplate.OrganizationID(organizationId), // Additional filter by organizationId
+		).
+		Only(l.ctx)
+
 	for _, v := range data.List {
+		// 自定义字段
+		var custom_field []types.ContactFieldTemplate
+		if field_template != nil && len(field_template.Template) > 0 {
+			field_set := make(map[string][]string)
+			fields := v.Edges.ContactFields
+			for _, field := range fields {
+				field_set[field.FormID] = field.Value
+			}
+			for _, template := range field_template.Template {
+				template.Value = field_set[*template.Id]
+
+				custom_field = append(custom_field, ConvertCustomToInternal(template))
+			}
+		}
+
 		isInBlockList := false
 		labelRelationships := make([]types.ContactLabelList, 0)
 		if v.Edges.ContactRelationships != nil {
@@ -187,6 +211,8 @@ func (l *GetContactListLogic) GetContactList(req *types.ContactListReq) (*types.
 				Cbirtharea:         &v.Cbirtharea,
 				CidcardNo:          &v.CidcardNo,
 				Ctitle:             &v.Ctitle,
+
+				CustomFields: custom_field,
 			})
 	}
 

+ 49 - 1
internal/logic/contact/update_contact_logic.go

@@ -2,7 +2,9 @@ package contact
 
 import (
 	"context"
+	"wechat-api/ent"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/contactfield"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -26,8 +28,12 @@ func NewUpdateContactLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upd
 }
 
 func (l *UpdateContactLogic) UpdateContact(req *types.ContactInfo) (*types.BaseMsgResp, error) {
+	tx, err := l.svcCtx.DB.Tx(l.ctx)
+	if err != nil {
+		return nil, err
+	}
 	organizationId := l.ctx.Value("organizationId").(uint64)
-	err := l.svcCtx.DB.Contact.UpdateOneID(*req.Id).
+	err = tx.Contact.UpdateOneID(*req.Id).
 		Where(contact.OrganizationID(organizationId)).
 		SetNotNilStatus(req.Status).
 		SetNotNilWxWxid(req.WxWxid).
@@ -57,8 +63,50 @@ func (l *UpdateContactLogic) UpdateContact(req *types.ContactInfo) (*types.BaseM
 		Exec(l.ctx)
 
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	err = UpdateContactFields(l.ctx, tx, *req.Id, req.CustomFields)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	_ = tx.Commit()
+
 	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
 }
+
+func UpdateContactFields(ctx context.Context, tx *ent.Tx, contact_id uint64, fields []types.ContactFieldTemplate) error {
+	for _, field := range fields {
+		f, _ := tx.ContactField.Query().Where(contactfield.ContactID(contact_id), contactfield.FormID(*field.Id)).First(ctx)
+		logx.Debug("f: ", f)
+		if f == nil {
+			if field.Label != nil && len(field.Value) > 0 {
+				_, err := tx.ContactField.Create().
+					SetContactID(contact_id).
+					SetFormID(*field.Id).
+					SetValue(field.Value).
+					Save(ctx)
+				if err != nil {
+					return err
+				}
+			}
+		} else {
+			if field.Label != nil {
+				if len(field.Value) == 0 {
+					field.Value = []string{""}
+				}
+				_, err := tx.ContactField.UpdateOneID(f.ID).
+					SetValue(field.Value).
+					Save(ctx)
+				if err != nil {
+					return err
+				}
+			}
+		}
+	}
+	return nil
+}

+ 62 - 0
internal/logic/contact_field_template/create_contact_field_template_logic.go

@@ -0,0 +1,62 @@
+package contact_field_template
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/custom_types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateContactFieldTemplateLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewCreateContactFieldTemplateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateContactFieldTemplateLogic {
+	return &CreateContactFieldTemplateLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *CreateContactFieldTemplateLogic) CreateContactFieldTemplate(req *types.ContactFieldTemplateInfo) (resp *types.BaseMsgResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	template := ConvertContactFieldTemplates(req.Template)
+	_, err = l.svcCtx.DB.ContactFieldTemplate.Create().
+		SetOrganizationID(organizationId).
+		SetTemplate(template).
+		Save(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+}
+
+func ConvertContactFieldTemplates(input []types.ContactFieldTemplate) []custom_types.ContactFieldTemplate {
+	result := make([]custom_types.ContactFieldTemplate, len(input))
+	for i, item := range input {
+		options := make([]custom_types.ContactFieldTemplateOptions, len(item.Options))
+		for j, opt := range item.Options {
+			options[j] = custom_types.ContactFieldTemplateOptions{
+				Label: opt.Label,
+				Value: opt.Value,
+			}
+		}
+		result[i] = custom_types.ContactFieldTemplate{
+			Type:    item.Type,
+			Id:      item.Id,
+			Label:   item.Label,
+			Options: options,
+		}
+	}
+	return result
+}

+ 42 - 0
internal/logic/contact_field_template/delete_contact_field_template_logic.go

@@ -0,0 +1,42 @@
+package contact_field_template
+
+import (
+	"context"
+	"errors"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteContactFieldTemplateLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewDeleteContactFieldTemplateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteContactFieldTemplateLogic {
+	return &DeleteContactFieldTemplateLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *DeleteContactFieldTemplateLogic) DeleteContactFieldTemplate(req *types.IDsReq) (resp *types.BaseMsgResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+	if len(req.Ids) == 0 {
+		return nil, errors.New("ids参数不能为空")
+	}
+
+	_, err = l.svcCtx.DB.ContactFieldTemplate.Delete().Where(contactfieldtemplate.IDIn(req.Ids...), contactfieldtemplate.OrganizationID(organizationId)).Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}

+ 66 - 0
internal/logic/contact_field_template/get_contact_field_template_by_id_logic.go

@@ -0,0 +1,66 @@
+package contact_field_template
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/ent/custom_types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetContactFieldTemplateByIdLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetContactFieldTemplateByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetContactFieldTemplateByIdLogic {
+	return &GetContactFieldTemplateByIdLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetContactFieldTemplateByIdLogic) GetContactFieldTemplateById(req *types.IDReq) (resp *types.ContactFieldTemplateInfoResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+	data, err := l.svcCtx.DB.ContactFieldTemplate.Query().Where(contactfieldtemplate.ID(req.Id), contactfieldtemplate.OrganizationID(organizationId)).First(l.ctx)
+	if err != nil && !ent.IsNotFound(err) {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	template := ConvertCustomToInternal(data.Template)
+
+	return &types.ContactFieldTemplateInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: template,
+	}, nil
+}
+
+func ConvertCustomToInternal(src []custom_types.ContactFieldTemplate) []types.ContactFieldTemplate {
+	var result []types.ContactFieldTemplate
+	for _, s := range src {
+		var options []types.ContactFieldTemplateOptions
+		for _, o := range s.Options {
+			options = append(options, types.ContactFieldTemplateOptions{
+				Label: o.Label,
+				Value: o.Value,
+			})
+		}
+		result = append(result, types.ContactFieldTemplate{
+			Type:    s.Type,
+			Id:      s.Id,
+			Label:   s.Label,
+			Options: options,
+		})
+	}
+	return result
+}

+ 50 - 0
internal/logic/contact_field_template/update_contact_field_template_logic.go

@@ -0,0 +1,50 @@
+package contact_field_template
+
+import (
+	"context"
+	"errors"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/contactfieldtemplate"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateContactFieldTemplateLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewUpdateContactFieldTemplateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateContactFieldTemplateLogic {
+	return &UpdateContactFieldTemplateLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *UpdateContactFieldTemplateLogic) UpdateContactFieldTemplate(req *types.ContactFieldTemplateInfo) (resp *types.BaseMsgResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	if *req.Id <= 0 {
+		l.Error("记录ID不存在")
+		return nil, errors.New("记录ID不存在")
+	}
+
+	template := ConvertContactFieldTemplates(req.Template)
+
+	err = l.svcCtx.DB.ContactFieldTemplate.
+		Update().
+		Where(contactfieldtemplate.IDEQ(*req.Id), contactfieldtemplate.OrganizationID(organizationId)).
+		SetTemplate(template).
+		Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 43 - 11
internal/types/types.go

@@ -802,17 +802,18 @@ type ContactInfo struct {
 	// 组织ID
 	OrganizationId *uint64 `json:"organizationId,optional"`
 	// 是否在黑名单中
-	IsInBlockList *bool   `json:"isInBlockList,optional"`
-	Ctype         *uint64 `json:"ctype,optional"`
-	Cname         *string `json:"cname,optional"`
-	Cage          *int    `json:"cage,optional"`
-	Carea         *string `json:"carea,optional"`
-	Cbirthday     *string `json:"cbirthday,optional"`
-	Cbirtharea    *string `json:"cbirtharea,optional"`
-	CidcardNo     *string `json:"cidcardNo,optional"`
-	Ctitle        *string `json:"ctitle,optional"`
-	Cc            *string `json:"cc,optional"`
-	Phone         *string `json:"phone,optional"`
+	IsInBlockList *bool                  `json:"isInBlockList,optional"`
+	Ctype         *uint64                `json:"ctype,optional"`
+	Cname         *string                `json:"cname,optional"`
+	Cage          *int                   `json:"cage,optional"`
+	Carea         *string                `json:"carea,optional"`
+	Cbirthday     *string                `json:"cbirthday,optional"`
+	Cbirtharea    *string                `json:"cbirtharea,optional"`
+	CidcardNo     *string                `json:"cidcardNo,optional"`
+	Ctitle        *string                `json:"ctitle,optional"`
+	Cc            *string                `json:"cc,optional"`
+	Phone         *string                `json:"phone,optional"`
+	CustomFields  []ContactFieldTemplate `json:"customFields,optional"`
 }
 
 // The response data of label information | Label信息
@@ -907,6 +908,37 @@ type LabelRelationshipInfoResp struct {
 	Data LabelRelationshipInfo `json:"data"`
 }
 
+type ContactFieldTemplateOptions struct {
+	Label *string `json:"label,optional"`
+	Value *string `json:"value,optional"`
+}
+
+type ContactFieldTemplate struct {
+	Type    *string                       `json:"type,optional"`
+	Id      *string                       `json:"id,optional"`
+	Label   *string                       `json:"label,optional"`
+	Options []ContactFieldTemplateOptions `json:"options,optional"`
+	Value   []string                      `json:"value,optional"`
+}
+
+// swagger:model ContactFieldTemplateInfo
+type ContactFieldTemplateInfo struct {
+	BaseIDInfo
+	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Status *uint8 `json:"status,optional"`
+	// 组织ID
+	OrganizationId *uint64                `json:"organizationId,optional"`
+	Template       []ContactFieldTemplate `json:"template,optional"`
+}
+
+// Contact information response | Contact信息返回体
+// swagger:model ContactFieldTemplateInfoResp
+type ContactFieldTemplateInfoResp struct {
+	BaseDataInfo
+	// Contact information | Contact数据
+	Data []ContactFieldTemplate `json:"data"`
+}
+
 type LoginQRStatus struct {
 	// 登陆二维码
 	QRCode string `json:"qRCode,optional"`